PDA

View Full Version : Reliable wireless data transfer



dhouston
- 1st May 2007, 18:27
The two small example programs that follow show how to send two data bytes (+ two error check bytes) using the NEC protocol. X-10 has used this protocol for about 20 years with their RF remotes and (with a slight alteration) wireless security sensors. Variations of it are used by many other wireless security devices from various manufacturers. As long as you have adequate received signal strength it is extremely reliable for transferring small amounts of data.

NOTE: I adapted these quickly from some apps I've used for several years with the PIC12F629. I have not tested the abbreviated examples.

Here's the transmitter example.


'-----PIC12F629-----
' Sends 2 bytes + their bitwise complements using a variation of the NEC IR protocol
' repeats every 15 seconds
' I've used this (and seen it used in commercial RF products) using 12-48 bits
' with lead-in pulses from 2.5-9.5mS and lead-in spaces from 2.5-4.5mS

@ __config _INTRC_OSC_NOCLKOUT & _WDT_OFF & _PWRTE_ON & _MCLRE_OFF & _BODEN_ON & _CP_OFF & _CPD_OFF

RF VAR byte[4]
Copies VAR byte 'RF copies
c VAR byte 'loop index (RF copies)
b VAR byte 'loop index (RF[b])
i VAR byte 'bit index
wb VAR byte 'work byte

CMCON = 7
Copies = 4
'Put data in RF[0] & RF[2]
SendRF: RF[0]=80:RF[1]=~RF[0]:RF[2]=66:RF[3]=~RF[2]
Low 4
For c=1 To Copies
PulsOut 4, 880 '8.8mS lead-in pulse
PauseUs 4400 '4.4mS space
For b=0 To 3
wb=RF[b]
For i=0 To 7 'LSB first
PulsOut 4, 50 '0.5mS pulse
If wb.0=1 Then
PauseUs 1500 '1.5mS space
Else
PauseUs 500 '0.5mS space
EndIf
wb=wb>>1
Next
Next
PulsOut 4, 50 '0.5mS pulse
Pause 40: '40mS GAP
Next
Sleep 15 '15 SEC DELAY
GoTo SendRF

End

Here's the receiver example.


'-----PIC12F629-----
'Receives 32 bits of NEC protocol
'RF with initial lead-in of 8.8mS
'sends codes via RS232 @ 9600bps on GPIO.2

@ __config _INTRC_OSC_NOCLKOUT & _WDT_OFF & _PWRTE_ON & _MCLRE_OFF & _BODEN_ON & _CP_OFF & _CPD_OFF

DEFINE PULSIN_MAX 968 '>968 RETURNS 0
DEFINE DEBUG_REG GPIO
DEFINE DEBUG_BIT 2 'GPIO.2
DEFINE DEBUG_MODE 1 'Inverted
DEFINE DEBUG_BAUD 9600
DEFINE OSCCAL_1K 1

RF VAR byte[4]
space VAR byte
i VAR byte
bits VAR byte
stx VAR word 'start of transmission

CMCON = 7 'comparators off

init: RF[0]=0:RF[1]=0:RF[2]=0:RF[3]=0
bits=0:i=0
PulsIn GPIO.1, 1, stx
If (stx<792) Then init
While GPIO.1=0:Wend 'wait pulse
Repeat
PulsIn GPIO.1, 0, space
If (space<40) Or (space>175) Then init
If (space>75) Then
RF.0(i)=1 'set bit
EndIf
i=i+1
Until (i>31)
If RF[0]+RF[1]<>&HFF Then init
If RF[2]+RF[3]<>&HFF Then init
For i = 0 to 3
Debug (RF[i] REV 8)
Next
GoTo init

End

I have used these with inexpensive RF modules made by Wen Shing in Taiwan. The same modules (or clones thereof) are available from several sources worldwide. I've listed some sources here...
http://davehouston.net/modules.htmI've explained the NEC protocol (as it applies to X-10's use of it) and provided a link to a NEC datasheet here...http://davehouston.net/rf.htm
If you do not have an oscilloscope, you can record the received signal (pin 2 of receiver) with a soundcard using the simple setup I show here...http://davehouston.net/learn.htmand then view it with a Wave editor.

skimask
- 13th August 2008, 05:01
NOTE: I adapted these quickly from some apps I've used for several years with the PIC12F629. I have not tested the abbreviated examples.

@ __config _INTRC_OSC_NOCLKOUT & _WDT_OFF & _PWRTE_ON & _MCLRE_OFF & _BODEN_ON & _CP_OFF & _CPD_OFF

Sleep 15
Aren't these 2 mutually incompatible?

charudatt
- 5th May 2009, 18:24
Does this code work

Bruce
- 6th May 2009, 02:55
Does this code work
I have not tested Daves code, but my guess would be yes. I haven't seen anything he's posted yet not work as advertised...;o}

I would set WDT to ON for this one though.

If you have questions, I'm sure Dave will chime-in here at some point. He offers a lot of excellent help here when he has the time.

dhouston
- 6th May 2009, 12:18
As I noted, this was adapted from code that I've used many times. There was a spate of posts here about wireless links and I put that together quickly as an example of a simple approach that I knew worked. The SLEEP statement was a last minute addition - it should have been a PAUSE or the WDT should have been on. It was intended as a break between repeats to make analysis easier which will usually be determined by the application. But the fundamental approach should be OK and I've heard from a couple of people who adapted it to their application.

charudatt
- 6th May 2009, 13:49
I actually I had an error compiling the code and that was sorted out in some other thread in the forum (by Skimask). Wonder why was it not corrected in this thread. Actually, I accidentally ran into the thread and found answers to the error.

Actually , I got good result in using Bruce's code earlier.

My application was a relay control with Toggle and Momentary action. While Toggle worked great , Momentary had a problem.

I hope your approach would help me.

Shall post the results soon.

Thank you once again for your code.

regards

incognico
- 12th October 2009, 16:47
Just wanted to say thanks for sharing this code Dave.

A couple of trivial modifications for my application and choice of PICs, and it's working great. Appreciate your efforts :)

--Nick

dhouston
- 12th October 2009, 22:00
@incognico

Glad it was helpful.

Dennis
- 20th November 2009, 10:45
Dave , your website is an excellent resource ..thank you!

Just curious about the code here.

Would you suggest specific oscillator settings ? Eg. External 4,8 or 20MHZ or would it be at all possible using the internal oscialltor?

Any particular pin choices for TX on the transmitter side and RX on the receiver side ?

Any info would be much appreciated.

Kind regards
Dennis

dhouston
- 20th November 2009, 12:17
Would you suggest specific oscillator settings ? Eg. External 4,8 or 20MHZ or would it be at all possible using the internal oscialltor?I almost always use the internal oscillator.


Any particular pin choices for TX on the transmitter side and RX on the receiver side ?Any pin, except for MCLR, should be OK. It really depends more on what other functions you want the PIC to handle.

Almost all the transmitters are SAW controlled so their frequency is independent of the PIC and most protocols can tolerate ±10-20 variation in pulse/space durations

Dennis
- 20th November 2009, 13:44
Dave
Thanks a million for the reply!
So if I wanted to send the value from two 8-pin dip switches I could alter the code to something like
SW1 var byte
SW2 var byte

SW1 =RF[0]
SW2 =RF[2]
Am I correct ?

And since this is a rather well established protocol there should be no need for things like holtek or motorola encoder decoder pairs ..not so ?

Is there any chance of a code snippit to add a 3rd byte of data ?

dhouston
- 20th November 2009, 17:56
So if I wanted to send the value from two 8-pin dip switches I could alter the code to something like
SW1 var byte
SW2 var byte

SW1 =RF[0]
SW2 =RF[2]
Am I correct ?I think you want it the other way around...
RF[0]=SW1
RF[1]=~RF[0]
RF[2]=SW2
RF[3]=~RF[2]

And since this is a rather well established protocol there should be no need for things like holtek or motorola encoder decoder pairs ..not so ?There's no need for additional encoding.

Is there any chance of a code snippit to add a 3rd byte of data ?

'-----PIC12F629 using MPASM-----
' Sends 2 bytes + their bitwise complements using a variation of the NEC IR protocol
' repeats every 15 seconds

@ __config _INTRC_OSC_NOCLKOUT & _WDT_OFF & _MCLRE_OFF & _CP_OFF

RF VAR byte[6]
Copies VAR byte 'RF copies
c VAR byte 'loop index (RF copies)
b VAR byte 'loop index (RF[b])
i VAR byte 'bit index
wb VAR byte 'work byte

CMCON = 7
Copies = 4
'Put data in RF[0],RF[2] & RF[4] & complement in RF[1],RF[3] &RF[5]
SendRF: RF[0]=80:RF[1]=~RF[0]:RF[2]=66:RF[3]=~RF[2]:RF[4]=33:RF[5]=~RF[4]
Low GPIO.2
For c=1 To Copies
PulsOut GPIO.2, 880 '8.8mS lead-in pulse
PauseUs 4400 '4.4mS space
For b=0 To 5
wb=RF[b]
For i=0 To 7 'LSB first
PulsOut GPIO.2, 50 '0.5mS pulse
If wb.0=1 Then
PauseUs 1500 '1.5mS space
Else
PauseUs 500 '0.5mS space
EndIf
wb=wb>>1
Next
Next
PulsOut GPIO.2, 50 '0.5mS pulse
Pause 40: '40mS GAP
Next
Pause 15000 '15 SEC DELAY
GoTo SendRF

End
I would not try to go beyond 48 bits.