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

Wireless Encoder (good for one-way link using cheap radios)

 
Post new topic   Reply to topic    CCS Forum Index -> Code Library
View previous topic :: View next topic  
Author Message
jmann



Joined: 27 Dec 2004
Posts: 21

View user's profile Send private message

Wireless Encoder (good for one-way link using cheap radios)
PostPosted: Sun Apr 10, 2005 3:14 pm     Reply with quote

This code is used to encode a few bytes for radio transmission, then decode them when it is received. Basically, it is intended for implementation using cheap radio modules (I use modules from Radiotronix) to form a one way link.
Transmission works by using the usart to send and receive data. The hardware usart preforms the difficult task of aligning incoming data in the receiver and so when data is received, the receive interrupt is triggered, and the data is read. After receiving the start sequence, the appropriate number of bytes is read and checked for errors. I used a simple addition scheme for error checking, but this could be replaces with CRC or something else more complex.

The transmission scheme begins with a preamble of 0x55. This is a alternating string of 1 and 0's the prepare the receiver's data slicer essentially teaching it what a 1 and 0 is. 0xff is the sync bit. it aligns the usart which is shifting data till it sees the start bit and stop bit in the right place. finally, the start sequence 0x00, 0xFE indicates data is after that point. I put in an extra long preamble and second sync bit to ensure that the sync does happen, this is not necessary, but improved my reliability


Manchester
Using this code, Manchester.c needs to be included in both the code for the transmitter and decoder.

MANencode1 generated the first encoded byte from a useful data byte
MANencode2 generated the second Encoded byte from a useful data byte
MANdecode takes two encoded bytes and returns a useful decoded byte

set MANerror=0, then run the decoder for all your data. if MANerror==1, then you know that there was an error (one nibble was not a manchester valid nibble).

manchester encoding is used to ensure that the data remains DC balanced. That is to say that it has the same number of ones and zeros.

Code:
char manchester[16]={
   0b01010101, //0
   0b01010110, //1
   0b01011001, //2
   0b01011010, //3
   0b01100101, //4
   0b01100110, //5
   0b01101001, //6
   0b01101010, //7
   0b10010101, //8
   0b10010110, //9
   0b10011001, //A 10
   0b10011010, //B 11
   0b10100101, //C 12
   0b10100110, //D 13
   0b10101001, //E 14
   0b10101010}; //F 15
static int MANerror;

byte MANencode1(byte ByteIn)
{
   return manchester[(ByteIn&0xf0)>>4];
}
byte MANencode2(byte ByteIn)
{
   return manchester[ByteIn&0x0f];
}   

byte MANdecode(byte ByteToDecode1, byte ByteToDecode2)
{
   int i, j, part1, part2;
   
   
   
   for(i=0;i<=15;i++)
    {
      if(manchester[i]==ByteToDecode1)
       break;
    }
   if(i==16)
     MANError=1;
   for(j=0;j<=15;j++)
    {
      if(manchester[j]==ByteToDecode2)
       break;
    }
   if(j==16)
     MANError=1;
   
   return (i*16 + j);
}

Transmitter

The code is used to send data.
TXWireless() is my own send usart function because I do not use #USE RS232, but it could be replaced with putc(). Also note that the usart is turned off when not sending data. This is because RS232 sits idle at HIGH, and would keep the transmitter on if I did not do this.

Code:

void SendWireless(void)
{
    int checksum;
   checksum=(int)(DataByte0+dataByte1+DataByte2)

   output_high(pin_C6);
   //Enable USART Transmitter


   SPEN=1;
   TXEN=1;
   delay_ms(5);
   //Preamble
   TXWireless((int) 0x55);
   TXWireless((int) 0x55);
   TXWireless((int) 0x55);
   TXWireless((int) 0xff); //usart sync 1
   TXWireless((int) 0x55);
   TXWireless((int) 0x55);
   TXWireless((int) 0x55);
   // send the uart sync byte
   TXWireless((int) 0xff);
   // send the start code
   TXWireless((int) 0x00);
   TXWireless((int) 0xfe);
   //Send Data
   TXWireless((int) MANencode1(DataByte0));
   TXWireless((int) MANencode2(DataByte0));
   TXWireless((int) MANencode1(DataByte1));
   TXWireless((int) MANencode2(DataByte1));
   TXWireless((int) MANencode1(DataByte2));
   TXWireless((int) MANencode2(DataByte2));
   TXWireless((int) MANencode1(checksum));
   TXWireless((int) MANencode2(checksum));

   TXWireless((int) 0x55); //this actually is not needed
    
   while(!TRMT); //Wait for shift register to stop sending last byte

   //Disable USART
   SPEN=0;
   output_low(pin_C6);//Pull output low

Reciever
The receive is Usart Interrupt driven. it is a state machine. also, I read right out of the receive register, but that can be replaced with Getc().

Code:

#int_RDA //Data Waiting in USART RX Buffer
void RecieveWireless()
{
   static int WirelessData[8];

   static int   RXModeByte;
   int data, checksum;
       data=RCREG;     //Get Data From USAART RX Buffer

   if (OERR) //Buffer Underrun
   {
      CREN=0; //Reset Usart reciever
      CREN=1;
      return;
   }

   if (data==0x00)   // wait for the start byte -  anytime the USART Sync Bit is
      {
      RXModeByte=1;  // encountered, restart the recieve process
      return;
     }

   Switch (RXModeByte)
   {
      Case 0:
         break;
      Case 1:
         if (data==0xfe)   // Start Byte, now Wait for data
            {
               RXModeByte=2;  // begin waiting for data bytes
               LastRXTime=time;
            }
         else
            RXModeByte=0;  // not start byte, go back to wait for start.
         break;
      Case 2: //DataByte 0
      Case 3:
      Case 4: //DataByte 1
      Case 5:
      Case 6: //DataByte 2
      Case 7:
      Case 8: //checksum
      Case 9:
         WirelessData[RXModeByte-2]=data;  // Read in bytes, one at a time.
         RXModeByte++;                     // Increment count
         
         if (RXModeByte==10) //After all eight databytes are recieved
         {
            RXModeByte=0;   //
            MANerror=0;      //reset error bit before decoding
            RecieveByte0=MANdecode(WirelessData[0], WirelessData[1]);
            RecieveByte1=MANdecode(WirelessData[2],WirelessData[3]);
            RecieveByte2=MANdecode(WirelessData[4],WirelessData[5]);
            checksum=MANdecode(WirelessData[6],WirelessData[7]);

            //Check For Errors:
            if (!MANerror && ((int)(RecieveByte0 + RecieveByte1 + RecieveByte2) == checksum ))
            {  //When no errors exist:
               
               //USE THIS SPACE TO DO SOMETHING WITH YOUR VALUES

            }
            else
            {  //Errors Exist

            }
            //Optional:
            //output_toggle(LEDwireless); //blink power LED with wireless packet data

         }
         break;
      default:
         RXModeByte=0;
         break;
   }
   return;
}


This code is very adaptable if you have questions, there are lots of people here that also have used cheap wireless modules to do amazing things that can answer your questions. also, simple modifications can make this useful for more data than the three bytes I used it to send.


Last edited by jmann on Mon Oct 12, 2009 8:48 am; edited 1 time in total
david90



Joined: 25 Feb 2006
Posts: 23

View user's profile Send private message

PostPosted: Sun Feb 26, 2006 11:13 pm     Reply with quote

how do I use these code? If I want to send char 'a', where would i put it??
rudy



Joined: 27 Apr 2008
Posts: 167

View user's profile Send private message Send e-mail MSN Messenger

Re: Wireless Encoder (good for one-way link using cheep radi
PostPosted: Sun Apr 27, 2008 7:29 am     Reply with quote

Hi jmann.
Looks great, but I am very new in PIC communicating, could you please send me the total transmitter and receiver routine, it will be much more comprehensive to me.

When you say that Manchester.c have to be included, I didn’t understand, your TXwireless routine to me is a huge blank too, hshs.

Please give some help on this.

Regards.
drbobbob



Joined: 02 May 2009
Posts: 1

View user's profile Send private message

PostPosted: Mon May 04, 2009 6:57 pm     Reply with quote

If you really care about speed, the return statement from MANdecode could be replaced with

Code:
return (i<<4 + j);


This should run a little faster. Bit shifts should take much less time than multiplication.
dilipvpn



Joined: 04 Jul 2009
Posts: 1

View user's profile Send private message

PostPosted: Sat Jul 04, 2009 1:21 am     Reply with quote

jmann,
Where I can get Manchester.c?
Please help.
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Sat Jul 04, 2009 1:44 am     Reply with quote

Manchester.c is the first block of code that he posted. It has routines
that are called by his Transmitter and Receiver code.
hobby_85



Joined: 17 Aug 2009
Posts: 50

View user's profile Send private message

PostPosted: Tue Aug 25, 2009 2:08 am     Reply with quote

Hey, sorry but im getting a little confused here.

To use this code, do you have to connect the RF transmitter and receiver to the TX and RX pins of the PIC respectively? Or can it just be connected to any I/O pin respectively.

If so, from what Ive read, and im not really sure about this, is that manchester coding isnt compatible with a UART.

Also, for the preamble, the statement says hes sending a series of 1's and 0's to let the uart know what it is. but from the code, he sends 0x55, which is the charactor 'U' in dec. So what is happening?

Thanks
mkuang



Joined: 14 Dec 2007
Posts: 257

View user's profile Send private message Send e-mail

PostPosted: Tue Aug 25, 2009 2:36 pm     Reply with quote

hobby_85 wrote:
Hey, sorry but im getting a little confused here.

To use this code, do you have to connect the RF transmitter and receiver to the TX and RX pins of the PIC respectively? Or can it just be connected to any I/O pin respectively.


The way THIS piece of code is written yo have to connect to the Tx and Rx of the PIC because the OP is using hardware UART (only hardware UART has a received interrupt).

rudy wrote:
Hi jmann.
your TXwireless routine to me is a huge blank too, hshs.

Regards.

I concur. There is no statement such as to the baud rate used in the UART.
hobby_85



Joined: 17 Aug 2009
Posts: 50

View user's profile Send private message

PostPosted: Tue Aug 25, 2009 4:10 pm     Reply with quote

Quote:

TXWireless() is my own send usart function because I do not use #USE RS232, but it could be replaced with cetc().

I suppose it's the equivalent of the fputc() function. He's putting it one character at a time, so it should work.
mkuang



Joined: 14 Dec 2007
Posts: 257

View user's profile Send private message Send e-mail

PostPosted: Wed Aug 26, 2009 8:10 am     Reply with quote

Yes but the point is that code you post in this section of the forum should be actual, compilable, usable code that the user can modify for his own applications. The code as it stands now is none of the above.
MPi



Joined: 12 Sep 2009
Posts: 1

View user's profile Send private message

PostPosted: Sun Sep 13, 2009 2:22 pm     Reply with quote

drbobbob wrote:
If you really care about speed, the return statement from MANdecode could be replaced with

Code:
return (i<<4 + j);


This should run a little faster. Bit shifts should take much less time than multiplication.

This code is wrong. You forget the precedence of operators.
The correct code would be this:
Code:
return ((i<<4) + j);

But it is not faster when using the PIC18.
Code:
....................    return((i << 4) + j); 
                         cycles
3D52:  SWAPF  x8B,W        1
3D54:  MOVWF  00           1
3D56:  MOVLW  F0           1
3D58:  ANDWF  00,F         1
3D5A:  MOVF   00,W         1
3D5C:  ADDWF  x8C,W        1
3D5E:  MOVWF  01           1
.................... }     7

....................    return(i * 16 + j); 
                         cycles
3D52:  MOVF   x8B,W        1
3D54:  MULLW  10           1
3D56:  MOVF   FF3,W        1
3D58:  ADDWF  x8C,W        1
3D5A:  MOVWF  01           1
.................... }     5


Last edited by MPi on Wed Dec 30, 2009 5:33 pm; edited 1 time in total
jmann



Joined: 27 Dec 2004
Posts: 21

View user's profile Send private message

PostPosted: Thu Oct 08, 2009 8:30 pm     Reply with quote

Hey buds, its been a while and this code has generated lots of questions. Let me see what I can address here.

First of all, I need to remind you that you need to have a good idea of what goes on inside of a micro-controller. What I mean by this is that you need to understand what certain built in functions of writing data to or reading data from hardware registers actually do. You should understand how a UART works and that it has a FIFO buffer and shift register in it; etc.

Quote:

Also, for the preamble, the statement says hes sending a series of 1's and 0's to let the uart know what it is. but from the code, he sends 0x55.

A UART sends a start bit (0), a stop bit (1), and 8 data bits. Thus, when sending 0x55, the UART sends 0101010101. (remember that UARTs send the LSB first. )

Quote:

There is no statement such as to the baud rate used in the UART.

Hey dudes, you guys have to setup the UART before you use it. You can either use the built-in #USE RS232 to do so or set the UART registers manually. I prefer the latter.

Quote:

I suppose it's the equivalent of the fputc() function. He's putting it one character at a time, so it should work.

Exactly. Because fputc() hangs the processor until the TX buffer is sent, I prefer to implement my own TX routine that includes a ring buffer, but that is just me.
Quote:

"I concur. There is no statement such as to the baud rate used in the UART."


pick any [appropriate] baud rate you want when you enable the UART.


Last edited by jmann on Fri Mar 19, 2010 11:09 am; edited 2 times in total
aruna1



Joined: 14 Oct 2008
Posts: 103

View user's profile Send private message

need example please
PostPosted: Mon Nov 02, 2009 9:16 pm     Reply with quote

@jmann thank you for this code it seems very useful Laughing

Can someone please post example of how to use this to create a transmitter and receiver using two 16F628A?

For example lets say I want to make two button remote:

press button 1 in transmitter --> then do task x at receiver
press button 2 in transmitter --> then do task y at receiver

Can someone post some example relevant to above?
I'm new to PIC programming and have little knowledge.
Thanks.
jmann



Joined: 27 Dec 2004
Posts: 21

View user's profile Send private message

Re: need example please
PostPosted: Tue Nov 10, 2009 10:10 am     Reply with quote

aruna1 wrote:

I'm new to PIC programming and have little knowledge.
Thanks.


Read the data sheet for the PIC in its entirety and understand the programming, register, and control architecture. Untill you know how the uart works, using it to send data via a OOK transmitter is not going to make any sense.
sam6154



Joined: 17 Feb 2014
Posts: 2
Location: Chennai

View user's profile Send private message

Receving from GSM,Xmit from Pic to another
PostPosted: Mon Feb 17, 2014 1:13 am     Reply with quote

I am doing a project based on RF transmitter(TxD1) and receiver(RxD1). When i try to normally fetch values i am receiving the value in between the garbage values which is hard to fetch.I have Read through this post and it would be helpful if anybody could send me some sample codes on how to communicate via rf.And also suggest me which give more reliable data transmission ,RF with encoder and decoder or RF connected directly to xmit and rcv.
thank you... in advance.
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> Code Library 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