|
|
View previous topic :: View next topic |
Author |
Message |
jmann
Joined: 27 Dec 2004 Posts: 21
|
Wireless Encoder (good for one-way link using cheap radios) |
Posted: Sun Apr 10, 2005 3:14 pm |
|
|
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
|
|
Posted: Sun Feb 26, 2006 11:13 pm |
|
|
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
|
Re: Wireless Encoder (good for one-way link using cheep radi |
Posted: Sun Apr 27, 2008 7:29 am |
|
|
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
|
|
Posted: Mon May 04, 2009 6:57 pm |
|
|
If you really care about speed, the return statement from MANdecode could be replaced with
This should run a little faster. Bit shifts should take much less time than multiplication. |
|
|
dilipvpn
Joined: 04 Jul 2009 Posts: 1
|
|
Posted: Sat Jul 04, 2009 1:21 am |
|
|
jmann,
Where I can get Manchester.c?
Please help. |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Sat Jul 04, 2009 1:44 am |
|
|
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
|
|
Posted: Tue Aug 25, 2009 2:08 am |
|
|
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
|
|
Posted: Tue Aug 25, 2009 2:36 pm |
|
|
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
|
|
Posted: Tue Aug 25, 2009 4:10 pm |
|
|
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
|
|
Posted: Wed Aug 26, 2009 8:10 am |
|
|
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
|
|
Posted: Sun Sep 13, 2009 2:22 pm |
|
|
drbobbob wrote: | If you really care about speed, the return statement from MANdecode could be replaced with
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
|
|
Posted: Thu Oct 08, 2009 8:30 pm |
|
|
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
|
need example please |
Posted: Mon Nov 02, 2009 9:16 pm |
|
|
@jmann thank you for this code it seems very useful
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
|
Re: need example please |
Posted: Tue Nov 10, 2009 10:10 am |
|
|
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
|
Receving from GSM,Xmit from Pic to another |
Posted: Mon Feb 17, 2014 1:13 am |
|
|
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. |
|
|
|
|
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
|