The RF24 Wireless Communication Stack: Communication, Consistency & Exploits
Using RF24Ethernet & RF24Gateway for an IoT Network
RF24Ethernet & RF24Gateway are two complimentary software libraries for Arduino that allow users to quickly design, develop & implement IoT networks that utilize TCP/IP for general communication. They use the Arduino Ethernet client/server APIs, so anyone with minimal programming experience can construct and deploy an IoT network in short order.
Recently, we discovered a buffer overflow in RF24Network that affected nearly the entire communication stack on Arduino devices. This buffer overflow was "externally triggered", meaning that an external user or system would need to send a certain packet type to a device to trigger the buffer overflow. It doesn't occur under "normal" operation of the system.
The interesting thing about this, is that my devices have been susceptible to this overflow for a long time, and there has been near-daily attempts to disrupt my network. It seems that somebody nearby has a LOT of time on their hands, and a penchant for causing problems.
The good part of this is RF24Mesh, the part of the RF24 Comm Stack that keeps things working, almost no matter what. RF24Mesh is a wireless-mesh system for the comm stack that provides addressing, DHCP type protocols, and self-healing/management of the network. With RF24Mesh involved, the network typically remains stable, despite the constant attacks.
The exploit in RF24Network has now been patched, so users are encouraged to update as soon as possible.
As far as the rest of the stack goes, everything is coming together with support for nRF52 and nRF54 radios, which now work with the comm stack. I have a little bit of work remaining in this regard, but basic support for these radios has been incorporated throughout the stack in the latest releases.
A chart of ping response times for one node on the network using NodeRed
There are a lot of different uses for this system, from monitoring, to managing and collecting data from sensors, to remotely controlling devices, etc. and it is very flexible and standardized. I've been using the NodeRed system with MQTT mainly for my devices. MQTT is a standard protocol for messaging and IoT systems, so it is well suited to this type of thing.
For anyone interested in wireless IoT systems, I would highly recommend checking out RF24Ethernet/RF24Gateway. You can be up and running in minutes, with a closed system using just two Arduino devices & RF24Ethernet, or a fully fledged IoT setup, using a Raspberry Pi/Linux for a gateway and a number of Arduino nodes running RF24Ethernet.
nrf_to_nrf Arduino Library: Now supports nRF54l15 devices!
New possibilities with nrf54l15 support
With the recent addition of an Arduino Core supporting nRF54l15 devices, I decided it was time to attempt to get the nrf_to_nrf library working with these devices. It was confusing initially, but once I worked out the specific differences in registers, things came together pretty quickly.
The main difference between these radios and nRF24 radios is the payload sizes and speeds. The nRF24 is capable of only 32-byte payloads, while the nRF52840 and nRF54l15 devices support much larger payloads. The nRF54l15 is also capable of 4Mbps transfer speeds.
The nrf_to_nrf library is designed to work out of the box between all 3 device types, but users can call
radio.begin();
radio.enableDynamicPayloads(254);
prior to calling network.begin(); or mesh.begin(); functions to configure large payload sizes if setting up communication between nRF52840 and/or nRF54l15 devices. nRF24 is not compatible with sizes > 32-bytes.
I'm still working on getting encryption working on the nRF54l15 devices, and it seems to be a little more complicated than it was on the nRF52840. This might take a while to address.
The rest of the libraries, RF24, RF24Network, RF24Mesh & RF24Ethernet are being updated to accommodate the newer radios.
nRF24l01 radios: Long Term Stability Issues & Error Handling Enhancements
Creating robust, reliable networks
We recently identified and addressed some long-term reliability issues affecting the RF24 radio library for nRF24l01 radios. The issues affect any users that make use of the write() or txStandBy() functions of the library. About a year ago, we found some issues with the radios returning "impossible" values, with one register indicating a payload is available, another saying there is not, and another saying the payload length is 0. This and similar issues appear to have affected the radio in transmitting mode as well, a fact we missed upon initial review of the previous issue. Now, a year later, we've addressed issues affecting transmission as well.
As of this writing, we are just completing testing and the changes have been pushed to the master branch of RF24. A new release should be available in a few days (version higher than 1.5.0) for the Arduino and PlatformIO platforms. For now, users can install from ZIP or clone the RF24 repo directly from the master branch.
This should be the final fix for stability in the RF24 platform, as we seem to have identified and implemented handling for all failure modes now.
RF24Ethernet v2.0 Released - lwIP IP Stack Support + Direct TCP/IP connectivity without a RPi
Better, faster & more reliable connectivity w/lwIP
Starting over the holidays, I began work with RF24Ethernet and the lwIP IP stack, integrating the IP stack into my existing library. Previously, and on smaller devices, the library utilized the uIP stack, which is no longer maintained, and used only on smaller devices that cannot run the lwIP stack.
This was quite a challenge, the lwIP stack functions in a lot of ways quite differently than the uIP stack, which in itself provided some challenges with integration. The RF24Ethernet library uses the lwIP stack in Mainloop (NO_SYS) mode, and lwIP uses callbacks for most of its functionality, so learning how that worked and the correct processes to use with this IP stack took some doing.
I was also able to adjust the code so that a Raspberry Pi or central PC is no longer required, nodes can simply run RF24Ethernet and connect between themselves via TCP/IP & UDP. I've included two examples, in the Headless examples directory, so users can try this new feature out.
What is it? / How does it work?
RF24Ethernet is a wireless TCP/IP communication system using nRF24 or nRF52x radios for comms. Users can create wireless mesh networks (NOT WiFi) that use much less power than WiFi networks and have many similar features, but with lower bandwidth.
The system mirrors the standard Arduino Ethernet API, and can function in many ways very similarly to standard Ethernet or WiFi connected devices, although over the nRF24 or nRF52 radios. See https://docs.arduino.cc/libraries/ethernet/
Essentially, you set it up, then just use TCP/IP protocols to communicate. Very little to no knowledge of the underlying APIs or code is required.
When a Raspberry Pi or other routing capable device is used as the master node, the system can utilize standard protocols to connect out to the internet or other parts of your network, via MQTT, HTTP etc.
In a standard IoT setup, for example, a Raspberry Pi can run an MQTT server, with Arduino sensors connecting in and logging sensor information to a database etc.
In another IoT system, and ESP32 can connect out to Arduino devices set up as servers. The ESP32 would send and/or retrieve sensor or other information.
How do I use it?
Just install the RF24Ethernet library and its dependencies via the Arduino Library Manager. One may also need to install the Arduino lwIP stack and optionally the MQTT library by Joel Gahwiler.
Then just run the two examples in the Headless directory on some Arduinos!
More with MP3 Decoding & Playback on nRF52x devices with the AutoAnalogAudio Library
Direct Playback of MP3s from SD card
Since designing and having some new circuit boards made for audio prototyping, I've begun testing more and more with advanced audio options, like decoding and playing MP3 files from SD Card. This is all thanks to a sponsorship from http://PCBWay.com
I've revised some previous experimental code and worked out some bugs, thanks to the simplicity of having a circuit board instead of a big ball of wires and breadboard.
The code shown below requires installation of my AutoAnalogAudio library and the microDecoder library which can both be installed from the Arduino Library Manager.
With my existing circuit board and the Feather 52840 Express or Sense boards, this code will work out of the box. It will also work with any 52840 based board. It is still in experimental stages but is working very well so far!
Designing & 3D Printing Some Cases for My New Circuit Boards
The beginnings of a final design
In order to put the finishing touches on my custom designed circuit boards, I figured its about time to build some cases for them. The final addition was a set of 1.5", 4-Ohm speakers I just purchased to complete the project. As shown below, iteration v1 of a case was pretty rough, just figuring out and confirming the basic measurements and form of a design. This ended up being very bulky, which would be OK for use as a tabletop speaker or intercom etc.
Case V1.0
Case V1.0
In the case shown below, V2, I opted to make it longer instead of wider. I tend to like this layout a little more. There are still a few tweaks to make, like lowering the speaker down into the case, so the USB cable will plug into the MCU without being blocked. I may add round holes for the buttons, but I kind of like the square layout, I still need to wire up the speaker, but this is how it will look.
Case V1.1
Case V1.1
Once I make the necessary changes to this form, I will put the files in the associated GitHub repository here
I'm still trying to decide on a cover, whether or not I really need one, and if so, how to make it snap in and out, so it is easy to remove. I wish I would have made the PCB a little smaller, which I could probably do pretty easily by rearranging the components. All in all though, I think its pretty good for a first attempt at building a real circuit board with functional components. Thanks again to PCBWay.com for sponsoring the PCBs!
Initial Testing, Notes & Progress on new PCB for Wireless Audio Prototyping
Testing out the new circuit boards and getting the built-in microphone working
If you weren't following along I just received some new custom built circuit boards from PCBWay.com and have been testing things out extensively. Everything works! I even got the custom-added I2S microphone working with the nRF52840.
The boards support functionality like voice transmission over the built-in radio, and can function as a radio, intercom or simple music player etc.
A full test of the new circuit boards
Getting the Microphone working with the AutoAnalogAudio library:
The nRF52840 Feather Express/Sense does have an I2S interface, but it only supports up to a 24-bit window, whereas the SPH0645LM4H expects 32 SCK pulses per audio frame (18 bits of data + 14 bits of padding) and a 64 x BCK signal, where the nRF52840 typically does a 48 x BCK signal.
After a bit of searching, I found that the appropriate signal could be created by the PWM peripheral of the 52840, and the I2S interface would just need to be configured with special settings to grab the 18-bits of data properly.
The main drawback with using this mode is the I2S interface can only operate in either Input or Output mode, they can't be run at the same time unless both I2S Input & Output devices use the same settings. I had to make some modifications to the AutoAnalogAudio library, released in v1.54.0, in order to allow switching between I2S modes.
Currently, this mode is only supported for input devices.
The Feather Express 52840
Configuration for the Microphone:
To use the new special settings, users need to set the aaAudio.manualI2S variable to True before calling the aaAudio.begin(2,0); function.
With the Feather Express, the LRCK or WS pin needs to be configured from the default of 29, to something like 28, which is A3 on the Feather Express 52840
In order to use the example, upload to two Feather 52840 Express or Sense boards, and plug them into the custom PCB, or manually attach external I2S microphone & amplifier.
The example features 3 buttons, the PTT button is used to transmit, then there are two for Volume Up/Down. If users press and hold Volume Down, then Press Volume Up, the device will go into a continuous transmission mode, not requiring the PTT button to be pressed.
The device also toggles the onboard red LED when data is received.
Audio is relatively high quality at 16-bits and 32kHz, so it is pretty clear and useful for many different applications.