RFM69 TX power testing & library fix

The RFM69 library has been very robust and stable over the years. It is widely used in many hobby and home automation projects as well as research and commercial products. But that doesn’t mean we can’t find occasional things to fix and improve!

Is there a problem?

Recently, after renewed attention to a long time issue relating to power levels being incorrectly set, I took measurements and found the setPowerLevel() function was behaving somewhat unexpected. Instead of a smooth  Namely it as making available the lowest possible transmit power levels on the HW/HCW (aka high power) variants of RFM69. Since a commit in 2015 the 32 power levels were actually made into 16 steps and only using PA1+PA2 in high power mode. Not so much a loss except for those hoping to maximize battery life by running at the lowest power levels on the HCW – in which case they’d be better off using the CW instead. But this is enough to find a fix and take full benefit anyway of what the HCW has to offer.

Basic TX power testing

To produce power profile I put together a set of Transmitter and Receiver examples. To measure power output you can just use the transmitter sketch – it toggles TX mode and you can navigate the power levels from min to max. Below is a simple hardware test setup that can be used to take some power measurements: a CurrentRanger reads the current going into a Moteino+RFM69HCW that radiates an unmodulated carrier signal into a dipole. Idle MCU current (TX off) is read and then subtracted from total current with TX enabled:

To also measure RSSI (poor man’s power meter) we can just use another Moteino with the receiver sketch mentioned above, which will simply sample RSSI continuously (in RX mode), at a max AGC setting of -48dB to simulate a long “distance” since we’re doing all this in close proximity (the same room!). Open the transmitter sketch in a serial terminal and toggle TX mode with t and increase power with + & - in steps or < & > in dB – there is a new function setPowerDBm() in RFM69 library v1.5.0, in addition to setPowerLevel(). The CurrentRanger will show the current drained by the Moteino when transmitting at different levels and the RSSI on the receiver will also reflect different output power levels.

This setup produced the following power profile on the W/CW radio, nothing unexpected since there’s only PA0 to be used with no other registers to set, power levels being set in RegPaLevel.OutputPower. The only thing to notice is the ‘step’ in TX current and RSSI which indicates something’s definitely being switched inside the transceiver itself as _powerLevel crosses the middle of the RegPaLevel.OutputPower register, even if PA settings remain unchanged (only PA0 is used).

On the HW/HCW, in v1.4.3 (prior to the fix this blog is about) the power profile looked like this:

As it turns out the startup power is correctly set to a valid level 31, but calling setPowerLevel() even once results in values being set from 0-16 (all “forbidden” – see tables below) and never back to the original 31. This results in a ‘step ladder’ of transmit power levels vs. current. I know this sounds confusing, because it is.

The theory – datasheets and registers

To better understand what’s really going on, first we need to clear some confusion and understand that RFM69 radios have several possible transmitter PA (power amplifier) combinations for different output power profiles as outlined in the datasheet:

For W/CW radios things are very simple – only PA0 is wired to RFIO output pin and it can produce from -18 to 13dBm, corresponding to 32 possible power levels that can be set in RegPaLevel, as clearly reflected in the W/CW graph above.

For RFM69 HW/HCW radios things get more complicated, there are two possible PAs  and a power boost mode to be enabled to reach the highest output of 18 to 20dBm, according to section 3.3.7:

I know of only one other good article that outlines all this in detail, a blog by Andre Hessling, I found it accurate and so my focus is not to replicate that here, but rather use it as reference and complement for those wanting to get a full picture, so check it out if you want to get more in depth.

So!  The RFM69 library v1.4.3 and prior, has been only using PA1+PA1 in boost mode, at power levels 0-16, except at startup where _powerLevel was initialized and set to 31 and never divided by 2 like in setPowerLevel() – bug!.  In addition, the datasheet says levels below 16 are off limits for the PA1+PA2 combination, but because this works it went unnoticed for a long time, at least in my library (semi bug?). If you’ve read Andre’s article, you will notice PA1 alone can be used and he proposes using the following PA combinations for HCW:

  • PA1 (and PA1 only!) from -2 to 13 dBm output
  • PA1+PA2 from 14 to 17dBm output
  • PA1+PA1+HighPower for 18 to 20dBm

If we revisit the datasheet, we realize there is actually a power profile overlap between these 3 combinations:

Notice for instance we can achieve -13dBm in 3 different ways on the HW/HCW:

  • using PA1 only with RegPaLevel.OutputPower=31
  • using PA1+PA2 with RegPaLevel.OutputPower=27
  • using PA1+PA2 with RegPaLevel.OutputPower=24

Enough already, what’s the conclusion?

Since theoretically the output is the same, it would be interesting to see the current profile against each of these as well. To cut this (really) short, I will link the spreadsheet with my tests and graphs and just mention the final conclusions. It matters which PA combination you pick, as a general rule, using more than one PA will result in higher current for the same effective transmitted output, at first this seemed counter intuitive but that’s what the meter and RSSI shows. I determined the best combination for HW/HCW to be the following:

If you notice, there are now only 24 _powerLevel‘s with slight overlaps between steps 14,15 and 16,17. The light orange band PA1+PA2 combination is sandwiched between PA1 and PA1+PA2+HighPower and helps optimize current used at those theoretical dBm outputs. This is similar but a little different than Andre’s proposed bands – I suspect he may have looked at RSSI but not at current used. Overall this produced the smoothest output power vs. RSSI vs. current curves that I could determine – with minimal ‘step’ jumps on the current and RSSI, and this is what we’d expect to properly use the power levels, especially in the RFM69_ATC extension which automatically regulates the power level based on a desired RSSI. And here are the measurements in a graph:

For the W/CW nothing really changes since there was no real issue, the graph will be the same as the first one included in this article.

Update the library and test on your own!

I made a new release v.1.5.0 which should address all these issues and includes the TX power testing examples which can be used by anyone with perhaps different/better test setups to verify these findings. Please update  and try this out. I may update this blog with further info if need be in the future since it’s more of a reference for RFM69 PA modes.

RFM69 and SPIFlash libraries released via Arduino LibraryManager

The LowPowerLab RFM69 and SPIFlash libraries are now published to the Arduino Library directory, and available to install in the IDE’s Library Manager (under Tools>Manage Libraries). Note that if you already have these library installed manually, you may need to remove it and re-install using the manager:

As new versions are released, you can update to the latest or switch back to an older version if you have a need to do so. If you’re new to using the Library Manager, it’s worth to read the official Arduino Library guide, and also check the Library Manager FAQ, to understand how Arduino libraries work, and how manage them (adding, switching, updating, manual library installation, deleting local libraries, etc).

As usual, please report any issues or bugs in the forum or open a Github issue where appropriate.

RFM69_ATC: Automatic Transmission Control

There is now a new extension to the RFM69 library. It’s called RFM69_ATC aka Automatic Transmission Control. Many thanks to Tom Studwell who implemented this and shared it in the forum. The basic idea behind this extension is to allow your nodes to dial down transmission power based on the received signal strength indicator (RSSI). For instance a sleepy battery node like a MotionMote sits still inside the home and usually has a very strong received signal, somewhere in the range of -30 to -40dBm when transmitting at full power. You could manually tune that down using radio.setPowerLevel(..) in code but its tedious and is a static change, if you move the node or conditions change it will not be smart to adjust the power level to the new environment. However with RFM69_ATC this is done automatically for you, you just need to indicate a target RSSI. On each packet sent and ACK received (using sendWithRetry(…) is required), the node analyzes the actual RSSI and continuously adjusts its own transmission power level of the RFM69 transceiver to attempt to match the target RSSI (+ or -). This way that end node is only “loud” enough to be heard by the gateway, not much louder. Close by nodes can “whisper” while nodes farther away or with more obstacles will “speak up” as necessary but avoid that default fixed maximum “screaming” level. This is “polite” in terms of “RF pollution” and efficient in terms of power consumption. Even non-battery nodes where power is no problem should implement this for the sake of the “polite” factor.

I have updated the Node and Gateway examples to have ATC enabled, and also the MotionMote example is now ATC enabled, in this case with a target RSSI of -90dBm. The noise floor is somewhere around -100dBm with the default RFM69 lib settings, so for static nodes that won’t experience a lot of movement or temperature drifts, a -90dBm target is pretty safe. That will keep the transmitter power to a minimum and save power. We know that the greatest toll on a battery powered node are the spikes of current used when the transmitter is active (up to 130mA for RFM69HW). Reducing the transmit power level to the minimum required will exponentially reduce that spike and result in longer battery life and a more “quiet” sensor network that won’t reach across your whole neighborhood. This is really awesome!

Here is a sample transmission using the Gateway and Node examples linked above. Note how the node starts transmitting at full power, then dials down power to match a test RSSI target of -68dBm. This is output from the Gateway end:


There are a few required changes to a sketch where you want to use ATC:

  • you must #include <RFM69_ATC.h> in addition to #include <RFM69.h>
  • you must use RFM69_ATC radio; instead of RFM69 radio;
  • for the gateway/receiver end the above two changes are sufficient, for the end node that does the power level adjustment you must also do the following:
  • in your setup() function (after all RFM69 initialization is complete) call this function to set your target RSSI: radio.enableAutoPower(targetRSSI);
    • targetRSSI is a negative integer, should be from very strong (-30) to very weak (-95). Usually you would want to be closer to the noise floor end (-100) since you want to reduce transmit power to the bare minimum
    • this is a one time call that enables the dynamic adjustment of the output power on that node
  • you must use radio.sendWithRetry() instead of just radio.send() or a combination of radio.send() and radio.receiveDone() for the radio to be able to receive the important headers from the gateway that tells it how to handle its power, this was done in the MotionMote example linked above

Once these changes are implemented, the node will start to progressively dial down power (assuming it starts transmitting at full power) with each packet sent, until the RSSI meets the target. When the RSSI is below the target power is dialed up again and so on, in an attempt to stay as close to the target as possible.

In the examples that I mentioned there is a pattern that I followed by implementing a define directive (#define ENABLE_ATC) which when left uncommented will enable ATC at compile time, if removed/commented the sketch will run normally without ATC. As always, bug reports, suggestions and contributions are welcome, the forum is the best place for that purpose.

I must mention here that at this time I have only partially implemented his variant with some adjustments to Tom’s implementation (I left the differences commented out in my version). For now I chose to leave my power control resolution as is. He actually went into more detail allowing a finer control of the power control – this is because of the differences between RFM69W and HW which handle output power control differently. If you’d like to try his variant with that extra control check this forum post or his Github repo. Thanks Tom for your great contributions and inspiring this piece of work and also the awesome forum projects you’ve posted!

Closing the security gap

HTTP(S) and Websockets Security

There are a lot of open source home automation attempts out there. Many are missing some essential security that leaves them vulnerable. Those that actually allow the user to control physical things in their home are especially vulnerable. An attacker could gain control and cause an appliance to turn on-off repeatedly causing a hazard, could gain access to the home by opening a garage or door, or could just watch for human activity for other evil purposes.

I knew that getting ahead of the crowd meant imposing some strict requirements including physical and virtual security to restrict access only to those authorized and minimize the chance of an attack.

Sure, anyone can add some authentication, not a big deal. And it’s not too hard to add SSL. I had thrown web sockets in the mix for real time updates (cf polling as a method of “updating” on end clients). So web sockets had to be secured as well. Since the node.js websocket server runs on a different port than the webserver, rather than securing two channels of communication (webserver and websockets) I implemented what I believe is the first OSHW home automation interface with real realtime two-way communication between the webserver and the clients, by marshalling the websockets through the webserver itself, and thus obfuscating the internal websocket port. Hence both the webserver and websockets traffic run on the same SSL port 433. The websocket server is obscured and any non localhost requests to it are blocked. The details of this implementation are extensively documented in this article on my blog. HTTP-Auth authentication blocks any intruders from accessing the web interface. Below is a diagram of this whole scheme.

 Wireless Security

Another important aspect of security is obfuscating the wireless requests and making it harder or impossible to decode. This is achieved with hardware AES128 encryption on the wireless transceivers such that any wireless packets to and from the end nodes cannot be decrypted by an attacker.

A more sophisticated attacker armed with a  $20 RTL-SDR dongle and laptop could listen for more extended periods of time and record messages and then replay them in hope to cause a door to open for instance. Such a simple portable SDR solution (cf. portableSDR project) is elegantly explained by Alan (w2aew) in this video:

Hence the remaining gap to fill is implementing an algorithm to thwart any replay attacks for those critical commands that control physical things like appliances, lights, garage, doors, etc. This is essentially a way to salt each wireless packet with a sliding window type signature such that if it’s replayed it would be obsolete. Until this is implemented, one can tune their end node transceivers output power to only be powerful enough to reach the home gateway, which would be recommended anyway to avoid polluting the RF traffic in your neighborhood. So unless you have a curious close-by neighbor with radio knowledge who might eaves drop on your RF traffic, it would make it harder for an external intruder to get physically close to your home/location to record your traffic and try to mess with it via replay attacks.

Rolling​ code vulnerabilities​

It​​ seems a lot of key fob entry systems ​like auto locks and garage openers are using rolling code to secure their wireless communication. The transmitter increments a number in the packet with each subsequent transmission. The receiver remembers the last received token and knows what token or series of tokens are expected next​. This attack involves blocking/jamming legitimate signal, then replaying the intercepted legitimate signal. Because of the jam, the receiver hears the noise and never receives the legitimate signal with the expected new token and thus the replayed message will appear legitimate. Continue reading

Moteino Framework architecture decisions

My vision for Moteino was to create an affordable/open/ideal/easy hardware platform that would fuel a new generation of wireless internet-of-things, and I think it came out pretty decent. My Hackaday Prize entry even made it in the top 50 semifinalists (out of 800+). More devices are being added to the Moteino Framework and existing ones are being improved to make it fun for those makers who like to DIY and solder their internet-of-things from easy to assemble kits. The end users have maximum freedom as far as using/building stuff with Moteino. They can build absoltely everything from scratch, as some have done, but some prefer to just save time and buy building blocks. Hence I funded my way through this adventure by selling ready made Moteinos and kits in my webshop.

People have asked many times why the Moteino was designed the way it was, and why not use this and that and the other type of MCU, transceiver type, radio band, or wireless technology. The number one reason why Moteinos are what they are today is because in the end they need to be designed to manufacture, work well, be reliable, license free, easy and fun to use in a friendly board format, cheap to buy or make, achieve long open air range or excellent indoor obstacle penetration when used with transceivers, etc. Here is my reasoning behind all these decisions and the answers to some frequently asked questions. Continue reading

Library updates & MoteinoMEGA support

Following the MoteinoMEGA release, the RFM69 library and examples have been updated to support MoteinoMEGA, there are significant changes to the library and you should get latest. The MoteinoMEGA Arduino Core has been released and needs to be installed in the Arduino/hardware folder (stable v1.0.5 tested working) before uploading to MoteinoMega. The Eagle source and schematic/board files are published in the LowPowerLab github repository. The Moteino page was updated to reflect the addition of the MEGA to the Moteino family.

The Wireless Programming library and examples are updated to fix bugs and support the MEGA as well. Another important change is the introduction of radio.ACKRequested() function in the RFM69 lib which should be used instead of the radio.ACK_REQUESTED variable. This ensures that ACKs requested by a broadcaster are ignored and only targeted ACKs are responded to. Please update your examples for proper wireless programming behavior. All examples have been updated to reflect this change. Also the SwitchMote sketch has been updated.

I consider this a major release and hence your constructive feedback and notification about anything that was omitted is appreciated.

SwitchMote source code released!

The source code for SwitchMote is finally “done”. As always, consider this a beta release at best, you should always check the github repository for any updates. There are 2 parts to configuring and programming a SwitchMote.

SwitchMoteConfig sketch, which needs to be loaded and used once, after assembly and before SwitchMote installation. This sketch is meant to help setup the essential parameters of the Moteino in the SwitchMote such as frequency, node and network IDs, RFM69 type (W or HW), encryption key, description, and some other utilities that may be extended in the future. All these parameters are then stored to EEPROM and will not be dependent on hardcoded values in your sketch.
This is especially useful when you have some nodes with RFM69W Moteinos and some with RFM69HW. It’s hard to keep track of all the transceivers settings. Additional settings could be added, like power level, bitrate, etc. Keeping the configuration with each node is most efficient in applications like SwitchMote. Setup once and forget!

SwitchMote sketch is the permanent sketch that will get loaded on your SwitchMotes. Note that this sketch will read the EEPROM configuration that was setup with the SwitchMoteConfig sketch mentioned above. This sketch does several things.

  • keeps track of which buttons were pressed, and manages the modes of operation
  • any button can be in ON or OFF mode – reflected in GREEN or RED led status
  • listens for BTNx:y tokens, to put button x in mode y, x={0,1,2}, y={0,1}
  • listens for SSR:y tokens, to turn the SSR on or off and the associated button in that same state (reflected by the LEDs)
  • if the button associated with the relay (SSR) is pressed then the SSR is turned ON or OFF depending on the mode that button transitions to
  • if a button is held pressed for at least 3 seconds (configurable) it enters SYNC mode, explained below
  • if a button has SYNC data it will notify the remote SwitchMotes to virtually “press a button”, and transition that button to the mode specified in the SYNC data
  • if any button is held pressed for at least 6 seconds (configurable) it erases the internal SYNC data in EEPROM. This could be modified such that only the SYNC data associated with the pressed button is erased, not the entire SYNC data
  • notifies the gateway, if any present, that a button was pressed

Note that SwitchMotes loaded with this sketch will work independently and with each other without the need for a network gateway or coordinator. A gateway is by default notified but the feature can be removed if not desired.

Also note that a SwitchMote can work without a relay, in which case only the neutral wire N and a hot wire to either one of S1/S2 is needed. In this case the SwitchMote can just act as a controller for other SwitchMotes or be customized to send other commands to other Moteinos. For instance you could open/close your garage (with GarageMote). The sky is the limit of what you can do.

Further details of the SYNC feature and how to use it are documented on the SYNC mode section of the SwitchMote page. Please refer to that page for any updates and latest information on SwitchMote.

Happy switching & sync-ing!

P.S. This code was released for RFM69 transceivers only because of huge growing interest in these line of transceivers and diminishing interest in RFM12B. You are welcome to port this to a RFM12B implementation as long as you keep within the boundaries of the CC-BY-NC-SA license.

Can RFM12B talk to RFM69?

I was asked this question a lot of times. Didn’t have a clear answer because in my early attempts to make them talk to each other I didn’t have success. I didn’t spend a lot of time on that since my interest has leaned towards RFM69 transceivers since they are much nicer and feature-rich overall (nicer packet engine, hardware AES encryption, digital RSSI etc).

Forum user timw has forked my RFM12B and RFM69 libraries and modded them to make them compatible, see this forum post for details. Turns out these mods makes communication possible between RFM12B and RFM69 transceivers. This is great news!

I was able to load his version of the libraries in my Arduino/libraries folder (I had to move/remove my original libraries because of conflicts), and using the examples that come with the two libraries (Struct_receive example on the RFM69 side, and Struct_send on the RFM12B side) I was able to see data coming through the RFM69 end. Seems very stable too. The signal strength (RSSI) fluctuates a little more than if I had RFM69 radios on both ends but it’s great to actually see a signal strength for a RFM12B transmitter:

The caveat is that the encryption must be turned off on both ends with the current version of the libraries. That’s because RFM69 uses hardware AES encryption and RFM12B does not support hadware encryption but uses a software XXTEA algorithm instead. The two are not compatible. One workaround would be to port/duplicate the XXTEA encryption on the RFM69 side, probably a little slower but worth it if encryption is important.

So anyway this should help folks that are trying to salvage their RFM12B nodes and make use of them while moving towards RFM69 based nodes. For me personally I will likely just upgrade everything to RFM69 moving forward but still this is a great development. Thanks timw for sharing your work!

Temperature and RC-Calibration for RFM69

I added two new functions to the RFM69 library: readTemperature() and rcCalibration(). Thanks to John for contributing.

  • readTemperature() function reads the internal CMOS 8bit temperature value, it’s fairly useful for situations where temperature varies a lot and RC calibration would be needed.
    The Gateway example has been updated to reflect its usage.
  • rcCalibration() will trigger a calibration of the internal RC oscillator. This is automatically performed at power-up according to the Semtech SX1231 datasheet section 4.3.5. But it can be triggered with this new function, as John has mentioned in the forum that when temperature changes, the RC oscillator will be affected, and a dramatic temperature shift will result in a frequency shift as well, causing a link to possibly be broken (for instance when your receiver is inside your house at room temperature and the transmitter is outside in bitter cold winter).

With the combination of these two functions, you can now recalibrate the RC based on temperature change, and also report a rough ballpark of what the temperature is. If you need more accuracy, a separate temperature sensor like the DS18B20 should be used.


RFM69HW transceiver now available

Finally it’s here, the high power version of the RFM69W FSK transceiver is now available in the store!

This is a relatively new transceiver from HopeRF, suggested replacement for RFM12B, RFM22B going forward. Some rumors have gone around that those transceivers might be phased out, but HopeRF has told me there are no such plans, however they do “recommend the RFM69 in place of RFM12B/RFM22B for new designs”.

Based on my range tests, and on some feedback, these might be an ideal RF platform for RC controlled drones, even the RFM69W should give you a pretty long range, especially in open air.


The RFM69HW is a 20dBm output power transceiver. In my open-air range tests I ran out of space at around 370m with this one. So potentially these will go significantly farther. The tests were done with my Gateway/Node example sketches, at 55.5kbps air bitrate, 50khz frequency deviation. If someone has better results with other settings please let me know.

They are powerful but will need more current to work, 130mA in transmit mode (for a short few milliseconds while the packet is modulated/transmitted), and the same 16mA in receive mode. So far the Moteinos in their current configuration seem to handle the high current spikes just fine.

HopeRF has suggested that 868Mhz units can be replaced with 915Mhz units that are loaded with 868Mhz settings. I have verified this myself with range tests and I don’t see any significant difference when using 915Mhz units at 868Mhz. Hence if you need 868Mhz units please get 915Mhz units and initialize them with settings for 868Mhz.