Skip to content

Communication NRF24

pschatzmann edited this page Oct 22, 2026 · 1 revision

The nRF24L01(+) is a cheap 2.4 GHz radio module that is connected via SPI. With up to 2 Mbit/s it is fast enough for uncompressed audio and has a very low latency - a nice choice for a wireless microphone or speaker with Arduino boards that have no WiFi. See Communication for the general considerations.

The NRF24Stream class

NRF24Stream (AudioTools/Communication/NRF24Stream.h) uses the RF24 library (install it). In TX_MODE the written data is sent in packets of payload_size bytes, in RX_MODE the received packets are collected in a buffer that you can read. It works on any board that is supported by RF24 (ESP32, Teensy, Nano, RP2040 ...).

You can pass your own RF24 object or receive buffer in the constructor; by default they are created for you.

Field (NRF24Config) Default Description
mode TX_MODE or RX_MODE (the parameter of defaultConfig())
pin_ce, pin_csn 9, 10 the pins of the module
channel 124 0..125: the upper channels are less crowded by WiFi
data_rate RF24_2MBPS RF24_250KBPS, RF24_1MBPS or RF24_2MBPS
pa_level RF24_PA_MAX the transmit power
payload_size 32 bytes per packet (max. 32)
address 0xF0F0F0F0E1 sender and receiver must use the same address
auto_ack false wait for acknowledgments and repeat lost packets
crc_length RF24_CRC_DISABLED check the packets with a CRC
use_write_fast true use writeFast() (no waiting for each packet)
max_begin_retry 10 retries if the module does not start

The defaults are tuned for a low latency: no acknowledgments and no CRC. Mono, 16 bit at 32 kHz reaches about 6.5 ms latency.

Sending and receiving

From the nrf24 examples. The sender:

#include "AudioTools.h"
#include "AudioTools/Communication/NRF24Stream.h"

AudioInfo info(32000, 1, 16);
SineGenerator<int16_t> sineWave(32000);
GeneratedSoundStream<int16_t> sound(sineWave);
NRF24Stream radio;
StreamCopy copier(radio, sound);

void setup() {
  auto cfg = radio.defaultConfig(TX_MODE);
  // cfg.pin_ce = 9;    // adjust for your board
  // cfg.pin_csn = 10;
  cfg.copyFrom(info);
  if (!radio.begin(cfg)) stop();
  sineWave.begin(info, N_B4);
}

void loop() { copier.copy(); }

The receiver:

AudioInfo info(32000, 1, 16);
NRF24Stream radio;
I2SStream i2s;
StreamCopy copier(i2s, radio);

void setup() {
  auto cfg = radio.defaultConfig(RX_MODE);
  cfg.copyFrom(info);
  radio.begin(cfg);

  auto icfg = i2s.defaultConfig(TX_MODE);
  icfg.copyFrom(info);
  i2s.begin(icfg);
}

void loop() { copier.copy(); }

Things to consider

  • Bandwidth: 2 Mbit/s is the raw air rate - in practice you get much less. 32 kHz mono 16 bit needs 512 kbit/s; stereo at 44.1 kHz (1.4 Mbit/s) is too much: use mono, a lower sample rate or a codec.
  • Data loss: without auto_ack lost packets are gone; with crc_length corrupted packets are dropped instead of played as noise. With PCM a lost packet is just a short glitch, but encoded data needs a codec or container that can resync.
  • Throttle: a generator or file produces data faster than the audio rate - put a Throttle before radio on the sending side, so that the receiver is not overrun. See also clock drift.
  • Power supply: the module needs a stable 3.3 V - add a 10 µF capacitor at the module, especially with the PA/LNA versions.

Clone this wiki locally