RF12demo is name of the firmware which comes pre-loaded on all JeeNodes and JeeLinks. It was originally intended just for demonstrating the features and wireless capabilities of JeeNodes, but over the years it has evolved to become a fairly useful package of its own, especially for central “master” transmit/receive nodes attached to a PC or laptop via USB.

What it is

RF12demo offers a command-line interface to control wireless radio modules, either an RFM12B or an RF69CW from HopeRF, as well as a few compatible chips.

The main purpose of RF12demo is to configure the wireless radio module, to report incoming packets to the serial port, and to send out packets via commands from that same serial port.

There are a number of other commands, to configure the radio, to define some preferences about how to report the packets, and which ones to report. There are a few commands (currently for RFM12B only) to put the radio in a special OOK mode to send out non-RF12 type messages to FS20- and KAKU-type remote RF switches.

RF12demo is a “sketch”, meaning it is written for and with the Arduino IDE, and can be compiled and uploaded into the JeeNode/JeeLink by that same IDE.

What it is not

RF12demo is general purpose, in that it can deal with any packet in or out of the radio module, but it cannot decode the packet into a meaningful format. If you have a remote node sending sensor data, then all you’ll get from RF12demo is a series of bytes representing that data, looking something like this:

OK 4 1 129 166 0

Likewise, to send out a packet with the same content to a remote node, you’d enter a command specifying the individual bytes, perhaps something like:


That’s a 4-byte packet (containing bytes 1, 129, 166, and 0), broadcast to all listening nodes, and identified as coming from node 4.

So RF12demo is a generic interface for the wireless radio. It’s not a decoder or encoder to make any sense of the bytes in that packet. For that, you’ll need to interpret those bytes, and figure out that it represents sensor values (in this case: temperature, humidity, light levels, and motion). That’s one of the things [[HouseMon:]] does, but you can of course use any computing environment and programming language you like.

RF12demo just lets you send and receive bytes, it has no clue to what they represent.


There have been several versions of RF12demo over the years:

  • RF12demo v10 - pre-loaded in 2012 / 2013 on most JeeNodes and JeeLinks (RFM12 only) - download
  • RF12demo v11 - adds “v” command to print the version, some bug fixes (mid 2013 - RFM12 only) - download
  • version#8 - frequency offset and RF69-compat support, also runs on JNµ’s ATtiny84 (early 2014)

Version 12 incorporates several improvements and extensions by @JohnO, from the RF12demo branch.

Getting started

If you have obtained two JeeNodes or JeeLinks from JeeLabs, then the RF12demo sketch will already have been pre-loaded onto them. Even if you’re soldering it all together, such as when using the JeeNode v6 through-hole kit, the ATmega is all set up to start running RF12demo when powered up.

To see RF12demo in action, you need to connect to the JeeNode/JeeLink via a serial USB connection. One way to do so, is through the Arduino IDE:

  • Select the new entry that appears in the device tables when the USB cable connection is first made (Tools-> Serial Port->….).
  • Start up the Serial Monitor (Tools-> Serial Monitor).
  • Check the serial connection speed (a.k.a. baud rate) to 57600 (lower right control on the Serial Monitor screen).

If you have everything set up right, the connection to your JeeNode is launched and ready to accept command input.

A proper connection will show the following greeting on your screen:

The first line contains information about software version and the current configuration settings:

[RF12demo.11] A i1* g5 @ 868 MHz

The rest of the page is a brief help text, describing all the available commands. Whenever you type an unknown command, or “?”, this help text gets repeated.

A first test

The first test you’ll probably want to run, is sending a message from one node to another. You’ll need to have two JeeNodes or compatibles working, with the RF12demo sketch running on both.
If you have only a single node, or suspect a node problem, there is a limited test available for the receiver section only - select quiet mode OFF with the ‘q’ command. There is usually enough random noise in the channel to occasionally decode a “noise” packet - this is prefaced by ‘?’ to indicate the junk packet not surprisingly failed the CRC test. The Rx section is working. If you see a continuous stream of ‘?’ packets, this is symptomatic of a high noise level in the channel and will make correct reception intermittent. Selecting an alternative channel with the ‘O’ command may put you into a channel with less interference.

Who connects to whom

To be able to exchange packets, there are a few requirements:

  • Both nodes have to be set to use the same frequency, selected from the same ISM band (433, 868, or 915 MHz). While the radio chips themselves can be set to any of these bands, the antenna matching circuitry on the module only works well in its specific frequency band. Note that different regions in the world allow/disallow different bands - in brief: 868 MHz for Europe and 915 MHz for North America, Australia etc. The often busier 433 MHz band is available in many countries also - you must check your specific country regulations before operating even these relatively low power/low range modules.

  • Both nodes have to be in the same “net group”. Net group is purely a software convention, coded as a number between 1 and 250, sent out as part of the packet. The radio modules will ignore all incoming packets other than the net group for which they have been configured. This makes it possible to run multiple networks in the same area, sharing the RF space, but each acting independently with only “their own” nodes seeing each other.

  • Nodes have to be assigned a “node ID”, which is a number between 1 and 30 (31 has a different behaviour, described later on). It is not strictly necessary to give each node a different node ID, but it’s the least confusing way to get started.

The way to set these values with RF12demo is with the “b”, “g”, and “i” commands, respectively. To set a node to work on 868 MHz, net group 5, node 17, you can enter the following three commands:

8b 5g 17i

These settings are stored in EEPROM, which means that they will persist across resets, and will also be retained across power down. Simply set these values once for each of your wireless nodes, and you should be all set to make them work together.

Stay within the ISM band marked on your RF Module, that is what it is tuned for (the colour code is Green/433 MHz, Yellow/868 MHz, Red/915 MHz). For experimenting, you can run in a different band from that marked, but the RF module tuning circuits are well out of specification, significantly reducing the connection range to a little as a few meters. Avoid running RF modules at high power settings without a matched antenna connected - there is a risk of permanent damage to the transmitter output stage(s) on the transceiver chip.

Setting up the two nodes

For this first test, you need two nodes and they have to be powered up and properly configured, but you don’t need to have them both connected to a serial port. There is a test command “t” in RF12demo, which sends out a packet with test data, and requests an “acknowledgment” from the other side. This is a common way to find out whether the other side got the packet successfully. The other side immediately sends a special small packet back, acknowledging proper reception.
Time to try it out:

> 0t
test 0
 -> 66 b
OK 193

Let’s go through this step by step:

  • > 0t - this prompt is displayed by RF12demo to show what command it has received (“0t” is equivalent to “t”)
  • test 0 - this is the first test (the number will increase with each “t” command)
  • -> 66 b - a quick confirmation that a 66-byte packet has been sent out
  • OK 193 - success! - this is the incoming “ACK” packet: a special header code, but no data bytes

That “193” value is the decimal representation of a byte with several bits set. If we decompose this as binary, it’s: 128 + 64 + 1. These values have the following meaning:

  • 128 = RF12_HDR_CTL, i.e. this is a special control packet (an ACK)
  • 64 = RF12_HDR_DST, i.e. the lower bits represent a _destination+ node ID
  • 1 = this packet is intended for node ID 1, which is indeed the number assigned to this node

Destinations versus broadcasts

The wireless driver has some conventions. One of them is that a packet contains either a destination node ID or a source node ID, not both.

> If you need both: set the destination in the header, and include the source ID in your own packet “payload”

In a sensor network, the most convenient mode is when remote nodes broadcast their data to whoever wants to receive it. This is done by “sending” to node ID 0. The driver recognises this special case, and replaces the ID in the header with its own ID, in essence re-using those bits as a source ID.

Conversely, a central node often wants to address a specific node, which it can do by filling on the header with that ID and setting the RF12_HDR_DST but (i.e. adding 64). For example, to send to node 2, you’d send a command of the form ...,...,66s to RF12demo.


Use with RFM69 radio modules

This is the radio module specific configuration setting in the RF12demo.ino sketch:

#define RF69_COMPAT 0

Set this to 1 to build a version which works with RFM69 radios in “RF12 compatibility mode”.
This drives the radio in such a way that it can send and receive packets in the same formats as RF12-based nodes.
You will benefit from the RFM69’s higher sensitivity and RSSI signal strength reporting, but this is not its full “native” mode.

Use with JeeLink

Changing this setting to 16 (matches the 16 Mbit flash chips on JeeLinks) enables the Dataflash packet logging code:

#define DATAFLASH 0

This enables a few more flash manipulation commands in the RF12demo.ino sketch.

Use with ATtiny

There is also a #define TINY option, which is enabled when compiling for the ATtiny84 used in the JeeNode Micro.
This is not completely supported however - just a first step to produce a downsized variant of RF12demo for use on ATtiny’s.

Command reference

Commands are entered in the following form:

 ","  "," ... ","  

Where arg1 .. argN are decimal byte values in the range 0..255, and command is a single letter or special character.
Most other character values (including spaces, tabs, and newlines) are ignored, you can type “?” to see a brief command summary.
For the “o” command (frequency offset), the argument can be in the range 96 to 3903.

Commands are echoed with a leading “>” followed by any output they generate.

All configuration settings are stored in EEPROM and will be restored after a reset or power-cycle.

Basic configuration

<bb> b - Set the frequency band

Set the frequency band used by the radio for reception as well as transmission.
Use 4b for 433 MHz, 8b for 868 MHz, or 9b for 915 MHz.
Note that each radio is built for a specific band - using it differently leads to severely reduced range.
See also the “o” command for precise freqency adjustments (RF12demo.12 and later).

<gg> g - Set the network group

Set the net group used by the radio - only nodes in the same group can see each other.
The net group should be a value from 1 .. 250.

Net group “0” is special: it puts the radio in promiscuous mode, receiving data from all net groups.
This is usually not very effective, due to the large amount of false triggers and noise received.
You can try to reduce output from false hits with the “0q” command, but it won’t improve the accuracy of reception.

<nn> i - Set the node ID

Set the node ID of this radio, the value should normally be in the range 1 .. 30.
Node ID “0” is special, in that it puts the radio in OOK transmit mode (not very useful in RF12demo).
Node ID “31” is also special: it will cause the radio driver to accept all packets in this net group, including those sent to other nodes.
This form of promiscuous mode is useful for central nodes, to make them aware of all communication in the same net group.

Sending packets

t - Send a test packet

...,<nn> s - Send one packet as is

...,<nn> a - Send one packet, request ACK

<bb>,<gg>,<nn>,<hh>,... > - Send one packet from a specific band/group/node

Output format

Incoming packets are reported as lines starting with “OK”, “OKX”, or “ASC” (see the “x” command).
Dataflash information is reported as lines starting with “DF”.
Packets with an invalid checksum or length are reported as lines starting with " ?" if enabled (see the “q” command).

<0/1/2> x - Report incoming packets as decimal, hex, or ASCII

The default mode is to display each byte in decimal (“0x”):

OK 9 117 146 63 235 196 64 183 3 22 126 224 27

When you set the mode to hex (“1x”), you will get lines like this instead:

OKX 0975923FEBCD401E04187E101C

There is also an extended-hex mode (“2x”), which adds a second line showing the ASCII text:

OKX 0975923FEBCD401E04187E101C

RF69-compat mode only - the output includes an RSSI (signal strength) value at the end of each output line:

OK 9 117 146 63 235 196 64 183 3 22 126 224 27 (-69) 
OKX 0975923FEBCD401E04187E101C (88) 

In decimal mode, the RSSI is shown in dBm, in hex mode it is the raw info (in half-dBm steps).

<0/1> q - Enable or disable quiet mode

Quiet mode (“1q”) disables the output of packets with an invalid length or checksum.
This is the default as of RF12demo.12 - with “0q”, you’ll see the bad packets as well:

? 44 29 74 208 0 0 2 34 218 34 96 121 32 0 83 32 149 133 48 60 64

These reports are not very useful, as the radio’s AGC will even make it accept noise if nothing else comes in for a while.

Collect mode

<0/1> c - Enable or disable collect mode

The default mode (“0c”) will send back an empty acknowledgement packet when it receives a packet asking for an ACK.
This is useful for nodes to make sure that their packet has been correctly received. It’s used by the “easy transmit” functions.

With broadcasts, the use of this default mode is somewhat limited, since there is no way to tell which node will send the ACK.
So for “the” central node (usually with node ID 31), “0c” is a good setting, but for all the other nodes “1c” is more useful.
This will prevent them from responding to such ACK requests. It’s also useful for listening in on a wireless network without disturbing it.

Collect mode must also be turned on (“1c”) when ACKs are generated by the host i.s.o. RF12demo, possibly including a payload.

OOK mode

<hchi>,<hclo>,<addr>,<cmd> f - Send one OOK packet, FS20 protocol

Using some special trickery, the RFM12 is able to send out a signal which resembles an OOK transmission.
This has been used to implement OOK sending for FS20-type home automation devices, such as RF-controlled switches.

Note that the RFM12 is not able to receive OOK packets without hardware modification.
See the Receiving OOKASK with a modified RFM12B and RFM12B OOK-receiver with op-amp pages.

<addr>,<dev>,<on> k - Send one OOK packet, KAKU protocol

Even more trickery is needed to send out OOK packets which can be picked up by a “KAKU” RF power switch.
The range will usually be very limited, since the radio needs to be set briefly to 433 MHz for this purpose.

Fine tuning

<N> o - Adjust the precise frequency setting

This is a new feature of the RF12demo.12 version. It allows adjusting the precise frequency used by the wireless radio.
It can be used to optimise range between any specific pair of radio’s, to correct for any differences and drift of their crystals.
The exact frequency used will be shown, i.e. for “1605o” on 868 MHz:

868.0250 MHz

The default setting is “1600o”, i.e. 434.0000 / 868.0000 / 912.0000 MHz, depending on the current frequency band.

See the Frequency Offsets section on this page for more details.


d - Dump all replay log markers

Show the list of “DF” replay markers currently stored in dataflash memory. For use with the “r” command.

<sh>,<sl>,<t3>,<t2>,<t1>,<t0> r - Replay from specified marker

This allows “replaying” stored data from flash memory. This mechanism can be used to leave a JeeLink with dataflash running unattended, and then pick up a log of all the packets received afterwards. By examining the “DF” markers in the output, an application can determine which data it has already received, and use this “r” command to obtain only the new packets received since the last time.

123,<bhi>,<blo> e - Erase one page in dataflash memory

Erase a single page of dataflash memory (usually 4 KB). For special use only.
Due to the loss of some stored, you have to include the extra “123” arg to trigger erasure.

12,34 w - Wipe entire dataflash memory

This erases the entire dataflash memory (the process takes a few seconds).
Due to the loss of the entire replay history, you have to include the extra “12,34” args to trigger erasure.


v - Display the version and settings

As of RF12demo.12, this displays the version of the code as well as the current configuration:

[RF12demo.12] A i1* g212 @ 868 MHz c1 o1599 q1 x1

Only settings which differ from the default are shown. Here is one with everything set to default:

[RF12demo.12] A i1 g212 @ 868 MHz

For backward compatibility, the “*" after the node ID is shown when collect mode (“1c”) is set.
<0/1> l - Turn activity LED on or off*
If there is an LED on PB1 (Arduino digital pin 9), you can turn it on with ”1l" and off again with “0l”.
This can be used to verify proper reception and execution of serial port commands.
The LED, if attached, will also be turned on briefly during each packet reception.

123 z - Total power down

This requires a complete power recycle (e.g. extract and re-insert into the the USB connector) to restart


Use of the RF spectrum

All accessible RF spectrum is busy with other users, mostly intentional and some from out-of-specification transmissions straying from their bands allocated by ITU-R. In addition, there is natural RF ‘noise’, for example from active thunderstorm cells - even the Sun pours RF energy down on us! This interference is joined by other, controllable sources like flickering fluorescent lighting and badly-filtered brush motors, even your laptop.

The objective is to get some information between two points by generating a coherent RF signal and reliably recovering that information at a remote receiver, despite all of the possible interference. In this case, the licence-free, ISM frequency allocations are used. A Band simply refers to the spectrum ‘space’ for use by transmitters tuned between the allocated upper and lower frequencies .

The ISM bands are free to use provided you follow some rules about the maximum power of your transmitter, its duty cycle and the type of information exchanged. Free inevitably means busy. There are a set of conventions used in an attempt to keep separation between multiple users competing in the same band for access to the RF spectrum so as to share this limited resource effectively.

Explanation of Terms

Here are three of those conventions used by the JeeLabs software driving a hardware RF module:

  • A Node ID is just a software convention to mark sets of nodes when there are several distinct things talking as a cluster of devices. This is done by marking a Node ID value in the header of the transmitted packets.
  • A Net Group is also just a software convention that defines members of a particular cluster. Similarly this is done by including a group ID value at the very start of the transmitted packets. All packets still share the same RF channel (defined by the xxxMHz used at module/library initialisation time) so different groups just organise the RF channel use without increasing its total capacity.
  • An RF channel is the centre carrier frequency PLUS the sidebands. These sidebands surround the carrier, generated when impressing the data stream of a packet on to the carrier. This process is called modulation of the carrier - it is the coherent RF energy in the sidebands that contains the information stream. Provided that different carriers are spaced far enough apart that these sidebands do not significantly overlap, you can have a set of transmitting/receiving nodes communicating completely independently of other sets. You can continue this segregation of traffic until you run out of “not busy”channels in the allocated ISM band.

Splitting traffic this way multiplies the available bandwidth by ~ the number of distinct RF channels you decide to use. The only disadvantage is that you will need with JeeNode implementations, one dedicated listener/control node for each RF channel. This might then require combining the aggregate traffic in software if the total traffic is of interest, for example when a central location monitoring many hundreds of remote nodes.

Net groups and node ID’s

The RF12 driver supports up to 250 different net groups, each with up to 30 different node ID’s, so theoretically there can be up to 7,500 individually addressable nodes, all in range of each other. That’s not the whole picture though - see below for more details how the limited number of channels in the ISM band (described above) imposes limits on very large node count clouds..

Each net group must be in the range 1 .. 250. Nodes in the same net group can “see” each other, i.e. send and receive packets between each other, whereas nodes in a different net group will never pick up packets from a cluster that has a different net group value.

Each node ID must be in the range 1 .. 30. There are two special reserved node ID values:

  • node ID 0 is exclusively for OOK modulation usage (all other Node ID’s are using some variant of FSK modulation.)
  • node ID 31 is used exclusively for promiscuous mode in that it accepts any packet in the same net group, regardless by whom or to whom it is sent.

Frequency offsets

The allowable values for the transmitted carrier frequency are defined by the ISM band allocations. Do not use a carrier frequency close to the edge of the band without allowing for the sidebands produced during FSK or other modulation, including OOK. All modulation schemes create energy at frequencies around the carrier, called sidebands. Significant sideband energy must not spill over into adjacent bands - this will interfere with other, ITU non-ISM radio spectrum allocations.

These band limits map to offset adjustment in RF12demo as follows:

  • 433.05 – 434.79 MHz (ETSI EN 300 220 - 433 MHz band) - Offset range 1220-1916
  • 863.00 – 870.00 MHz (ETSI EN 300 220 - 868 MHz band) - Offset range 96-2000
  • 902.00 – 928.00 MHz (FCC Part 15.247; 15.249 - 915 MHz band) - Offset range 267-3733

Eeprom Layout

byte 0x000 Undefined
byte 0x010 Undefined
byte 0x020 Node number in bits        ***n nnnn  1 - 30
           Reserved                   **0* ****  Reserved 
           Band to use                00** ****  Don't use, unsupported 325 Mhz band
            "                         01** ****  433 MHZ  0x40
            "                         10** ****  868 MHZ  0x80
            "                         11** ****  915 MHZ  0xC0
byte 0x021 Group number               1101 0100  // 212 0xD4
byte 0x022 Eeprom format              MMMM mmmm  Major/minor version
byte 0x023 Hex output style           01** ****  1: Hex output, 2: hex+ascii
           Collect Mode               **1* ****  Don't send acks
           Quiet mode                 ***1 ****  Don't report bad packets
           Reserved                   **** 0000  Reserved  
word 0x024 Frequency offset LSB       llll llll  Frequency offset word
 "   0x025 Frequency offset MSB       mmmm mmmm
     0x026 Padded at the end with NUL 0000 0000
     0x02D Padded at the end with NUL 0000 0000
word 0x02E CRC                                   CRC of values w/ offset 0x020-02F
 "   0x02F  as above
byte 0x030 Reserved
     0x03F  as above
byte 0x040 Key storage for encryption algorithm
     0x04F  as above
byte 0x050 Reserved
     0x400  as above

Also available in: PDF HTML TXT