Upload
ozmeen
View
223
Download
0
Embed Size (px)
Citation preview
8/8/2019 RF Encoding - Decoding
1/4
1
A laymans guide to RF transmission encoding-decoding using PbPro
As promised a while ago, I finally got the OK from our client to release part of the code that was used in
their RF data link project. The project, which will become a commercial instrument at the end of the next
quarter, consisted of 16 remote logging stations with RF data links into a main controller located in the
main building. We ended up utilizing Radiotronix module OOK transmitter and receiver modules because
of their specs (109dbm sensitivity on the receiver, 75 kHz accuracy around the center frequency of 433.92
MHz on the transmitter and 4800-baud rate speed on both) and low cost. By the end of the project we were
able to achieve 99.9% link reliability and 100% data integrity reliability, measured over a period o 35 days,
and operating 24-7 at distances in excess of 70 meters inside buildings of various types. After each remote
is polled, it is given 5 opportunities to come back. Should transmission fail after the 5th
attempt (data
integrity, no answer etc.), then that link is assigned a fail code until the next time. For our purposes, at 4800
baud, using CRC and Manchester encoding and based on the number bytes that we are dealing with, each
transmission is well under 1 second ( more like 400 msec)
As RF was new to us, it took a while to learn (the hard way I might add) that you cannot treat RF serial
communications as you would ,say, a hard-wired system. We got bit by most, if not all, of the alligators
which normally attack such a project, that is, PC board layout, choice and positioning of the antenna,
propagation interference, signal absorption, reflection, multipath interference and radio interference inside
the buildings, nulls, deep nulls etc. After solving the usual hardware problems, it was then that we found
out the hard way that RF serial transmission has to be treated quite a bit differently than hard-wired serialcomms.
Given the nature of the OOK type receivers all of which contain data slicers, the transmitted bit pattern has
to be able to:
1. Provide some sort of synching for the receiver2. Provide a pattern which will keep the receivers data slicer at mid point (DC balanced) when using
NRZ type data -(Manchester encoding)
3. Provide some sort of control for its integrity at the receive end -(16 bit CRC check).4. Provide some sort of unique identifier (if you have more than one remote working)Our transmission sequence and format looked like the following:
Gosub Manchester_Encode
Gosub Calc_CRCTransmit_Data:
Serout2 RFSerOut,RfBaudRate,WaitDelay,[Preamble,Preamble,Preamble,Preamble,_
Preamble,XmtSynch,EncodedWord.LowByte,EncodedWord.HighByte]
At the receiver end our receive proc looked like the following:
Receive_Results:
TempVar = SerialNum[z]
gosub Manchester_Encode ' Encode byte
RFSerout = 1 ' prepare xmitter
pause 15 ' time to settle
Serout2 RFSerOut , RfBaudRate , 15 , [Preamble,Preamble,Preamble,Preamble, Preamble, Synch ,
EncodedWord.Lowbyte,EncodedWord.Highbyte] ' wake up remote
gosub Xmit_OFF ' xmitter is OFFGosub Rcv_ON ' receiver is ON
CRC = 0
ChannErr = 1 ' If fail code 1 then time out
goto Get_Rx_Data ' get the data
Continue1:
If TempVar = SerialNum[z] then ' Is the remaote answering the correct one?
ChannErr = 2 ' If fail code 2 then SerNum ;Timeout 2
goto Get_Rx_Data ' get the data
Continue2:
8/8/2019 RF Encoding - Decoding
2/4
2
x = TempVar ' Remote S/N
gosub Calc_CRC ' calculate CRC for byte
ChannErr = 3 ' Type comparison error code
goto Get_Rx_Data ' get the data
Continue3:
ChannErr = 4 ' Type comparison error code
If SensorType[z] (TempVar) then Finish_Receive ' Type error;remote type base type
SensorType = TempVar
x = SensorType
gosub Calc_CRC ' calculate CRC for byte
goto Get_Rx_Data ' get the data
Continue4:
ResultSign = TempVar
x = ResultSign ' Result sign
gosub Calc_CRC ' calculate CRC for byte
ChannErr = 5
goto Get_Rx_Data ' get the data
Continue5:
Result.LowByte = TempVar
x = Result.LowByte ' result low byte
gosub Calc_CRC ' calculate CRC for byteChannErr = 6 ' Result High Byte error code
goto Get_Rx_Data ' get the data
Continue6:
Result.HighByte = TempVar
x = Result.HighByte ' Result high byte
gosub Calc_CRC ' calculate CRC for byte
ChannErr = 7 ' result low byte error code
goto Get_Rx_Data ' get the data
Continue7:
Result2.HighByte = TempVar
x = Result2.Highbyte ' must do CRC with Hi CRC byte first
gosub Calc_CRC ' otherwise CRC 0 on good xmission
ChannErr = 8goto Get_Rx_Data ' get the data
Continue8:
Result2.LowByte = TempVar
x = result2.Lowbyte
gosub Calc_CRC
If CRC 0 then ' Calculated CRC must = 0 ;else crc error
ChannErr = 9 ' CRC Error
goto Finish_Receive ' end reception with error
endif
ChannErr = 0 ' Reset error var; receive OK
gosub Rcv_OFF ' Evereything OK; Receiver is OFF
Goto Finish_Receive
endifGet_Rx_Data:
Serin2 RFSerIn,RfBaudRate,RxTimeOut,Finish_Receive,[Wait(Synch), Encoded Word.Lowbyte ,
EncodedWord.Highbyte]
gosub Manchester_Decode ' decode the variable back to a byte
The above procedure, which was a subroutine in our program, basically:
8/8/2019 RF Encoding - Decoding
3/4
3
1. Wakes up each of remotes based on the serial number of the remote station. Note that we send out 5preambles. If you have the time and speed, the more the merrier since the preambles purpose is to helpDC balance the reeivers bit slicer.
2. Receives each byte of data from the remote3. Does a CRC (integrity check) calculation on the received data (less the preambles, and the CRC byte)4. Manchester decodes the received data5. Note that ChannErrs were inserted in there so that we would know exactly where the transmission
failed (if it failed).Some of the constant and variable definitions for the above procedures to work were:' CONSTANTS Here:Preamble con $55 ' preamble data byte forxmiter synching;%101010Synch con "j" ' synchronization byteCRCPolynomial con $1021 ' CRC-CCIT
Notes:1. We chose $55 as the preamble because of its inherently balanced nature of equal number of 0s and
1s. If one looks at the binary equivalent of 55h is 01010101b. Note that 1s and zeros equal eachother and the bit run length (how many 1s and 0s are next to each other- also important to keep thebit slicer DC balanced) ) is 1.
2. The j was chosen as the Synch byte for the same reason3. The CRC polynomial is a standard. Much information available on the net about CCIT CRC
polynomials.
Manchester encoding and decoding the data:
Manchester_Encode:For y = 0 to 7
If TempVar.0[y] = 0 then ' Bit = 0EncodedWord.0[y * 2] = 0EncodedWord.0[(y*2)+1] = 1
elseEncodedWord.0[y * 2] = 1 ' Bit = 1EncodedWord.0[(y*2)+1] = 0
endifnext
Return
Note that:1. TempVar is the byte we want to encode2. We will encode it into a 16 bit word, the low byte will contain the lower nibble of the encoded
variable; ' the high byte will contain the upper nibble of the encoded variable3. A 0 will be equated to a 0-1 transition4. A 1 will be equated to 1-0 transition5. I used a little touted, extremely useful, undocumented feature of PbPro- the ability to access each bit of
a byte or word using Word.0[y] feature. This saves on LOADS of IF-ANDs as well as codereadability and size. I suspect that the CASE statement in 2.34 may be usable instead of this feature.
6.
The above procedure will encode each 8-bit byte to a 16-bit word with an equal number of 1s and 0s.Run length is 1. The upside is that this is perfect for DC balancing the receivers bit slicer. Thedownside is that this results in doubling bandwidth.
Since the data is encoded at the transmitter, it must be decoded at the receiver. The procedure I used forthat was:
Manchester_Decode:For y = 0 to 7
If EncodedWord.0[y*2] = 0 then ' if bit =0
8/8/2019 RF Encoding - Decoding
4/4
4
If EncodedWord.0[(y*2)+1] = 1 then
TempVar.0[y] = 0
Endif
Else
TempVar.0[y] = 1 'then bit =1
Endif
Next
Return
Note that:
1. We will decode EncodedWord (lower byte) as the lower nibble of tempVar2. EncodedWord ( high byte) as the upper nibble of TempVar3. Basically, again using the Word.0[y] feature of PbPro, we are able to access each bit of the encoded
word and decode it (strip it) back to the original 1 or 0 that was transmitted.
For data integrity at the receive end,(that is to make certain that what you receive is exactly what you send)
we used a CRC check. We found this to be much safer and reproducible than the simpler checksum. The
CRC routine was:
Calc_CRC: 'calculate byte CRC; 16 bit crc based on CCIT polynomial
CRC = (x * 256) ^ CRCFor y = 0 to 7
If CRC.15 = 0 then Multiply
CRC = (CRC