Arduino library 路 Communication

RF24: two Arduinos talking over nRF24L01 radios

RF24 drives Nordic鈥檚 nRF24L01+, the cheap 2.4 GHz transceiver used for remote controls, sensor nodes and robot links. The radio does a lot itself: each packet carries up to 32 bytes, the receiver sends an acknowledgment, and the sender retries automatically, so radio.write() returns true only when the other side really got it.

Built in on Mokxi: #include <RF24.h> and it builds, with nothing to install. Free, and no account needed.

What RF24 does

Communication is through pipes, named by addresses up to five bytes long, such as "00001". The sender opens a writing pipe and calls stopListening(); the receiver opens a reading pipe with the same address and calls startListening(). A receiver can listen on six pipes at once, which is how one base station hears several nodes.

The module runs on 3.3 V and is fussy about it. Its current spikes when it transmits, and an Uno鈥檚 3.3 V pin cannot always supply them, so a 10 碌F capacitor across the module鈥檚 power pins, or an adapter board with its own regulator, fixes most "it works sometimes" problems.

Library Manager nameRF24
AuthorTMRh20
Include#include <RF24.h>
#include <nRF24L01.h>
#include <printf.h>
Boardsevery board Mokxi compiles for but ATtiny85
In the simulatorSimulated: it runs against the part the way it does on the bench.
Parts it drives2.4 GHz radio, nRF24L01+

Install it

It builds on every board Mokxi compiles for but ATtiny85.

In Mokxi it is built in: #include <RF24.h> and the sketch compiles, with no download, no zip and no Library Manager.

On a real board, install "RF24" by TMRh20 from the Arduino IDE鈥檚 Library Manager (Sketch, Include Library, Manage Libraries), or add RF24 to lib_deps in PlatformIO. Mokxi follows the calls of release 1.5.0, so a sketch written here builds there too.

ESP32-C3 路 Arduino Uno 路 Arduino Nano 路 Arduino Mega 2560 路 Arduino Leonardo 路 SparkFun Pro Micro 路 Arduino Micro 路 ESP32-C6 路 Raspberry Pi Pico 路 Raspberry Pi Pico W 路 Seeed XIAO SAMD21 路 STM32 路 STM32 Nucleo-F411RE 路 STM32 Blue Pill 路 micro:bit V2 路 Arduino Uno R4 路 ESP32 DevKit 路 ESP32-S3-DevKitC-1 路 ESP8266 NodeMCU 路 Arduino Pro Mini 3.3 V 路 Seeed XIAO ESP32-C3 路 ESP32-C3 SuperMini 路 Seeed XIAO ESP32-C6 路 ESP32-DevKitC V4 路 LOLIN32 Lite 路 Wemos D1 R32 路 Cheap Yellow Display 路 TTGO T-Display 路 Seeed XIAO ESP32-S3 路 Arduino Nano ESP32 路 Arduino Nano RP2040 Connect 路 Seeed XIAO RP2040 路 Waveshare RP2040-Zero 路 Arduino Uno R4 WiFi

The calls you will use

In the order a sketch meets them.

RF24 radio(7, 8)

Creates the radio with CE on pin 7 and CSN on pin 8. The SPI pins are the board鈥檚 own.

radio.begin()

Starts the radio and returns false if it does not answer on SPI.

radio.openWritingPipe(address)

Sets the address to send to, a five-byte array like const byte address[6] = "00001".

radio.openReadingPipe(0, address)

Listens on pipe 0 (up to 5) for packets sent to that address.

radio.setPALevel(RF24_PA_MIN)

Sets the transmit power, from RF24_PA_MIN to RF24_PA_MAX. Use MIN when the two radios sit on one desk, since MAX can swamp a nearby receiver.

radio.stopListening()

Puts the radio in transmit mode. The receiver calls radio.startListening() instead.

radio.write(&text, sizeof(text))

Sends up to 32 bytes and waits for the acknowledgment. Returns true when the receiver confirmed it.

const char text[] = "Hello World";
bool ok = radio.write(&text, sizeof(text));
Serial.println(ok ? "sent" : "failed");

radio.available()

True when a packet is waiting; read it with radio.read(&buffer, sizeof(buffer)).

radio.printDetails()

Prints the radio鈥檚 registers to Serial (with printf_begin() from printf.h first), the quickest way to see if SPI works at all.

Example: Radio doorbell

On the Arduino Uno R3. It runs in the browser exactly as printed.

sketch.ino 路 Arduino Uno R3
// Radio doorbell, the sending end.
//
// Press the button and this Uno sends a packet over its nRF24L01 to the other
// Uno, which rings. radio.write() waits for the other radio's acknowledgement
// and says whether it came: take the receiving board's program away, or put
// its radio on another channel, and every press prints "no answer".
//
// Both radios have to agree on three things: the channel (76 is RF24's
// default), the data rate, and the address, "00001" here. Change any one of
// them on one side only and the packets go nowhere.

#include <SPI.h>
#include <nRF24L01.h>
#include <RF24.h>

RF24 radio(7, 8); // CE on 7, CSN on 8
const byte address[6] = "00001";

const int BUTTON = 2;
int presses = 0;

void setup()
{
    Serial.begin(9600);
    pinMode(BUTTON, INPUT_PULLUP);
    radio.begin();
    radio.openWritingPipe(address);
    radio.setPALevel(RF24_PA_MIN);
    radio.stopListening();
    Serial.println("Press the button to ring.");
}

void loop()
{
    if (digitalRead(BUTTON) == HIGH) {
        return;
    }
    presses++;
    char message[32] = "ding dong ";
    message[10] = (char)('0' + presses % 10);
    bool heard = radio.write(&message, sizeof(message));
    Serial.print(message);
    Serial.println(heard ? ": delivered" : ": no answer");
    // Wait for the button to come back up, so one press is one ring.
    while (digitalRead(BUTTON) == LOW) {
        delay(10);
    }
    delay(50);
}

Open it in the editor, wired and ready to run 路 Radio doorbell: the project page

Common errors and how to fix them

radio.write() always returns false

No acknowledgment came back: the receiver is off, on another channel or data rate, or listening on a different address. Make the address bytes identical on both sides and call startListening() on the receiver.

printDetails() shows all zeros or all 0xFF

The radio is not talking over SPI. Check CE and CSN match the constructor, MOSI, MISO and SCK go to the SPI pins (11, 12, 13 on an Uno), and the module has 3.3 V, never 5 V.

It works for a few packets, then stops or resets the board

The 3.3 V supply sags when the radio transmits. Solder a 10 碌F to 100 碌F capacitor across VCC and GND at the module, or use an adapter with its own regulator, and lower the PA level.

Try RF24 without installing anything

Open the example, change the sketch, and keep your version in a free account.