Tuesday

Monitoring an RF24/NRF52x Network Continued...

 Monitoring an RF24/NRF52x Network Continued...

Explaining the recent changes

So in my last blog post I noted the progress I made in automating and monitoring my radio network, and it has been super interesting. Due to the ongoing activities affecting my network, it has become more robust and functional than ever, with bug fixes and recent changes vastly improving functionality of the network.

The network uses the RF24Gateway & RF24Ethernet libraries to enable use of the RF24 & RF52 radios as standard Network Interface Cards (NICs), with full TCP/IP support. The system makes use of the HTTP & MQTT protocols for communication. This along with software like Home Assistant and/or Node Red allows full automation of the network, including the generation of graphs, charts and buttons/controls.

The obsessive hacker activity that has been going on for years has now finally stopped for an astounding few days! I'm not exactly sure what finally did it, but I can only assume this person reads my blog.

The following screenshot shows the results of the past few days now, with the tail-end of some interference lowering the results, but very promising none the less. This is 0.3 percent packet loss after a few days of monitoring on a network with 17-18 Mesh/Ethernet nodes and going up!


It is super nice to be able to test, monitor and operate these little radios the way they were intended, without constant bombardment and incoming packets from my neighbor. Due to recent changes and a lack of interference, my MQTT nodes are now staying connected to the server for a large number of hours instead of minutes, and because of this are more responsive and communicative than ever. All statistics are up from the norm and looking good! The below video shows the connection times for 10 MQTT nodes on my network.

The video below shows my 'activity monitor' in which 15 of my active nodes are reporting in every few seconds. They simply identify themselves and show that they are active. An inactive node will fall behind quickly, making it obvious it is not active as its bar will not move. The intent is simply to put extra load on the network and keep track of any nodes that are failing.

Interestingly enough, when I introduced the ability to change the channel the network operates on, a small number of nodes would fail when I activated this functionality. I've found the issues to be hardware related, as when adding capacitors or replacing the connecting wires and/or nodes themselves, the problems went away. It seems changing channels regularly is kind of hard on the devices. It requires them to be pretty sound hardware-wise. All in all its been a good few days for the radio network. Lets just hope this keeps up!


Sunday

Monitoring an RF24/NRF52x Network & Creating a Scanner with the XIAO 52840 Sense

Monitoring an RF24/NRF52x Network & Creating a Scanner with the XIAO 52840 Sense

Monitoring the data from a scanner and other sources in real-time


I've been trying automate analysis of the RF24/NRF52 communication stack lately and decided it was time to automate things to a degree further. I've setup a system using MQTT and a failover node in the network, so at any given time, I can switch my main RF24/RF52 network to a different channel for testing purposes. The results have been a bit interesting, with interference popping up on channels that appear clean for long periods of time, going away after I switch to a new channel... for a while.

I also leverage NodeRed, MQTT, and other methods to monitor the radio network. To put things in perspective, I am using TCP/IP over the radio network, using the NRF24 radios as a standard NIC, to test connectivity etc, so the radios are very busy, transmitting many 32-byte packets for every TCP/IP packet sent. The network layer handles routing, fragmentation/reassembly, and the mesh layer ensures nodes stay connected to the network even under adverse conditions.

Here is a couple pictures showing ping statistics for a RPi5 running RF24Gateway in close proximity to a very busy master node:




This last picture shows a clean channel with minimal interference over a long period of time.



The % success rate of pinging the RPi5 from the master node, showing 2.24% packet loss on a busy network after a couple hours after changing to a better channel:


This is with 17 RF42Ethernet and/or RF24Gateway nodes running on the network and communicating large MQTT messages typically every few seconds each, so I'd say that amount of packet loss is very much acceptable. The network runs on a variety of NRF24 modules as well as the newer NRF52x modules.

The following is a graph of how long each of 10 nodes stay connected to the MQTT server over the radio network before having to re-connect. This tends to happen when there is interference and/or the mesh breaks down a bit and needs to re-converge. In some cases, in good radio conditions, nodes stay connected up to 5 hours or longer. With a recent update to RF24Ethernet, nodes should now stay connected even longer!



You see, I was thinking that 17 nodes pumping out constant traffic might be a bit too much for a the mesh network, but the results of testing indicate that this is not the case. I've had more nodes on a single network in the past, but was doubting recent changes to the network and the network itself. Testing on separate channels shows that the mesh works great with this number of nodes, its just the interference causing problems, which would occur with any number nodes.

One good example is the following screenshot, you can see the RX Packets (user): 327 line. Since none of my nodes are sending RF24Mesh or RF24Network messages, this is just one more pretty good indicator that one of my neighbors has an affinity for RF24 programming and is constantly hitting my network with spam and garbage. There is a history of DOS attacks as well, which took advantage of limited functionality of the is_valid_address() function of RF24Network at the time, and continue in very limited fashion due to the simplicity and effectiveness of RF24Mesh. Its been going on for years, almost daily, and I just can't understand the obsession with trying to hack my radio network. Its for testing purposes and contains no useful data. 
For somebody who was able to study the RF24 stack and identify a quality DOS attack that required only one small radio and took down my whole network, why not do something constructive with those skills?


The following is a good example of interference on the network, with my main network experiencing massive interference, with a node about 1.5-meters from the master unable to establish connectivity for a long period of time. I'm not sure what creates this level of interference, but it seems most if not all of my nodes on the main testing network using channel 111 lost connectivity for this same period of time between 10:33pm and 12:18am Jun 28th to Jun 29th 2024.



With that, I've developed a scanner sketch for the XIAO NRF52840 Sense, since the radio has a feature to directly monitor RSSI levels, and it also has an option to monitor received packets separately. This is a little different from the scanner sketch included with the library, since it uses the RGB LEDs onboard to indicate signal strength in real time. It also outputs data for the Serial Plotter in the Arduino IDE, so you can see what is going on on a graph as well as the LED indicators.

The Scanner:

The images below show the Serial Plotter output in the Arduino IDE. Since I have a very busy master node, it is normal to see a fair number of 'RX 'packets. The 'Values' indicator shows the count of how often the radio received a signal with an RSSI better than -65dBm.



The scan in the pics are during normal mesh operation, with not much happening. When there is a large amount of interference the RSSI (green) line goes way up, communication is hindered, but the mesh nature of the system ensures that nodes re-converge around the master node in a short period of time after the interference stops. Testing shows the mesh is very stable and reliable at this point, with interference measured showing a direct correlation to the communication abilities of the mesh.

The Sketch:

The sketch is fairly simple, but very useful for pulling in data regarding noise and received packets on a given channel over time. 

The sketch is also available on GitHub here.

/*
* Single channel scanner for XIAO 52840 Sense
*
* Monitoring of a single channel using the built-in radio of the NRF52840
* Scans a single channel for noise using the RSSI measurement feature
* Can also listen for received packets
*
* Used for monitoring level of traffic and noise separately for a given RF24Mesh master node
* Default is RSSI level monitoring, uncomment USE_RX to enable monitoring of received packets also
*
* ** LED Indicators: **
* Blue: Minimal traffic,
* Green: Medium traffic, 15/100 signals > -65dBm
* Red: Heavy traffic,  25/100 signals > -65dBm
* Orange: Very heavy traffic, 35/100 signals > -65dBm
*
*/
#include "nrf_to_nrf.h"
#include <RF24Network.h>
#include <RF24Mesh.h>

/**********************************************************/
#define CHANNEL 3   // What channel to scan on
#define MIN_DBM 65  // The minimum RSSI (dBm) for counting signals. Higher value == greater sensitivity.
#define USE_RX      // Also listen for and count received packets
/**********************************************************/

// Set up nRF24L01 radio on SPI bus plus pins 7 & 8

nrf_to_nrf radio;
RF52Network network(radio);
RF52Mesh mesh(radio, network);

const uint8_t num_channels = 1;
uint8_t values = 0;
uint8_t valuesR = 0;

// LED Setup
void red() {
  digitalWrite(LED_BLUE, HIGH);
  digitalWrite(LED_RED, LOW);
  digitalWrite(LED_GREEN, HIGH);
}
void green() {
  digitalWrite(LED_BLUE, HIGH);
  digitalWrite(LED_RED, HIGH);
  digitalWrite(LED_GREEN, LOW);
}
void blue() {
  digitalWrite(LED_BLUE, LOW);
  digitalWrite(LED_RED, HIGH);
  digitalWrite(LED_GREEN, HIGH);
}
void orange() {
  digitalWrite(LED_BLUE, HIGH);
  digitalWrite(LED_RED, LOW);
  digitalWrite(LED_GREEN, LOW);
}

void setup(void) {
  Serial.begin(115200);
  Serial.println(F("\n\rRF24/examples/scanner/"));

  // Setup and configure rf radio
  mesh.setNodeID(0);
  mesh.begin(CHANNEL);
  radio.setAutoAck(false);
  radio.setCRCLength(NRF_CRC_DISABLED);
  radio.setAddressWidth(2);
  radio.setChannel(CHANNEL);
  radio.startListening();
}

const int num_reps = 100;  // Max 255

void loop(void) {

  // Clear measurement values
  values = 0;
  valuesR = 0;

  // Scan channel num_reps times
  int rep_counter = num_reps;
  while (rep_counter--) {

    if (radio.testCarrier(MIN_DBM)) {
      ++values;
    }
    delayMicroseconds(256);

#if defined USE_RX
    if (radio.available()) {
      radio.read(0, 0);
      valuesR++;
    }
#endif
    delayMicroseconds(256);
  }

  // Print out channel measurements
  Serial.print("Low:");
  Serial.println(15);
  Serial.print("Med:");
  Serial.println(25);
  Serial.print("High:");
  Serial.println(35);
  Serial.print("Values:");
  Serial.println(values);
  if (values >= 15 && values < 25) {
    green();
  } else if (values >= 25 && values < 35) {
    red();
  } else if (values >= 35) {
    orange();
  } else {
    blue();
  }
#if defined USE_RX
  Serial.print("RX:");
  if (valuesR) {
    Serial.println(valuesR);
  } else {
    Serial.println(0);
  }
#endif
}

Tuesday

RF24Mesh and RF24Network Enhancements

 RF24Mesh and RF24Network Enhancements

Libraries updated with better functionality

So we've been putting in a bunch of work lately on the RF24/NRF52x communication stack for Arduino, and surprisingly, given the age of the libraries, we were able to make a number of changes that significantly impact the performance of the network and mesh.

RF24Mesh:

1. Utilize all poll requests. 

The prior behavior of the mesh was to send out a poll request via multicast and gather the responses. Then the mesh layer would attempt to request an address via one of the nodes that responded to the poll. If this failed however, the node would continue on and send out another poll. The current behavior now utilizes up to 4 received poll responses and loops through them all until either failure or a successful address request is made before moving to the next multicast level and sending out another poll request.

2. Enhance the ability to verify connectivity

The prior behavior of the mesh was to call `getAddress(_nodeID);` and verify its own address with the master node. The call would fail if anything but a successful address response was received. Now there is some logic added to return immediately if the address is not found in the master list or is default. It will also return immediately if the nodes address has been zeroed out. Retries will take place if the request failed or timed out. Finally, the node actually verifies that the received address matches its own address.

Update: I am currently testing a new method of connection checking, where each node only contacts their parent node instead of the master node. This appears to reduce traffic, increase connection times, and improve the overall stability of the mesh.

It may not seem like much, but the changes should tend to reduce network traffic, while providing more seamless mesh operation.

RF24Network:

1. Fix error sending data

Per the RF24 documentation and behavior, when using some of the advanced write functions, there is a need to call `radio.txStandby()` if a write fails, otherwise the radio will essentially hang and all subsequent writes will fail. This was partially missed in RF24Network, so a call has been added when an auto-ack payload fails. This should improve reliability and consistency in sending data.

RF24:

1. Interrupt enhancements. 

The use of interrupts on Linux platforms like the Raspberry Pi has been greatly improved and no longer requires root access to operate. Unlike the RF24 library, the interrupt functionality uses GPIO pin numbers instead of BCM pin numbers. ie: Use GPIO 24 instead of pin 18.

RF24Ethernet

1. Fix re-transmit mechanism

The associated UIP IP stack incorporated with RF24Ethernet uses a retransmit mechanism when acks are not received etc, but it was not working. This is now fixed and results in much more reliable, longer connectivity with MQTT, HTTP and other protocols & applications that transmit data.


All in all its been a good year for the RF24/NRF52x communication stack, with support also recently added for Nordics NRF52x SOCs, there are so many potential ways these libraries can be configured! Encryption and authentication features are also available with the newer radio modules, which will easily handle audio streaming and more advanced functionality.

Auto Analog Audio & NRF52840: Now working on non-Mbed cores

 Auto Analog Audio & NRF52840: Now working on non-Mbed cores

Playing around with the AAAudio library

So I finally decided to make the necessary purchase and get myself a relatively cheap oscilloscope, and with that play around more with the AAAudio library. Even with the added view into the output signal and what is going on using the scope, I still haven't been able to figure out what I'm doing wrong with the I2S interface, so for now the audio is not of the highest quality, which is relatively good for voice, but not so good for higher frequency audio signals.

I have, however, made progress on using the non-MBED core for both input and output of audio using the PDM (microphone) and PWM (amp/speaker) interfaces, which opens up more of the capabilities of this device! In the end, once I actually quit working with the I2S interface, it wasn't that difficult getting the non-MBED core to work. This means that AAAudio should work on other devices like the Feather 52840 Express etc, but it hasn't been fully tested yet. The PWM interface can handle ~10-bit audio at 16Khz, and lower at higher sample rates.

It also allows users to adjust between 20khz and 16khz PDM samples now as well!

Users can specify which pins to use for PWM by editing the library src/NRF52840/AutoAnalogAudio.cpp file and specifying the GPIO pin and port numbers, else it defaults to GPIO #5, port 0 for output.

As of this writing, users would need to download and install the library from ZIP directly from here because I will not do a new release for a while. (Still testing and potentially updating the new capabilities)

Monday

Installing and using the RF24 Communication stack on Arduino and RPi - 2024

 Installing and using the RF24 Communication stack on Arduino and RPi - 2024


I made a video to demonstrate current installation and usage of the RF24 comm stack on Arduino and Linux using the latest available code.

See Arduino Project Hub for a text based tutorial




Thursday

Encrypted Audio Comms with XIAO 52840 Sense

Encrypted Audio Comms with XIAO 52840 Sense
The beginnings of wireless audio comms


I've been playing around with the NRF52840 boards I have, and now that I have basic audio functionality working via PDM microphone and PWM audio output, the next thing to do is test out an encrypted wireless communication scenario, so that's what I've done.

The devices use the AutoAnalogAudio and nrf_to_nrf libraries created by me to communicate wirelessly. I've also enabled encryption at the nrf_to_nrf layer, and the related code is an example of implementation, with the device randomly generating a new key and re-keying every 30 seconds. This will prevent others from decrypting the payloads or performing replay attacks outside the 30-second windows. 

This means that users would need to start the devices at the same time (within a 30-second window), so they start-up using the same key. After 30-seconds, a new key is generated and configured, so both devices will then use the same new key. The receiving device ensures that the old key matches before accepting the new key, so unauthorized users can't simply send a new key or replay an old key. Any power down of either device will result in lost communication unless the other device is restarted within the same 30-second window.

To use the sketches (posted lower down), users would need a XIAO 52840 Sense board and both of the aforementioned libraries installed, then just run the code. No wires to connect, no power supply issues to worry about, no counterfeit nrf24 devices to worry about, just a straightforward device that works.

There are still a few issues with synchronization of the audio vs how the device handles PWM data. Essentially, you can have the PWM pin default to a LOW or HIGH state when the current PWM sequence ends, which happens during radio communication when packets are lost or slow to transmit. Compared to other devices I've worked with, which maintain the current state of the pin when PWM or DAC data ends, this device will revert the pin to either HIGH or LOW which causes a popping or clicking sound. 

I'm not sure how to work around this currently, but will continue to experiment to try and achieve better results. In the mean-time users can try out the prototype code by downloading the sketches here: https://github.com/TMRh20/Sketches/tree/master/XIAO-EncryptedAudio

Sunday

Recording and Playback of Audio on the XIAO NRF52840 Sense - Auto Analog Audio

 Recording and Playback of Audio on the XIAO NRF52840 Sense

Auto Analog Audio Library

So I've been struggling with the I2S interface of the NRF52 devices, and have given up for the time-being trying to get it to work properly. In the meantime I've made some decent headway with the PWM interface and reproducing audio that way. This is similar to the TMRpcm library for AVR devices, which also uses Pulse-Width-Modulation to reproduce audio. 

So far the AutoAnalogAudio library is in a very basic but functional state with an included example to demonstrate how to record and playback audio on the XIAO 52840 Sense. It is designed to input audio from the PDM microphone directly and output using Pin5 of the XIAO board via PWM. The audio signal is 16-bit, 16kHz audio, so of reasonable quality, and cannot currently be modified. The code is still in its infancy.

This makes it easy to record and transmit audio over radio link, since with the nrf_to_nrf radio library, users can broadcast the audio to another device very easily. 

There are still a few problems with it, mainly some synchronization issues, which result in a clicking sound when audio is fed directly from the microphone into the PWM output (Amp & Speaker). I'm not quite sure how to resolve it currently, so will leave things as-is. Update: Adjusting the timers slightly to make the PWM a bit slower than PDM input results in a smooth output signal.

A new release will not be made for a little while, so to try it out, just install the AAAudio library directly from ZIP. See GitHub at  https://github.com/TMRh20/AutoAnalogAudio 

Monitoring an RF24/NRF52x Network Continued...

 Monitoring an RF24/NRF52x Network Continued... Explaining the recent changes So in my last blog post I noted the progress I made in automat...