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

PIC16f628 radio link

 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
cykrus



Joined: 01 Oct 2012
Posts: 7

View user's profile Send private message Yahoo Messenger

PIC16f628 radio link
PostPosted: Mon Oct 01, 2012 12:13 pm     Reply with quote

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

View user's profile Send private message Yahoo Messenger

PostPosted: Mon Oct 01, 2012 1:02 pm     Reply with quote

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

View user's profile Send private message Yahoo Messenger

PostPosted: Mon Oct 01, 2012 2:48 pm     Reply with quote

OOps ... i did some more reading and it looks like my code reinvented the wheel Smile))) ... 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

View user's profile Send private message AIM Address

PostPosted: Mon Oct 01, 2012 7:21 pm     Reply with quote

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

View user's profile Send private message Yahoo Messenger

PostPosted: Tue Oct 02, 2012 2:40 pm     Reply with quote

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

View user's profile Send private message Yahoo Messenger

PostPosted: Tue Oct 02, 2012 2:41 pm     Reply with quote

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

View user's profile Send private message AIM Address

PostPosted: Tue Oct 02, 2012 5:46 pm     Reply with quote

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.
Very Happy Very Happy Very Happy Very Happy Very Happy
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Page 1 of 1

 
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