|
|
View previous topic :: View next topic |
Author |
Message |
oxxyfx
Joined: 24 May 2007 Posts: 97
|
Composite PPM to UART |
Posted: Wed Nov 10, 2010 10:40 am |
|
|
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: 19499
|
|
Posted: Wed Nov 10, 2010 10:55 am |
|
|
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
|
|
Posted: Wed Nov 10, 2010 11:21 am |
|
|
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
|
|
Posted: Wed Nov 10, 2010 3:01 pm |
|
|
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
|
|
Posted: Wed Nov 10, 2010 3:09 pm |
|
|
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
|
|
Posted: Wed Nov 10, 2010 3:40 pm |
|
|
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
|
|
Posted: Wed Nov 10, 2010 3:54 pm |
|
|
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
|
|
Posted: Wed Nov 10, 2010 4:21 pm |
|
|
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
|
|
Posted: Wed Nov 10, 2010 5:26 pm |
|
|
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
|
|
Posted: Wed Nov 10, 2010 7:35 pm |
|
|
Ok, that works. |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Wed Nov 10, 2010 7:51 pm |
|
|
Use that program as the basis for future programs. |
|
|
oxxyfx
Joined: 24 May 2007 Posts: 97
|
|
Posted: Thu Nov 11, 2010 6:34 am |
|
|
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
|
|
Posted: Thu Nov 11, 2010 12:18 pm |
|
|
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
|
|
Posted: Thu Nov 11, 2010 3:53 pm |
|
|
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
|
|
|
|
|
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
|