|
|
View previous topic :: View next topic |
Author |
Message |
cykrus
Joined: 01 Oct 2012 Posts: 7
|
PIC16f628 radio link |
Posted: Mon Oct 01, 2012 12:13 pm |
|
|
Hello all,
I am very new to the micro-controller world so bear with me.
I want to make a remote control to be able to send data between t PIC's (16f628). I know that there are already products out there (i have tested h12e/d rd600 d/e and they work great). My scope is to learn and play with PIC and not to use already made products
Before this project i did the "flash led" type of tutorials to learn a little bit about PIC's.
Environment setup :
I have 2 16f628 pic's and a set of 434 MHz RX/TX. I also have a max 232
connected to my serial port and receiver PIC in order to be able to debug data. At the hardware level have no problems setting it up.
Software setup:
The idea is that I want to be able to send a data package (coming from input pins) from PIC1(connected to the TX 434) to PIC2(connected to rx 434).
And here comes the code I have already wrote. Again ... this is my first real program so bear with me :-)
DECODER
Code: |
#include <16F628.h>
#fuses INTRC_IO, NOLVP, NOWDT, PUT, BROWNOUT
#use delay(clock=4000000)
#use rs232(baud=19200, xmit=pin_B2, rcv=pin_B1)
void display_binary(int c){
int i;
i = 8;
do
{
if( c & 0x01 )
{ putc('1'); }
else
{ putc('0'); }
c >>= 1; i--;
} while(i);
}
int sync(int a){
int found;
int string;
int bit;
int original;
original = a;
do{
a = original;
found = 0; // found the string
string = 0x00;
do{
if( input(PIN_A0) ){
bit = 0x01;
}
else{
bit = 0x00;
}
string = string | bit;
string <<= 1;
if( ((a & 0x01) ^ bit ) == 0 ){ // right bit == input
a >>= 1; // shift 1 position right
}
else{
return 0; // error
}
if( a == 0x00){
found = 1;
}
delay_us(500); // wait until next bit
}while( found == 0 );
}while( found == 0 );
return 1;
}
int getdata(){
int string = 0x00;
int i;
for(i=0;i<8;i++){
string <<= 1;
if( input(PIN_A0) ){
string |= 0x01;
}
else{
string |= 0x00;
}
delay_us(500);
}
return string;
}
void main(void) {
int prev, k, i;
unsigned int data;
while(1) {
k=0; // until i get 3 time the same result
do{
i=0;
do{
if( sync(0xAB) == 1 ){
i++;
delay_us(500);
}
else{
i = 0;
}
}while(i<3);
data = getdata();
if( k > 0 && data != prev) k=1; // reset
else k++; // one more good result
prev = data; // previous result used in the next loop
}
while(k<3);
if( data == -1 ) output_high(PIN_A2);
if( data == 63 ) output_high(PIN_A1);
printf("Found %d = ", data);
display_binary(data);
printf("\r\n");
delay_ms(250);
output_low(PIN_A2);
output_low(PIN_A1);
}
}
| ENCODER
Code: |
#include <16F628.h>
#fuses INTRC_IO, NOLVP, NOWDT, PUT, BROWNOUT
#use delay(clock=4000000)
void send1(){
output_high(PIN_A0);
delay_us(500);
output_low(PIN_A0);
}
void send0(){
output_low(PIN_A0);
delay_us(500);
output_high(PIN_A0);
}
void sendbyte(int x){
int i=8;
do{
if(x & 0x01){
send1();
}
else{
send0();
}
x >>= 1;
i--;
}while(i);
}
main() {
while(true) {
if(input( PIN_B0) ){
// sync
sendbyte(0xAB);
delay_us(500);
sendbyte(0xAB);
delay_us(500);
sendbyte(0xAB);
delay_us(500);
sendbyte(0xFF);
delay_us(500);
}
else if(input( PIN_B1) ){
// sync
sendbyte(0xAB);
delay_us(500);
sendbyte(0xAB);
delay_us(500);
sendbyte(0xAB);
delay_us(500);
sendbyte(0xFC);
delay_us(500);
}
}
}
|
The idea is the encoder is sending 3 bytes (AB) as a sync (in order to align it with the RX) and then it send a byte of data depending on which pin B0 or B1 is high. The decoder searched for the 3 sync packages and then reads the byte (I'm reading it until i get 3 times the same value .. as i have experienced some errors due to radio noise i guess). Everything work so far but I'm sure it's not the perfect way to do it.
My questions are :
1. I have set a delay of 500us between bits and bytes as well. Is this correct ? What should be an optimal value ?
2. I coded 2 function for sending 1 or 0 bits. Is there another way to send directly a full byte to a pic PIN ?
2a. I have seen that in Manchester it says that 1 is 0to1 transition and 1 is 1to0 ... does this mean that for sending a 1 I should do the following code ?
Code: |
output high;
delay 250us;
output_low;
delay 250us
| How do i read this data (from port) on the other end ?
3. I have studied for 1 week a lot about the Manchester encoding, i have understood how it works but i don't know how to apply it to hardware. Meaning how to I put the bits on the PORTS and how do i read them ? What is the delay between bits ? I searched a whole week but did not find any c sample of this ... only the Manchester encoding process.
4. Is the way that I'm reading data from 434RX correct ? I have setup on both tx and rx same timing (delays between bits) and this is the way i "sync" .. is there another way do to this ?
Please feel free to correct/adjust my code and tell me what do I do wrong.
I want to learn and experimenting is for me the best way to do this.
Thanks,
Vlad |
|
|
cykrus
Joined: 01 Oct 2012 Posts: 7
|
|
Posted: Mon Oct 01, 2012 1:02 pm |
|
|
Another question just came into my mind. The way that i'm syncronising the encoder/decoder is my seting the same delay between bits. Now my question is this ... how much time does it take to execute operations between sending bits ? For example is the encoder has a code like
Code: |
output high
delay 10us
output low
delay 10us
| and the decoder has the code
Code: |
read input
delay 10us
<=== other 10 instructions come here
read input
delay 10us
| How much does it take for the "10 instructions" to execute ... can that cause a delay and with the 10us added on top the second "input" would no longer be aligned with the encoder's timing ?
How to solve this issue ... I suppose there is a way with the clock ? ... like in the so if we say "we'll meet there in 10 minutes" ... it is not so accurate as saying "we'll meet there at 2:50 PM" .. right ? |
|
|
cykrus
Joined: 01 Oct 2012 Posts: 7
|
|
Posted: Mon Oct 01, 2012 2:48 pm |
|
|
OOps ... i did some more reading and it looks like my code reinvented the wheel ))) ... sorry for that ... i just discovered ... "USART" ...
It looks like my code for sending/receiving bits is a "stoneage" version of USART ... |
|
|
asmboy
Joined: 20 Nov 2007 Posts: 2128 Location: albany ny
|
|
Posted: Mon Oct 01, 2012 7:21 pm |
|
|
Have you looked at your "manchester code on an oscilloscope ???
Your code example seems strikingly discontinuous.
My experience has been that manchester is an NRZ type of code with continuous clocking, that uses a fixed square wave time base, and encodes a 1 - as a transition in mid cycle - while a zero allows the base frequency to complete. Also known as B-FM and BI-phase encoding.
A typical manchester stream encodes continuous zeros, and punctuates the stream with a specific 1/0 sequence to begin framing of a complete set of data. One of the most famous examples of Manchester code is the Biphase SMPTE TimeCode standard. IRIG, favored by NASA in the old days is another. So for a radio link - great idea you have !!
Manchester is a useful code for data that must flow on an RF channel as it is inherently symmetric , and as such does not produce nasty frequency shift offsets. Thats is in fact why it is far superior to RS-232 for non-hardwired, data transmission. Manchester code can be passed through a variety of wireless or even recorded systems, quite nicely.
IN the old days SMPTE code and IRIG were desired because you could record them directly on magnetic tape- at with low baud rates -
recover data with no error correction typically required.
I have (unfortunately) had a bit of experience with codes of this type,
AND unless your clock frequency/ data rate is very low, you are gonna have a heap of trouble generating a smooth and reliable manchester code with ONLY a PIC ( 4mhz), at data rates of more than say 300 baud, IMHO. |
|
|
cykrus
Joined: 01 Oct 2012 Posts: 7
|
|
Posted: Tue Oct 02, 2012 2:40 pm |
|
|
So .. after another day spent on forums I got the idea. I am using the UART and I have learned about all the registers and bits for the rx buffer, error, etc etc. Great stuff ...
So I managed to implement a fully working link with a 4 bit address and 8 bit (can be extended to 10 - two pins are still left as rx/tx for the wireless link ) data between 2 pic16f628.
Next question just for fun ... can I save one more pin ? Is there a way when init the UART to only assign a pin (the tx) and rx to leave it undefined OR assigning it to some kind of NULL ? |
|
|
cykrus
Joined: 01 Oct 2012 Posts: 7
|
|
Posted: Tue Oct 02, 2012 2:41 pm |
|
|
asmboy wrote: | Have you looked at your "manchester code on an oscilloscope ???
Your code example seems strikingly discontinuous.
My experience has been that manchester is an NRZ type of code with continuous clocking, that uses a fixed square wave time base, and encodes a 1 - as a transition in mid cycle - while a zero allows the base frequency to complete. Also known as B-FM and BI-phase encoding.
A typical manchester stream encodes continuous zeros, and punctuates the stream with a specific 1/0 sequence to begin framing of a complete set of data. One of the most famous examples of Manchester code is the Biphase SMPTE TimeCode standard. IRIG, favored by NASA in the old days is another. So for a radio link - great idea you have !!
Manchester is a useful code for data that must flow on an RF channel as it is inherently symmetric , and as such does not produce nasty frequency shift offsets. Thats is in fact why it is far superior to RS-232 for non-hardwired, data transmission. Manchester code can be passed through a variety of wireless or even recorded systems, quite nicely.
IN the old days SMPTE code and IRIG were desired because you could record them directly on magnetic tape- at with low baud rates -
recover data with no error correction typically required.
I have (unfortunately) had a bit of experience with codes of this type,
AND unless your clock frequency/ data rate is very low, you are gonna have a heap of trouble generating a smooth and reliable manchester code with ONLY a PIC ( 4mhz), at data rates of more than say 300 baud, IMHO. |
Hi, I don't own an oscilloscope .. I'll have to buy one. The PIC stuff is new stuff for me (i want to "smart" my house that's why i'm using it).
Thank you for your ideas. I'll study more. |
|
|
asmboy
Joined: 20 Nov 2007 Posts: 2128 Location: albany ny
|
|
Posted: Tue Oct 02, 2012 5:46 pm |
|
|
Use one side of RS232 RX pin for other function ??
I have not done it:
I don't know for sure about that chip and your compiler version but to find OUT try this:
On pin B1, put a LED in series with 3.3k ohms to ground and run this code
Code: |
#include <16F628.h>
#fuses INTRC_IO, NOLVP, NOWDT, PUT, BROWNOUT
#use delay(clock=4000000)
#use rs232(baud=19200, xmit=pin_B2, errors)
main(void){
while (1){
output_toggle(pin_B1);
delay_ms(5200);
}
}
|
If the led flashes - you can do it.
Trust the experiment and you won't go wrong.
|
|
|
|
|
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
|