Thursday

Using RF24Ethernet & RF24Gateway with the Arduino Cloud

 Using RF24Ethernet & RF24Gateway with the Arduino Cloud

 Pushing automation even further

 Recently, I was offered an Arduino Uno Q, Arduino Uno R4 Wifi and 1-year of Arduino Cloud access for free! This came as quite the surprise, because I was contacted out of nowhere by Per Tillisch, an Arduino Support Engineer, who offered me the devices and cloud access with no strings attached! I was quick to take him up on his offer. He stated it was due to my work contributing to the Arduino ecosystem.

In looking at the cloud access, it looks like it will be very simple to create dashboards etc, and integrate everything I want from my existing systems into the cloud! No code changes, no updates, no nothing. Just some simple changes in the NodeRed system I use.

With the current wireless IoT systems I am using, based on RF24Ethernet and RF24Gateway + wireless radios + MQTT, I also use NodeRed for managing all the data and interactions locally. This means that all I had to do was install the node-red-contrib-arduino-iot-cloud nodes, setup an API key, and use the newly installed nodes to communicate with the cloud!

See  https://docs.arduino.cc/arduino-cloud/guides/node-red/ for more information.

Right off the bat, I was able to create a simple dashboard that displays incoming Temperature, Humidity & Barometric pressure data on some charts!


 From here, it is very simple to add/remove & create new parts of the dashboard.

All of the existing Arduino devices in my network now have potential cloud access via NodeRed! I didn't have to modify any code, upload new firmware or really do much of anything! This all works with my existing systems!

The beauty of this is users can keep all their data and integrations local, logging to a database if desired etc, and still make use of the Arduino Cloud at the same time. Some data can go to the cloud, some to a local repository, and everything just seems to work in sync!

I currently have all my integrations set up via NodeRed + NodeRed Dashboard, so it is very similar already to the Arduino Cloud Dashboard, though only available locally. Using the cloud, I can now make some parts of it accessible from anywhere.

This is all very cool, I can't wait to get the new hardware! 

 

Monday

AutoAnalogAudio Library - Updated with I2S support for nRF54L15 devices

 AutoAnalogAudio Library - Updated with I2S support for nRF54L15 devices

 Bringing audio to the nRF54L15

 I was able to dabble little over the weekend, and ended up connecting an I2S amp and microphone to a nRF54L15 device. Getting it working was a little confusing at first, but the datasheet provided enough info to figure out the compatibility differences between nRF52840 and nRF54L15 devices. It was just a matter of making a few small changes.

One of the most glaring differences is with the main data pointer (NRF_I2S->RXTXD.MAXCNT). With the nRF52840 it counts by the number of 32-bit words, where the nRF54L15 counts individual bytes, so the main data handling functions needed to be modified.  

The other glaring difference is the pin layouts, but I've used the same physical layout as the 52840. That is, the physical spots on the board are the same, but the underlying pin and port numbers have changed.

 


    Per the AutoAnalogAudio library, these are how the pins are laid out by GPIO Pin / Port numbers:

    I2S_PIN_MCK = 8;
    I2S_PORT_MCK = 2;
    I2S_PIN_SCK = 5;
    I2S_PORT_SCK = 1;
    I2S_PIN_LRCK = 7;
    I2S_PORT_LRCK = 1;
    I2S_PIN_SDOUT = 11;
    I2S_PORT_SDOUT = 1;
    I2S_PIN_SDIN = 10;
    I2S_PORT_SDIN = 1;

 The changes have been pushed to the master branch as of this writing, and I will clean up the code, possibly add support for the PWM and SAADC features, and do a release soon. For now users can clone from the master branch or install from ZIP.

Saturday

The RF24 Wireless Communication Stack: Communication, Consistency & Exploits

 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!

 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. 

 

 

Thursday

nRF24l01 radios: Long Term Stability Issues & Error Handling Enhancements

 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.
 

Monday

RF24Ethernet v2.0 Released - lwIP IP Stack Support + Direct TCP/IP connectivity without a RPi

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!

 Please log any issues or problems with us at https://github.com/nRF24/RF24Ethernet/issues

 

Saturday

More with MP3 Decoding & Playback on nRF52x devices with the AutoAnalogAudio Library


 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!


/*
* Requires https://github.com/TMRh20/microDecoder library
*/

#include <SD.h>
#include <AutoAnalogAudio.h>
#include "mp3.h"  // decoder
#include "pcm.h"

mp3 MP3;
pcm audio;
AutoAnalog aaAudio;


/************ USER CONFIGURATION ***************/
const char* audioFilename = "noceil.mp3";
uint8_t SD_CS_PIN = 2;  // Set this to your CS pin for the SD card/module

float volumeControl = 0.2;
#define AUDIO_BUFFER_SIZE 1152  // Should be a multiple of 64
/**********************************************/

void setup() {

  Serial.begin(115200);
  while (!Serial) delay(10);

  Serial.print("Init SD card...");
  if (!SD.begin(SD_CS_PIN)) {
    Serial.println("init failed!");
    return;
  }
  Serial.println("SD init ok");

  aaAudio.I2S_PIN_LRCK = 28;  // Use different LRCK pin for Feather Express 52840
  aaAudio.maxBufferSize = AUDIO_BUFFER_SIZE;
  aaAudio.begin(0, 2);

  playAudio(audioFilename);
}

void loop() {

  loadBuffer();

  // Control via Serial for testing
  if (Serial.available()) {
    char c = Serial.read();
    if (c == '=') {
      volumeControl += 0.1;
    } else if (c == '-') {
      volumeControl -= 0.1;
      volumeControl = max(0.0, volumeControl);
    } else if (c == 'p') {
      playAudio("atliens.mp3");
    } else if (c == 'c') {
      playAudio("dopeBoys.mp3");
    }
    Serial.println(volumeControl);
  }
}


File myFile;

void playAudio(const char* audioFile) {

  MP3.end();
  if (myFile) {
    myFile.close();
  }
  aaAudio.disableDAC();

  //Open the designated file
  myFile = SD.open(audioFile);

  if (myFile) {

    MP3.begin(myFile);
    MP3.getMetadata();
    aaAudio.setSampleRate(MP3.Fs, 1);
    Serial.println(MP3.Fs);
    aaAudio.dacBitsPerSample = MP3.bitsPerSample;
    Serial.println(MP3.bitsPerSample);
  } else {
    Serial.println("Failed to open file");
  }
}

void loadBuffer() {

  uint32_t sampleCounter = 0;
  if (myFile.available() >= AUDIO_BUFFER_SIZE) {
    for (uint32_t i = 0; i < AUDIO_BUFFER_SIZE / 64; i++) {
      audio = MP3.decode();
      memcpy(&aaAudio.dacBuffer16[sampleCounter], audio.interleaved, 128);  // 128 bytes
      sampleCounter += 64;                                                  // 64 samples per go
    }
    for (uint32_t i = 0; i < AUDIO_BUFFER_SIZE; i++) {
      int16_t sample = aaAudio.dacBuffer16[i];
      sample *= volumeControl;
      aaAudio.dacBuffer16[i] = sample;
    }
    aaAudio.feedDAC(0, sampleCounter);
  } else {
    aaAudio.disableDAC();
  }
}
 

 



Using RF24Ethernet & RF24Gateway with the Arduino Cloud

 Using RF24Ethernet & RF24Gateway with the Arduino Cloud  Pushing automation even further  Recently, I was offered an Arduino Uno Q, Ard...