POSTS
NRF24 Troubleshooting
These little nRF24L01+ radios are awesome. They are available very cheap and provide a simple way to add fast packet-based wireless communications to a project.
I’ve used them before on my LED strip audio visualizer and LED glasses.
Extended range versions of these modules are available on amazon with a built-in LNA (low-noise amplifier) and PA (power amplifier). I’ve always had trouble getting these to work for me though.
Looking around online it seems like I’m not the only one. Searching on the Arduino forums for NRF24L01+PA+LNA problems yields dozens of posts.
In this post I’ll be diving into the reasons that these modules are so much more difficult to get working than the standard ones.
For starters, let’s look at the signal transmitted by an nRF24L01+ using an SDR.
To capture this data, I’m using a HackRF One with SDRSharp, and using the remote from my LED strip project to generate the packets.
Using the baseband recorder in SDRSharp, the raw I/Q signals from the hackRF can be saved as a .WAV audio file.
This file is then opened in GNU Octave using the audioread command.
This is what the raw I and Q signals look like when the packet is transmitted:
A low-pass filter can get rid of some of the unwanted noise:
The NRF24L01+ uses GFSK (Gaussian Frequency-Shift Keying) for transmitting data. In the case of this device the carrier wave moves between two frequencies, one indicating a ‘1’ and one a ‘0’.
According to the datasheet, at the 1Mbps data rate used by my remote, the frequency shift is +/-160kHz (typ).
Calculating the angular frequency using diff(arg(iq)) produces large spikes whenever the result of arg() jumps from -pi to pi, so instead I came up with this way to calculate it.
I’m not sure if there’s a name for it but I wasn’t able to find reference to this online.
w = imag(S’ / S) where w is angular frequency (in radians/s), S is the complex IQ signal, and S’ is the derivative of it with respect to time.
This is the result:
When the data was captured, the hackRF was tuned to the carrier frequency of 2.476GHz. The first part of the signal we see is the carrier frequency of the nRF settling. After this, we can start to see the nRF packet format.
Zooming in on the GFSK data and looking for ones and zeros, we can see the packet data.
In this plot, blue is the expected value of the packet including the preamble (01010101), address (“1Node”), packet control field and payload. I didn’t calculate the CRC. Red shows the value of the signal at 1us intervals, chosen to match the 1Mbps data rate.
Now let’s look at the signal from an nRF24L01+PA+LNA module: With the module the same distance from the hackRF, it looks pretty bad right away.
Angular phase velocity looks bad too.
I don’t know what’s causing this but I think it’s probably why the packets aren’t getting picked up by the other normal nRF receiver.
Another note on these modules, I learned that the chip commonly used on these LNA+PA modules is a Skyworks RFX2401C. datasheet
These chips have TX EN and RX EN pins for enabling the LNA or PA one at a time. I found that on my module, RX EN is tied to CSN through a 1K resistor, and TX EN is tied to ANT2 on the NRF, which is only powered while the device is transmitting.
Investigation of this issue is still ongoing, but if I find the answer I’ll post it here.
Update 6-21-23
After reducing the NRF TX power from 0dBm (RF_PWR[1:0] = 11) to -18dBm (RF_PWR[1:0] = 00), the signal looks much cleaner. I think at full power it might be saturating the PA.
Raw I/Q looks smoother after filtering:
And the GFSK data looks better:
It still looks ok at -12dBm (RX_PWR[1:0] = 01):
but starts to look worse at -6dBm:
It’s interesting that as the TX power increases, the settling time of the RF oscillator also seems to increase. At -18dBm it’s almost immediate but at -6dBm it takes about 40us to settle.