Tuesday, 18 February 2014

433Mhz RF communication between two PIC microcontrollers

The Arduino VirtualWire makes communication between two microcontrollers really easy - simply send some data onto the TX module and it magically appears on the on RX module. We've already built most of this functionality using our Manchester encoding/decoding routines (in both Oshonsoft and SourceBoostC) and can send data over a single wire - all that remains is to replace the wire with our RF modules.

On paper, they're easy enough to work with.
When the TX output line goes high, the RX input goes high. When the TX output line goes low, the RX output line goes low. Simples!




Many years ago we played with RF modules, and they had to be bought (and used) in "matched pairs" - a transmitter and receiver module were "laser tuned" to be exactly on the same frequency. These days, with a flood of cheap RF modules coming out of China via websites like Alibaba and eBay, they are a little more forgiving. There are receiver modules which work with a variety of transmitters - allowing "broadcast" networks to be created - where multiple transmitters can all talk to a single receiver (or multiple receivers can listen to a single transmitter).

Our receiver module is an RR3 and can work across a range of frequencies (the Low Power Device 433Mhz radio range is actually 69 specific frequencies, at 0.025Mhz intervals, between 433.075Mhz and 434.775Mhz)

After hooking up a test rig, it seems that getting rid of our single connecting wire between the two mcus is not quite as simple as sticking a TX module on one end and an RX module on the other!
For testing, we programmed two PICs - one which sent an output pin high when a button was pressed and another which toggled an RGB LED from red to green as the incoming signal went from low to high (and vice versa).

With each press of the button, we were expecting to see a green light, but that doesn't happen. The output from the receiver module stays high, even when we've explicitly turned off the pull-up resistors on our input pins - and even if we stick a 100k pull-down resistor on the input! Yet, interestingly enough, if we press the button often enough, eventually the signal starts to appear:




So what's going on?
We can only surmise from the description of how the 433Mhz receivers work, the idea of having 69 channels in the 433Mhz range, and the fact that one receiver works across a range of frequencies (and the datasheet tells us that the receiver automatically "locks on" to the strongest signal) that something like this is happening:

Firstly, the receiver needs to scan all 69 channels to see which has the strongest signal strength. If we leave our output signal high for a long time, the receiver does not see this not as data activity on the 433Mhz spectrum (since the signal is not alternating) - in the same way running a continuous current through a speaker does not result in sound, it is the change in current which generates a signal (whether audio or data).
We've no idea at what speed the receiver  may be scanning the channels, but at some point, we assume that it's detecting a change on whichever channel (specific frequency) that our transmitter is tuned to. Once this has happened, the receiver knows which frequency to monitor for incoming data, and the response starts to appear on the LED.

This is all supposition, but would explain why there's a delay between us starting to pulse the output on the TX line and it appearing on the RX input pin - and also why, when we send data in tiny, short bursts, it doesn't get picked up on the receiver (which appears to be non-responsive).

With this in mind, we went back to our Manchester encoding example and made a few changes, so that it sends the data repeatedly, with an "out-of-phase" signal between data bursts (to keep the receiver "listening" on the channel our transmitter is receiving):

With these changes in place, the data appears on the receiver module so that it can be read back over UART/serial. We're still losing about 1-in-20 messages but apparently that's about the average for these kinds of cheap TX/RX modules - I guess we'll just have to make sure we send every message twice (with a few milliseconds delay between them) and parse out the duplicates on our receiver end.

But it's nice to be able to have worked something through, from start to finish, and understand (with a few assumptions) what's going on at every step along the way! Next, we'll be shoving these modules into our electronic board game so we can place the board on a table top and send the data wirelessly to a listening computer....