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.