View previous topic :: View next topic |
Author |
Message |
_panzerschreck_
Joined: 06 Feb 2012 Posts: 6
|
RF Serial Communication Problems |
Posted: Mon Feb 06, 2012 7:53 am |
|
|
Hi everyone
I am trying to make a communication between two pics (16f877a) over 433mhz rf modules and uart. One pic takes data from computer (I am using pickit's UART tool) processes it and transmits it to the other pic.
Baud rate is set to 1200 and errors are enabled in #use rs232 code part.
When I send the data over a cable (from one pic's tx to others rx) it works perfectly. However when it comes to the rf wireless modules, I have to send a char approximately 10 times in uart tool software to receive the data in the other side. I am using the preamble data and 2 byte pass in order not to be affected by the noise.
There are some possibilities that come into my mind but I am not sure, so I need help
1.) Rf data should be DC balanced. So either using manchester coding or sending bytes including equal number of 0's and 1's should work. Since I don't know how to implement manchester coding, I preferred the second one.
2.) Since the RX buffer is only 1 byte, I might be missing some data in the receiver side. But I do not know how to overcome this.
3.) There are too many processes in the interrupt routine so I may be missing some data in the receiver side.
4.) Other problems which I could not figure out
CODE:
TRANSMITTER SIDE:
Code: | #include "C:\Users\Desktop\PC RS232\main.h"
char temp;
int i;
#int_rda
void rx_interrupt ()
{
disable_interrupts(int_rda);
temp=getc(); //GET THE DATA AND STORE IT INTO TEMP VARIABLE
switch (temp) //CONVERSION PROCESS FOR THE DC BALANCED ISSUE I HAVE MENTIONED ABOVE
{
case 'w':
temp='f';
break;
case 'a':
temp='e';
break;
case 's':
temp='j';
break;
case 'd':
temp='i';
break;
case 'q':
temp='S';
break;
case 'e':
temp='V';
break;
case 't':
temp='Z';
break;
case 'g':
temp='Y';
break;
case 'b':
temp='5';
break;
case 'n':
temp='+';
break;
case 'h':
temp='3';
break;
case 'l':
temp='6';
break;
}
putc(0x55); //UUUUU 01010101 PREAMBLE DATA
putc(0x55);
putc(0x55);
putc(0x55);
putc(0x55);
putc('K'); //PASSWORD 1st BYTE
putc('M'); //PASSWORD 2nd BYTE
putc(temp); //1 BYTE DATA TO BE SENT
}
void main()
{
setup_adc_ports(NO_ANALOGS);
setup_adc(ADC_OFF);
setup_psp(PSP_DISABLED);
setup_spi(SPI_SS_DISABLED);
setup_timer_0(RTCC_INTERNAL|RTCC_DIV_1);
setup_timer_1(T1_DISABLED);
setup_timer_2(T2_DISABLED,0,1);
setup_comparator(NC_NC_NC_NC);
setup_vref(FALSE);
enable_interrupts(GLOBAL);
enable_interrupts(int_rda);
// TODO: USER CODE!!
delay_ms(1000);
while(1) //INFINITE LOOP
{
enable_interrupts(int_rda);
}
}
|
RECEIVER SIDE:
Code: | #include "C:\Users\Desktop\PC RS232\ALICI\2\main.h"
#use fast_io(b)
#define use_portb_lcd TRUE
#include <lcd.c>
//DEFINITIONS
#define trig pin_D0
#define echo pin_D1
#define pwm1 pin_C1
#define pwm2 pin_C2
#define mot11 pin_A0
#define mot12 pin_A1
#define mot21 pin_A2
#define mot22 pin_A3
//FUNCTIONS
void sol_ileri_20(); //LEFT MOTOR FWD 20% PWM
void sol_geri_20(); //LEFT MOTOR REV 20% PWM
void sag_ileri_20(); //RIGHT MOTOR FWD 20% PWM
void sag_geri_20(); //RIGHT MOTOR REV 20% PWM
void sol_bos();
void sag_bos();
void ileri ();
void geri ();
int sonar ();
//VARIABLES
int okumamodu =0;
char temp;
int temp1=0;
int duty=50;
int16 distance, time;
#int_rda
void rx_interrupt ()
{
disable_interrupts(int_rda);
if(okumamodu==0) //COUNTING THE VARIABLE OKUMAMODU AND IF IT REACHES 3 I READ THE ACTUAL DATA
{
temp=getc();
if(temp=='K') //PASS 1.BYTE CONTROL
{okumamodu++;
}
else okumamodu=0;
}
if(okumamodu==1)
{
temp=getc();
if(temp=='M') //PASS 2.BYTE CONTROL
{okumamodu++;
}
else okumamodu=0;
}
if(okumamodu==2) //START READING DATA AND MAKE ASSIGNMENTS TO USE IN FUNCTIONS
{
temp=getc();
if(temp=='f') //Corresponding char for w
{
temp1=119; //ascii for w
okumamodu=0;
}
else if (temp=='j') //Corresponding char for s
{
temp1=115; //ascii for s
okumamodu=0;
}
else if (temp=='e') //Corresponding char for a
{
temp1=97; //ascii for a
okumamodu=0;
}
else if (temp=='i') //Corresponding char for d
{
temp1=100; //ascii for d
okumamodu=0;
}
else if (temp=='5') //Corresponding char for b
{
temp1=98; //ascii for b
okumamodu=0;
}
else if (temp=='Z') //Corresponding char for t
{
temp1=116; //ascii for t
okumamodu=0;
}
else if (temp=='Y') //Corresponding char for g
{
temp1=103; //ascii for g
okumamodu=0;
}
else if (temp=='S') //Corresponding char for q
{
temp1=113; //ascii for q
okumamodu=0;
}
else if (temp=='V') //Corresponding char for e
{
temp1=101; //ascii for e
okumamodu=0;
}
else if (temp=='3') //Corresponding char for h
{
temp1=104; //ascii for h
okumamodu=0;
}
else if (temp=='6') //Corresponding char for l
{
temp1=108; //ascii for l
okumamodu=0;
}
okumamodu=0;
}
if(okumamodu==80)
okumamodu=0;
}
void main()
{
setup_adc_ports(NO_ANALOGS);
setup_adc(ADC_OFF);
setup_psp(PSP_DISABLED);
setup_spi(SPI_SS_DISABLED);
setup_timer_0(RTCC_INTERNAL|RTCC_DIV_1);
setup_timer_1(T1_INTERNAL|T1_DIV_BY_8); //USED FOR SONAR
setup_timer_2(T2_DIV_BY_16,170,1); //USED FOR PWM
setup_ccp1(CCP_PWM);
setup_ccp2(CCP_PWM);
set_pwm1_duty(100);
set_pwm2_duty(100);
setup_comparator(NC_NC_NC_NC);
setup_vref(FALSE);
set_tris_b(0x00);
lcd_init();
duty=50;
delay_ms(1000);
// TODO: USER CODE!!
enable_interrupts(GLOBAL);
enable_interrupts(int_rda);
while(1)
{
enable_interrupts(int_rda);
switch (temp1)
{
case (119): //CALLING FUNCTIONS FOR THE temp1 VARIABLE FROM THE RX INTERRUPT
duty=100;
ileri();
break;
case (115):
duty=100;
geri();
break;
case (97):
duty=75;
sag_ileri_20();
sol_geri_20();
break;
case (100):
duty=75;
sol_ileri_20();
sag_geri_20();
break;
case (98):
duty=10;
sag_bos();
sol_bos();
break;
}
}
}
//FUNCTIONS
void ileri ()
{
set_pwm1_duty(duty);
set_pwm2_duty(duty);
output_low(mot11);
output_high(mot12);
output_low(mot21);
output_high(mot22);
}
void geri ()
{
set_pwm1_duty(duty);
set_pwm2_duty(duty);
output_high(mot11);
output_low(mot12);
output_high(mot21);
output_low(mot22);
}
void sol_ileri_20()
{
set_pwm1_duty(duty);
output_low(mot11);
output_high(mot12);
}
void sol_geri_20()
{
set_pwm1_duty(duty);
output_high(mot11);
output_low(mot12);
}
void sag_ileri_20()
{
set_pwm2_duty(duty);
output_low(mot21);
output_high(mot22);
}
void sag_geri_20()
{
set_pwm2_duty(duty);
output_high(mot21);
output_low(mot22);
}
void sol_bos()
{
set_pwm1_duty(duty);
output_low(mot11);
output_low(mot12);
}
void sag_bos()
{
set_pwm2_duty(duty);
output_low(mot21);
output_low(mot22);
}
|
.h FILE:
Code: | #include <16F877A.h>
#device adc=8
#FUSES NOWDT //No Watch Dog Timer
#FUSES HS //High speed Osc (> 4mhz for PCM/PCH) (>10mhz for PCD)
#FUSES NOPUT //No Power Up Timer
#FUSES NOPROTECT //Code not protected from reading
#FUSES NODEBUG //No Debug mode for ICD
#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
#use delay(clock=20000000)
#use rs232(baud=1200,parity=N,xmit=PIN_C6,rcv=PIN_C7,bits=8,errors)
|
|
|
|
ckielstra
Joined: 18 Mar 2004 Posts: 3680 Location: The Netherlands
|
|
Posted: Mon Feb 06, 2012 8:59 am |
|
|
I have no experience with the 433MHz modules but on this forum you will find many discussions from people having troubles with them. Some modules are better quality than others, is yours an AM or FM type?
Posting the brand and type number of your modules could give you more hints & tips. Even better, provide a link to the datasheet.
A few issues:
For every character you receive from the PC you are sending 8 characters. The PIC hardware can only buffer up to three characters in the receive buffer, so make sure the PC is sending data with long intervals between the characters or you will overflow the PIC UART and loose data. At 1200 baud that is at least 8 ms between the characters.
Code: | setup_spi(SPI_SS_DISABLED); | This is an illegal configuration and a long known error in the CCS setup wizard. Should be changed to:
Code: | disable_interrupts(int_rda); | There is no need to disable the interrupts inside the interrupt handler as this has already been done by the PIC hardware. I'm glad you didn't make the error of enabling the global interrupts again inside the interrupt handler. After removing this line you can also remove the enabling inside the main loop.
Quote: | ...
else if (temp=='V') //Corresponding char for e
{
temp1=101; //ascii for e
okumamodu=0;
}
else if (temp=='3') //Corresponding char for h
{
temp1=104; //ascii for h
okumamodu=0;
}
else if (temp=='6') //Corresponding char for l
{
temp1=108; //ascii for l
okumamodu=0;
}
okumamodu=0; | You definitely like to make sure okumamodu becomes zero...
A few more links on the 433 MHz modules:
http://www.ccsinfo.com/forum/viewtopic.php?p=144720
http://www.ccsinfo.com/forum/viewtopic.php?p=891 |
|
|
Mike Walne
Joined: 19 Feb 2004 Posts: 1785 Location: Boston Spa UK
|
Comms problem |
Posted: Mon Feb 06, 2012 9:21 am |
|
|
You've not told us which RF module you're using, or how it's connected.
I've used two different types of 433MHz devices, and was amazed at the difficulties I had with the second more modern one!
Your answer is built into the question. Write a short simple program to test your RF link alone (ignore everything else).
Repeatedly send a short message over the link, check with a 'scope that you can see what you're expecting, then proceed from there.
If you are well within the quoted receive range, with proper antennae, missing data should be a rarety.
Mike |
|
|
_panzerschreck_
Joined: 06 Feb 2012 Posts: 6
|
|
|
Gabriel
Joined: 03 Aug 2009 Posts: 1067 Location: Panama
|
|
Posted: Mon Feb 06, 2012 10:26 am |
|
|
the RF modules that you are using will not work.
Unless you do your own error checking routines, with paritys and checksums and .... still it will only work partially.
the reciever itself has autogain... so it produces uncontrollable noise on its output... and your UART will think its data... and your system will think its garbage.
these modules work best with pulse position or pulse width comunications... (like the one used in wireless doorbels and IR remotes)... not standard serial.
those modules are not a "virtual wire"...
try the Bluesmirf from sparkfun.... that is literaly plug and play... flawless. or an RFM22 module....
ive used succefully your modules to interface with other wirelss mass produced devices and the Bluesmirf for personal proyects... _________________ CCS PCM 5.078 & CCS PCH 5.093 |
|
|
_panzerschreck_
Joined: 06 Feb 2012 Posts: 6
|
|
Posted: Mon Feb 06, 2012 10:44 am |
|
|
I guess you are right, modules are not good for the applications that is intolerable for data loss. Is there any way to work with these (i.e. intensive coding etc) or should I buy a new pair? Or how can I understand which module is good for this kind of applications in case for future choices.
I have tried an application to test the modules now.
On transmitter side, I have sent K, L for password bytes and numbers from 0 to 9 in an infinite loop.
Code: |
putc('K'); putc('L'); putc('0');
putc('K'); putc('L'); putc('1');
putc('K'); putc('L'); putc('2');
putc('K'); putc('L'); putc('3');
putc('K'); putc('L'); putc('4');
putc('K'); putc('L'); putc('5');
putc('K'); putc('L'); putc('6');
putc('K'); putc('L'); putc('7');
putc('K'); putc('L'); putc('8');
putc('K'); putc('L'); putc('9');
|
On receiver side I have controlled K and L bytes and if they are satisfied I send the data to the serial port to read.
Code: |
int okumamodu=0;
int temp;
#int_rda
void rx_interrupt ()
{
if(okumamodu==0)
{
temp=getc();
if(temp=='K')
{okumamodu++;
}
else okumamodu=0;
}
if(okumamodu==1)
{
temp=getc();
if(temp=='L')
{okumamodu++;
}
else okumamodu=0;
}
if(okumamodu==2)
{
putc(getch());
okumamodu=0;
}
}
|
UNFORTUNATELY
The receiver misses some data and it explains why I should have to repeat sending the same data repeatedly which is undesired. This is the log file that is received from serial port which is supposed to be and it should continue forever
However what I got is: (with a lot of missing data)
Code: | 1357913579135791357913579
135791357913579135791357913579
135791357913579135791357913579
135791357913579135791357913579
135791357913579135791357913579
135791357913579135791357901234
567890123456802468012357913579
135791356789012345678901234567
913579123456789012345679123456
791234567912345679123456791234
567912345680123456791235791357
913579135791357912345679123456
791357913579135791357913567912
345680234567913579135791357912
345680123579135791356789012345
680246890123456789123456802468
023456789012345679135791357912
345679135791234567913579123456
802356801234567913579135791234
567913579135791357913579135791
234567890123456791357912345679
135791357913579123456791357913
567890123456791357912345678901
234568024689012345678901246802
456789012345679135791234568012
356802468012345680123456791234
568012345680123456791234568012
345678901234567890123456789012
345678901234567912345679123456
791234567890123456789012345678
901234567801235791345678901234
567802468023456789012345680246
801234567802468012356802356801
235791356789012345678901234568
023568024680235680246801234568
024680123456791357913579135791
234567913579135791357913579135
791356791234567913579135790123
456791357913579123579135791357
913579123456791357912345679135
791234567912345679123457913579
123456791235791357913456791357
913579135791357913579135791357
913579135791357913579135791357
913579135791357913579135791357
913579135791357913579135791357
913579135791357913579135791357
912345679135791357913579135791
357913579135791357913579135791
357913579135791357913579135791
357913579135791357913579135791
35791357 |
|
|
|
_panzerschreck_
Joined: 06 Feb 2012 Posts: 6
|
|
Posted: Mon Feb 06, 2012 11:05 am |
|
|
CORRECTION:
However when I send preamble data first (putc('U')) five times before sending any data, it works flawlessly. I couldn't figure out what is the problem. On robot, it causes a large delay, but here I can see the characters are sent correctly. (But I encounter some missing data also, not correct all the time)
Quote: | 01234567890123456789
01234567890123456789
01234567890123456789
012345673456789
01234567890123456789
01234567890123456789
01234567890123456789
01234567890123456789
01234567890123456789
01234567890123456789
01234567890123456789
01234567890123456789
01234567890123456789
01234567890123456789
01234567890123456789
01234567890123456789
01234567890123456789
01234567890123456789
01234567890123456789
01234567890123456789
01234567890123456789
01234567890123456789
01234567890123456789
01234567890123456789
01234567890123456789
01234567890123456789
01234567890123456789
01234567890123456789
01234567890123456789
01234567890123456789
012345678901 |
HOWEVER
when I do not put chars directly, but I send putc(getc()) which is received from the computer, I encounter the delay issue and some unidentified characters again.
What is wrong with these modules or program? |
|
|
Gabriel
Joined: 03 Aug 2009 Posts: 1067 Location: Panama
|
|
Posted: Mon Feb 06, 2012 12:13 pm |
|
|
Sending the 'U' character before the actual data a few times actually helps you because it gives the receiver a chance to properly adjust its gain before receiving data.
Its better if you send char 0XAA before as it has equal amount of hi/lo transitions.
These modules tend to like having the same number of transitions.
First test your communications using a wired connection, then move on to RF. _________________ CCS PCM 5.078 & CCS PCH 5.093 |
|
|
_panzerschreck_
Joined: 06 Feb 2012 Posts: 6
|
|
Posted: Mon Feb 06, 2012 1:32 pm |
|
|
Gabriel wrote: | Sending the 'U' character before the actual data a few times actually helps you because it gives the receiver a chance to properly adjust its gain before receiving data.
Its better if you send char 0XAA before as it has equal amount of hi/lo transitions.
These modules tend to like having the same number of transitions.
First test your communications using a wired connection, then move on to RF. |
As I mentioned before, I have tested it with cable communication and it works well without any loss. I just get some weird characters when I use rf modules even if I use preamble data and password characters.
By the way, do I need to put any delays for transmitter side when it is set to 1200 baud rate? |
|
|
|