I'm trying to build some sort of RC transmitter using the 434 MHz radio link set. Sometimes called Easy Radio, but not by SparkFun. Edit: because they're not the same thing!
I am setting this up on a breadboard with a Picaxe 08M and two potmeters as inputs. The two ADC bytes are combined into one byte. The one byte gets transmitted.
The breadboard also has the receiver on it. The antennas are ridiculously close to each other, less than a 1/4 wavelength. But it works. I am comparing scope traces of the data signal that goes into the transmitter and compare that to the signal that the receiver spits out.
This one shows three bytes: 85, 234 and again 234. The red squares are 1 ms wide. My software scope does not indicate the voltage for the vertical scale, because the soundchip in my laptop couldn't care less. The green trace is the input signal, the blue one is what comes out the receiver. Notice the inversion. And the jacked corners. This was pretty much the cleanest signal I could get.
Time goes left to right, s the oldest signals are on the left. Please follow the green line and interpret the bits with me. The line is low when the signal is idle. It goes high for the start bit, then follow eight databits. The last one (bit 0) first, a high voltage indicates a zero value, a low voltage indicates a one.
So the data reads 10101010 left to right.Which is really %01010101 or 85 decimal. After the data comes the low "stop bit". And it confused me at first because it is longer than all the other bits. Almost twice as long. This is to give the receiving party to process the data and get ready for the next start bit.
The RX uses the 01010101 to get synchronised. This is the whole reason to send the value 85. Or as the official symbol in the basic code OUGHT to read: "readyfreddyareyousteady".
After that, the 08M is sending the proper data. Twice. Start bit high, 8 databits, stop bit low. And again. The the line goes idle again. At that point the received signal wanders off again. So next time around we need to reinitialize the whole 85-shebang.
This trace show 170, 15, 255. Or in chronological bits (S means start, s means stop): S10101010s S11110000s S11111111s. The trailing 255 just shows up as a single blip in the trace and helps to get the signal clear until the very end. Notice how the blue line starts to droop off within the data part of the last byte.
So far, I've tried many different ways to get data across and learned the following.
- Stick with the advertised bps rate of 4800. Slower is not better. This requires clocking the 08M at 8 MHz, or it won't do 4800 bps.
- Use True serial signals (as opposed to inverted) from picaxe to TX, or my Xoscope (software scope) will not display it. No explanation by me. I noticed though that data was still being received by the RX.
- The RX spits out inverted signals, whatever the TX' input signals.
- The famous readyfreddyareyousteady %01010101 is explained in the datasheet: the units both need about 20 ms of transmission to warm up (probably to sync clocks and clear out caps). At 4800N1 one byte takes about ten bits or 10/4800th of a second or ca 20 ms.
- Better safe than sorry: spit out your byte of data twice. My single byte spitter sits in an infinite loop anyway. But the looparound between serout commands is just enough to relax the TX/RX and it needs a fresh %01010101 every time.
- PWM or servo pulses don't work (well). This link was made for serial data.
- I try to not send just 0 or 255, but I am probably being over-cautious. Each byte has at least one change from high to low in the data, so the RX know we're still busy communicating.
My proof of concept code:
#picaxe08m
#no_data
#no_table
setfreq m8
' rik letsmakerobots.com 20100922
' this reads 2 pots: 1 for starboard and 1 for port side of a diff traction bot
' this picaxe just sends the combined values in one byte over a RF TX
symbol in_ps = b0 ' port side left
symbol adc_ps = 4 ' adc channel 4 is IC pin 3
symbol in_sb = b1 ' starboard side right
symbol adc_sb = 1 ' adc channel 1 is IC pin 6
symbol out_both = b2 ' mix both values into a single bytesymbol
pin_radio = 2 ' radio TX takes data via this picaxe output-pin
' (which is really pin 5 in the IC)
main:
readadc adc_ps, in_ps
readadc adc_sb, in_sb
' out_both = four bits ps followed by four bits sb
in_ps = in_ps AND %11110000
in_ps = in_ps min %00010000 max %11100000
in_sb = in_sb / 16 min %00000001 max %00001110
out_both = in_ps OR in_sb
serout pin_radio, T4800_8, (85, out_both, out_both)
goto main
update 26 sep 2010
I finished building a soldered version of my transmitter, so that I can do some range testing (I really need to buy a few more breadboards!).
It's a nice little package on a Dagu little protoboard, with dual voltage supply, two potmeters, picaxe 08M, programming connector and a 434A TX. The antenna is not 17 but 34 cm long (1/2 wavelength). It's powered by 6x AA NiMh for 7.7 V. The TX takes the raw battery voltage, because more is better. They can take up to 12 V. The picaxe needs a regulated supply of 5 V.
Then comes the receiver. Boy, did I learn new -late night- lessons here! First of all about my Xoscope using my laptop's microphone input. The mics intended for use with PCs are electrets and require some supply voltage. They get that from your mic "input". So, I finally measured it and it is ca 2.8 V compared to GND. That 2.8V is enough to screw up any measurement I was trying to make of the serial signal the RF receiver tries to pump into my Picaxe. I had to find a reliable way to separate laptop from picaxe. I ended up using a little diode.
(RX serial signal “85 85 96 96” with TX at 2 m away)
Until I figured this out, I could not trust the scope traces as a reliable means of judging signal quality. So I programmed the picaxe to evaluate incoming bytes. My TX is now programmed to send double bytes. Each byte is repeated. When firstbyte and secondbyte received by picaxe are equal, the picaxe will flash a green LED. If not, a red LED. For use outdoors, I added a “crystal” earphone to the green LED. So I could hear it flash.
This is how I learned to use INVERTED serial signals on both ends. Anyting else would fail. Ignore the lesson above! That was just to keep my stupid “oscilloscope” happy. When trying to feed your picaxe, use INVERTED signals only.
(stupid thing - keeping me awake all night - mumble grumble *%%#%$#@#@!)
So I too went walkabout with a breadboard in my hand and a curly wire in my ear. On a nice sunny Sunday afternoon. I placed my TX on a clear spot, just outside of town and walked away, listening to the clicks in my ear. After about 200 metre, the clicks disappeared. When I tilted my antenna from vertical to horizontal, the signal returned. No longer a continuous stream of bytes, but at least one came in undamaged every half second or so. Not enough for a RC vehicle under direct control, but nice for a semi-autonomous rover, I suppose.
Next I rigged my TX way up in the air, on the roof of my house. I walked through town and learned how much the buildings and trees can influence the reception. And again, antenna orientation. And my own body. And the movement of the antenna. And a gust of wind blowing my TX down to the ground…
But even with the antenna “directly coupled to GND”, I could still pick up the signal, with bytes intact, at about 100 metre. Not bad.
Legend: the red dot is my TX on the roof. The purple circle has a radius of approx. 200 m. The pink area is sorta the area where I could pick up at least some bytes. The outer violet border is my rough estimation of where the absolute edge of my range would be. Given this supply voltage, antenna, elevation, etc, etc.
Notice the relevance of buildings and "line of sight". There was absolutely no signal behind the church, but at the far end of the water, twice, if not thrice the distance, it was still OK.
Another lesson, kinda relevant, learned today: superglue will mess up your pots!
Receiver code:
#picaxe08m
#no_data
#no_table
setfreq m8
' rc_easy_radio_08m_signal_detection
' rik letsmakerobots.com 20100925
' this receives serial input
' and gives feedback to user via tunes about perceived data errors
symbol pin_radio = 1 ' radio RX serial data
symbol pa0 = b0 ' preamble 0
symbol pa1 = b1 ' preamble 1
symbol firstbyte = b2
symbol secondbyte = b3
' green LED on pin 2
' red LED on pin 4
high 2 low 4 pause 2000
low 2 high 4 pause 2000
low 2 low 4
' the TX will send 85, 85, value1, value1
' but we don't know where in the sequence we're picking up the data
main:
pa0=0 pa1=0 firstbyte=0 secondbyte=0
low 2 low 4
serin pin_radio, N4800_8, pa0
if pa0 = 85 then
serin pin_radio, N4800_8, pa1
if pa1 != 85 then
firstbyte = pa1
else
serin pin_radio, N4800_8, firstbyte
endif
serin pin_radio, N4800_8, secondbyte
if firstbyte != 0 and firstbyte = secondbyte then
high 2 low 4 ' data checks out OK
else
low 2 high 4 ' data is bad
endif
else
low 2 high 4 ' data is bad
endif
goto main
update 27 sep 2010:
More lessons. Sometimes a very short distance between TX and RX is a bad thing. When doing bench tests, I discovered I needed to take off the RX antenna, in order to get reliable results. Just to make sure my test would be valid, I placed the TX in the other room.
I simplified my datagram. It now has one 85, followed by twice the actual data byte. And I removed a lot of if/thens from the RX code. I can now send/receive zero as a data value. And 85 as well. Time to mount this RX on a proper bot!