IntroductionFor 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 emulationI 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 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.
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
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.
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 XRFBy utilising the return value from the
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_autoselect example sketch illustrates this concept.
How does it differ from 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
Thanks to JeeLabs and JC Wippler for the RF12 library and to Arduino for the standard Arduino libraries.