CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to CCS Technical Support

Composite PPM to UART
Goto page 1, 2  Next
 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
oxxyfx



Joined: 24 May 2007
Posts: 97

View user's profile Send private message

Composite PPM to UART
PostPosted: Wed Nov 10, 2010 10:40 am     Reply with quote

Hello,

I am working on a code to convert the composite PPM signal into uart data. The composite PPM signal looks something like this:

10ms high, 0.2ms low, 1-2ms high, 0.2ms low, 1-2ms high, 0.2ms low..... 1-2ms high, 0.2ms low, 10ms high

The signal repeats itself every 20-22.5ms.

The number of channels can vary, I wrote a little code to try to convert this signal to serial (UART). There are 3 values to be sent for each pulse width. 255 is the starting character, x is the number of the channel and y is the pulse value.

I am trying to do this on a PIC12F629.

I have spent several days trying to figure out the best way to do this. Originally I counted numbers between the two 0.2ms drops and when I had the number I sent it out to UART. I was getting results, but the values were changing which lead me to believe that sending out to UART it takes time and the 0.2ms is not enough for this, so when it comes back trying to count the next one, it is already on the following pulse.

For that reason I rewrote the code using Timer0 and since then my code is not running. I know this for fact because I have an LED connected to the test circuit to flash a few times when the code starts running - but this time it does not flash.

I wonder what am I doing wrong here. I set the timer0 to overflow every 3.2ms, this helps me find the long 10ms waits and ind the first pulse.

Here is the code:


Code:

#include <12F629.h>
#device ICD=true

#FUSES NOWDT                    //No Watch Dog Timer
#FUSES INTRC_IO                 //Internal RC Osc, no CLKOUT
#FUSES NOCPD                    //No EE protection
#FUSES NOPROTECT                //Code not protected from reading
#FUSES MCLR                     //Master Clear pin enabled
#FUSES NOPUT                    //No Power Up Timer
#FUSES NOBROWNOUT               //No brownout reset
#FUSES BANDGAP_HIGH         
#use delay(clock=4000000)
#use rs232(baud=57600,parity=N,xmit=PIN_A4,rcv=PIN_A5,bits=8)


Code:

#include "C:\PPM to serial converter.h"
#include <stdlib.h>

#define PPMIN PIN_A2
#define LED PIN_A5


int serval[11];
int chcnt, i, j, t1o;

#int_RTCC
void  RTCC_isr(void)
{
   t1o = 1;
}

Void Chnum(){

      chcnt = 0;
      j = 0;
      While(input(PPMIN)) {};
      While(true){
         While(!input(PPMIN));
         chcnt++;
         While(input(PPMIN)){
            If (t1o) {
               Break;
               j = 1;
            }
            If (j == 1) Break;
         }
      chcnt = chcnt - 1;
      }
}


void main()
{

   setup_timer_0(RTCC_INTERNAL|RTCC_DIV_64);
   setup_comparator(NC_NC_NC_NC);
   enable_interrupts(INT_RTCC);
   enable_interrupts(GLOBAL);
   chcnt = j = t1o = 0;
   Delay_ms(500); 
   Output_high(LED);
   Delay_ms(500);
   Output_low(LED);
   
   While(True){
      If (!Input(PPMIN)){
         While(!Input(PPMIN)){};
      }
      Else{

         While(Input(PPMIN)){
            If (t1o) {
               j = 1;
               break;
            }
         }
      }
      If (j == 1) {
         t1o = 0;
         Break;
      }
   }
       
   Chnum();
   While(input(PPMIN)){};
   For (i=1; i<=chcnt; i++){
        While(!input(PPMIN)){}
        set_timer0(0);
        While(input(PPMIN)){}
        serval[i] = get_timer0();
   }

   While (true){
         For (i=1; i<=chcnt; i++){
               printf("255,%u,%u\n\r",i,serval[i]);
         }
         While(input(PPMIN)) {};         
         For (i=1; i<=chcnt; i++){
               While(!input(PPMIN)){}
               set_timer0(0);
               While(input(PPMIN)){}
               serval[i]=get_timer0();
             
         }
   }
}
Ttelmah



Joined: 11 Mar 2010
Posts: 19513

View user's profile Send private message

PostPosted: Wed Nov 10, 2010 10:55 am     Reply with quote

You can't do this with the UART. You potentially could do it with the SPI.
Problem is that a UART character will always have a 'start bit'. This is low, so at 57600bps, the longest 'high' pulse you can generate, would be 8/57600th second, followed by a 1/57600th second low pulse. In either case, you _would_ need a genuine hardware UART or SPI. You are currently using a software 'emulation' of a UART, and the pulses with therefore stop, while the next value is loaded from memory...

Best Wishes
oxxyfx



Joined: 24 May 2007
Posts: 97

View user's profile Send private message

PostPosted: Wed Nov 10, 2010 11:21 am     Reply with quote

Thank you, So if I change the PIC to one which has hardware UART like 16F88 then do I have chances to get this right? I am not sure I can do this with SPI, I never actually worked with SPI. Besides on the other side there will be a receiver which would have to convert the UART back to pulses....
oxxyfx



Joined: 24 May 2007
Posts: 97

View user's profile Send private message

PostPosted: Wed Nov 10, 2010 3:01 pm     Reply with quote

Now this really freaks me out. I replaced the PIC in the above project with a 16F87. I rewrote the code to match this and I see it is not running. I am not sure why. Then I started commenting things out to see what might make this code not run. I cut it down to this:

Code:

#include <16F87.h>
#device ICD=True

#FUSES NOWDT                    //No Watch Dog Timer
#FUSES INTRC_IO                 //Internal RC Osc, no CLKOUT
#FUSES NOPUT                    //No Power Up Timer
#FUSES MCLR                     //Master Clear pin enabled
#FUSES NOBROWNOUT               //No brownout reset
#FUSES NOLVP                    //No low voltage prgming, B3(PIC16) or B5(PIC18) used for I/O
#FUSES NOCPD                    //No EE protection
#FUSES NOWRT                    //Program memory not write protected
#FUSES NODEBUG                  //No Debug mode for ICD
#FUSES NOPROTECT                //Code not protected from reading
#FUSES FCMEN                    //Fail-safe clock monitor enabled
#FUSES IESO                     //Internal External Switch Over mode enabled

#use delay(clock=4000000)
#use rs232(baud=9600,parity=N,xmit=PIN_B5,rcv=PIN_B2,bits=8,errors)



Code:
#include "C:\Users\zoltan\Documents\Pic Projects\Servosomething\PPM-uart converter 16F87.h"

#define PPMIN PIN_B4
#define LED PIN_A1

int16 serval[11];
int chcnt, i, j, k, t1o, s, signal;

void main()
{

   setup_spi(SPI_SS_DISABLED);
   setup_timer_0(RTCC_INTERNAL|RTCC_DIV_1);
   setup_timer_1(T1_INTERNAL|T1_DIV_BY_1);
   setup_timer_2(T2_DISABLED,0,1);
//   setup_comparator(NC_NC_NC_NC);
//   setup_vref(FALSE);
   setup_oscillator(OSC_4MHZ|OSC_INTRC);
   enable_interrupts(INT_RTCC);
   enable_interrupts(INT_RB);
   enable_interrupts(GLOBAL);
   port_b_pullups(true);
   
   chcnt = j = t1o  = k = i = s = 0;
   signal = 1;


   Output_high(LED);
   
/*   for (s=0; s<5; s++){
        Delay_ms(500); 
        Output_high(LED);
        Delay_ms(500);
        Output_low(LED);
   }
*/ 


I am using an ICD3 programmer debugger connected with USB to the computer and prgramming the PIC through this with the debug module enabled.

As you can see above when all the delay_ms functions are commented out the code will run, it will turn the LED on. If I enable the For cylce and use the Delays the code will not work. I am not sure why...

Another thing - when I tried to change the boud rate to 38400 I get an error that the baud rate is out of bound...
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Wed Nov 10, 2010 3:09 pm     Reply with quote

Quote:
void main()
{

setup_spi(SPI_SS_DISABLED);

Don't do this on the 16F87. The hardware UART pins are multiplexed
with the SPI pins. If you use the statement above, it actually enables the
SPI module. The compiler sets the TRIS for that module, and this totally
messes up the hardware UART's TRIS requirements. Delete the line
above.

Quote:
enable_interrupts(INT_RTCC);
enable_interrupts(INT_RB);
enable_interrupts(GLOBAL);

Don't enable interrupts when you have no interrupt handler routines.
The program will crash. Delete all the lines above.
oxxyfx



Joined: 24 May 2007
Posts: 97

View user's profile Send private message

PostPosted: Wed Nov 10, 2010 3:40 pm     Reply with quote

Thank you. I modified the code this way:

Code:

#include "C:\Users\zoltan\Documents\Pic Projects\Servosomething\PPM-uart converter 16F87.h"

#define PPMIN PIN_B4
#define LED PIN_A1

int16 serval[11];
int chcnt, i, j, k, t1o, s, signal;

void main()
{

   setup_timer_0(RTCC_INTERNAL|RTCC_DIV_64);
   setup_timer_1(T1_INTERNAL|T1_DIV_BY_1);
   setup_timer_2(T2_DISABLED,0,1);
//   setup_comparator(NC_NC_NC_NC);
//   setup_vref(FALSE);
   setup_oscillator(OSC_4MHZ|OSC_INTRC);
   port_b_pullups(true);
   
   chcnt = j = t1o  = k = i = s = 0;
   signal = 1;


   Output_high(LED);
   


and the LED turns on. However if the code looks like this:

Code:

#include "C:\Users\zoltan\Documents\Pic Projects\Servosomething\PPM-uart converter 16F87.h"

#define PPMIN PIN_B4
#define LED PIN_A1

int16 serval[11];
int chcnt, i, j, k, t1o, s, signal;

void main()
{

   setup_timer_0(RTCC_INTERNAL|RTCC_DIV_64);
   setup_timer_1(T1_INTERNAL|T1_DIV_BY_1);
   setup_timer_2(T2_DISABLED,0,1);
//   setup_comparator(NC_NC_NC_NC);
//   setup_vref(FALSE);
   setup_oscillator(OSC_4MHZ|OSC_INTRC);
   port_b_pullups(true);
   
   chcnt = j = t1o  = k = i = s = 0;
   signal = 1;


   Output_high(LED);
   Delay_ms(1000);


the LED never turns on. What am I missing?
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Wed Nov 10, 2010 3:54 pm     Reply with quote

Post a complete test program in one post. I don't mean to add new code.
I mean, post the code that you have, but with the #include, #fuses,
#use delay(), etc., as part of the complete test program.
Then I can copy and paste it all into MPLAB and compile and test.

Also, post your compiler version. It's a 4 digit number (only 4 digits),
in this format: x.xxx
It's given at the top of the .LST file in your project directory. The .LST
file will be there after a successful compilation.
oxxyfx



Joined: 24 May 2007
Posts: 97

View user's profile Send private message

PostPosted: Wed Nov 10, 2010 4:21 pm     Reply with quote

Here it is the one which does not turn on the LED:

Code:


#include <16F87.h>
#device ICD=True

#FUSES NOWDT                    //No Watch Dog Timer
#FUSES INTRC_IO                 //Internal RC Osc, no CLKOUT
#FUSES NOPUT                    //No Power Up Timer
#FUSES MCLR                     //Master Clear pin enabled
#FUSES NOBROWNOUT               //No brownout reset
#FUSES NOLVP                    //No low voltage prgming, B3(PIC16) or B5(PIC18) used for I/O
#FUSES NOCPD                    //No EE protection
#FUSES NOWRT                    //Program memory not write protected
#FUSES NODEBUG                  //No Debug mode for ICD
#FUSES NOPROTECT                //Code not protected from reading
#FUSES FCMEN                    //Fail-safe clock monitor enabled
#FUSES IESO                     //Internal External Switch Over mode enabled

#use delay(clock=4000000)
#use rs232(baud=9600,parity=N,xmit=PIN_B5,rcv=PIN_B2,bits=8,errors)


#define PPMIN PIN_B4
#define LED PIN_A1

int16 serval[11];
int chcnt, i, j, k, t1o, s, signal;

void main()
{

   setup_timer_0(RTCC_INTERNAL|RTCC_DIV_64);
   setup_timer_1(T1_INTERNAL|T1_DIV_BY_1);
   setup_timer_2(T2_DISABLED,0,1);
//   setup_comparator(NC_NC_NC_NC);
//   setup_vref(FALSE);
   setup_oscillator(OSC_4MHZ|OSC_INTRC);
   port_b_pullups(true);
   
   chcnt = j = t1o  = k = i = s = 0;
   signal = 1;


   Output_high(LED);
   Delay_ms(1000);
}


compiler version is 4.093
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Wed Nov 10, 2010 5:26 pm     Reply with quote

Try running a simple LED blinker program without all that other stuff.
If it doesn't work, then try it with the LED on some different pins.
Code:

#include <16F87.h>
#fuses INTRC_IO,NOWDT,PUT,BROWNOUT,NOLVP
#use delay(clock=4000000)

#define LED PIN_A1

//============================
void main()
{

while(1)
  {
   output_high(LED);
   delay_ms(500);
   output_low(LED);
   delay_ms(500);
  }

}
oxxyfx



Joined: 24 May 2007
Posts: 97

View user's profile Send private message

PostPosted: Wed Nov 10, 2010 7:35 pm     Reply with quote

Ok, that works.
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Wed Nov 10, 2010 7:51 pm     Reply with quote

Use that program as the basis for future programs.
oxxyfx



Joined: 24 May 2007
Posts: 97

View user's profile Send private message

PostPosted: Thu Nov 11, 2010 6:34 am     Reply with quote

Well I tried that. However as soon as I start adding other lines of code - or as a matter of fact just simply enabling the RS232 - it stops again. IS it possible something is wrong with this chip?
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Thu Nov 11, 2010 12:18 pm     Reply with quote

Try a simple test program for rs-232, as shown below. The PIC board
must have a Max232-type chip connected between the UART pins and
the DB-9 connector. The board must be connected to a PC which is
running a terminal program such as TeraTerm. With this program, if you
type characters into the terminal program, they will go to the PIC which
will send them back to the PC, where they will be displayed in the terminal
window.
Code:

#include <16F87.h>
#fuses INTRC_IO,NOWDT,PUT,BROWNOUT,NOLVP
#use delay(clock=4000000)
#use rs232(baud=9600, xmit=PIN_B5, rcv=PIN_B2, ERRORS)

//============================
void main()
{
int8 c;

while(1)
  {
   c = getc();   // Get char from PC
   putc(c);  // Send it back to the PC
  }

}
oxxyfx



Joined: 24 May 2007
Posts: 97

View user's profile Send private message

PostPosted: Thu Nov 11, 2010 3:53 pm     Reply with quote

Well that works on it's own as well. Only one thing to be noted though - if I try to change the baud rate to 38400 I get an error when I try to compile it:

Baud out of range

Why is that?
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Thu Nov 11, 2010 3:59 pm     Reply with quote

Quote:
- if I try to change the baud rate to 38400 I get an error when I try to compile it:

Baud out of range

Why is that?

See this thread about the Picbaud program:
http://www.ccsinfo.com/forum/viewtopic.php?t=37250
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Goto page 1, 2  Next
Page 1 of 2

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group