Introduction
For the AuroraWatchNet magnetometers that I am developing I currently use the Ciseo XRF radio module. They are based upon the pseudo-standard XBee footprint, operate at 3.3V and provide a UART interface to the microcontroller. They are easy to use but I have found the range is not always sufficient, typically limited to 60 metres of free space plus one exterior wall/window. Another commonly-used radio module is the HopeRF RFM12B transceiver, as used on the JeeNode. The RFM12B also operates at 3.3V but features an SPI interface to the microcontroller. It is available as a 2mm pitch surface-mount module, or as a 12 pin 2mm pitch DIP package.As my Calunium v2 microcontroller development board can be fitted with a RFM12B radio module I naturally wanted to compare the performance of the RFM12B and XRF. Initial testing of the Hope RFM12B gave a usable range of 150 metres of free space after transmission through one exterior wall/window. Some of the additional range is due to using the 433MHz version of the RFM12B compared to the 868MHz operating frequency that the XRF defaults to. The range measurements were not very scientific and further work is required before meaningful conclusions can be drawn regarding the comparative ranges. However these initial results have encouraged me to investigate replacing the XRF by the RFM12B, particularly as it is both cheaper and uses less power. A comparison of the basic specifications can be found at http://blog.homelabs.org.uk/wireless-connectivity/.
As I have already deployed a few magnetometers using the Ciseco XRF module I would like to to use the RFM12B as a serial device. This would enable the existing firmware to be used with minimal changes. It would also allow the possibility of having a single firmware support both XRF and RFM12B modules.
Serial emulation
I have created a serial emulation layer for the RFM12B by deriving a class (RF12_Stream
) from the Arduino Stream
class. Text or binary data can then be read from or written to the RFM12B in exactly the same way as the standard Serial
port. Since it is a Stream
object the Streaming
class (which overloads the >> and << operators) can also be used with RF12_Stream
. The RF12_Stream
class automatically breaks up the data to be transmitted into short packets which are sent using the Jeelab RF12 library. ACKs and retransmissions are employed to prevent losing data from dropped packets. A packet number is included to prevent duplicated data, which could otherwise occur for the case when the ACK is not received and a packet is retransmitted. The class keeps track of the number of packets sent and received, and the number of retransmissions, data which may be useful to identify the optimal channel on which to operate.The
begin()
function takes different parameters to Serial.begin()
and it returns a logical value to indicate whether the RFM12B has been found on the system. The user is required to call the poll()
function periodically so that outgoing packets are sent and received packets processed. These are the only differences compared to sending data to the standard Arduino Serial
port.Source code for the
RF12_Serial emulation
can be found on Github, https://github.com/stevemarple/RF12_Stream; it is released under the MIT license. An example sketch is included which echoes data between the Arduino serial port and the RFM12B. When compiled for the ATtiny84 this sketch is less than 8kB so I am hopeful it can be used on the RFM12B to Raspberry Pi expansion board designed by Martin Harizanov. AsyncDelay
, https://github.com/stevemarple/AsyncDelay, and CircBuffer
, https://github.com/stevemarple/CircBuffer, are also required.Calunium uses
INT2
for the interrupt from the RFM12B which is not supported by the JeeLabs version of the RF12 library so I am currently using a modified version. Source for this version is also available on Github, https://github.com/stevemarple/RF12. It is intended that RF12_Serial
should work with both the original RF12
library and my version.Single firmware to support RFM12B and XRF
By utilising the return value from theRF_Stream
begin()
function it becomes trivial to produce a single firmware which can support either the RFM12B or XRF radio modules. The trick is to create a Stream
reference which is set to either Serial
(for the XRF) or to rfm12b
. The RFM12B_autoselect
example sketch illustrates this concept.How does it differ from RF12sio
?
The RF12sio
library overloads the << and >> operators so that packets can be constructed and processed easily. The user is still responsible splitting the data into packets. RF12sio
is not derived from Stream
so it is not possible to use the Stream
pointer trick shown in the RFM12B_autoselect
sketch.Credits
Thanks to JeeLabs and JC Wippler for the RF12 library and to Arduino for the standard Arduino libraries.