Computing stuff tied to the physical world

Using RFM12’s with RFM69 native

So far so good – we now have the RFM69 running in native packet mode using the RF69 driver, for LPC8xx ARM µC’s, ATmega328 JeeNodes, and Raspberry Pi’s w/ RasPi RF.

But let’s not leave the RFM12 modules behind, and the many Arduino IDE projects using the RF12 driver in JeeLib. If only it could send and receive native RF69-type packets!

Well, it turns out that the RFM12B wireless module can be tricked into doing just this. There are several issues involved:

  • the frequency, FSK swing, and bandwidth can be chosen to match the RFM69
  • likewise, the preamble and sync bytes can be chosen to work with both modules
  • the RFM69’s CRC can be computed in software (it’s not the same as in RF12!)
  • the data whitening used in the RFM69 can also be emulated in software
  • and lastly, differences in packet / header layouts can all be handled in software

Quite a few differences, but by carefully choosing the parameters on both types of modules, we can indeed get packets across in both directions. An updated RF12.cpp driver has been committed to GitHub with all the necessary changes.

To enable this “native + RFM12 + RF12 + Arduino + AVR” mode, change one define in RF12.h to set RF12_COMPAT to 1 (not to be confused with RF69_COMPAT mode!):

#define RF12_COMPAT 1

Note that this change needs to be made in JeeLib itself, you cannot simply add such a define to your own sketch. The reason for this is that the changes are much more pervasive.

The result is an “RF12 driver” with a virtually unmodified “RF12 API”, i.e. you can poll using rf12_recvDone(), etc – just as you would with a classic setup.

But there are some important differences when using RF12_COMPAT mode:

  • the packet layout is different (rf12_len and rf12_hdr are defined differently)
  • there’s a new rf12_dst field, the lower 6 bits contain the destination node ID (or 0)
  • the lower 6 bits of rf12_hdr always contain the node ID of the sending node
  • RF12_HDR_ACK is defined as bit 6 (this is bit 5 in classic mode packets)
  • RF12_HDR_DST is no longer present, since there is now a rf12_dst field

The RF12_ACK_REPLY test is not working right now, due to the above flag bit changes.

For an example, see the new rf12compat.ino sketch:

#include <JeeLib.h>

MilliTimer timer;

void setup() {
  rf12_initialize(63, RF12_868MHZ, 42, 1720); // 868.6 MHz for testing

void loop() {
  if (rf12_recvDone()) {
    Serial.print(rf12_crc == 0 ? "OK" : " ?");
    Serial.print(" dst: ");
    Serial.print(rf12_dst, HEX);
    Serial.print(" hdr: ");
    Serial.print(rf12_hdr, HEX);
    Serial.print(' ');
    for (int i = 0; i < rf12_len && i < 66; ++i) {
      Serial.print(rf12_data[i] >> 4, HEX);
      Serial.print(rf12_data[i] & 0xF, HEX);
  if (timer.poll(1000))
    rf12_sendNow(0, "abc", 3);

Here is some sample output, receiving packets from a Micro Power Snitch:

OK dst: 80 hdr: 3D 1EBFCFEF01
OK dst: 80 hdr: 3D 1EBFCFEF41
OK dst: 80 hdr: 3D 1EBFCFEF81
OK dst: 80 hdr: 3D 1EBFCFEFC1
OK dst: 80 hdr: 3D 1EBFCFEF01

The destination is 0x80 & 0x3F => 0, i.e. this is a broadcast.
The sending node ID is 0x3D & 0x3F => 61, i.e. the sender’s node ID is 61.
The rest is the 5-byte payload (4 h/w ID bytes, and type 1 = MPS with 2-bit sequence).

Some code refinements are still needed – the exact settings have not yet been optimised for both modules to inter-operate as well as possible. This results in some packets still being missed (IOW, the CRC not matching up). Also, as usual with the RF12 driver, there are occasional noise packets coming in (again with non-matching CRC, and easily flagged).

But as you can see, the basic mechanism is working: RFM12B-based nodes can successfully participate in a network designed for RFM69’s, all running in native packet mode!

In summary, the RF12 driver in JeeLib can now be used in three different ways:

  • as is, the “traditional” mode: classic + RFM12 + RF12 + Arduino + AVR
  • in RF69_COMPAT mode: classic + RFM69 + RF12 + Arduino + AVR
  • in RF12_COMPAT mode: native + RFM12 + RF12 + Arduino + AVR

The two compatibility modes are a compromise compared with an all-RFM12 or all-RFM69 network, simply because these modules are being pushed in some very unusual ways using various software tricks, but these modes should nevertheless come in handy for existing networks, where you don’t have the option to choose 100% uniform hardware.

[Back to article index]