NRF24L01+ Tranceiver Modules

12/08/18

Last modified on 12/08/18

Categories: Electronics Tags: Modules Arduino

After having a lot of issues with 433Mhz RF modules I decided to upgrade to NRF24L01, a popular 2.4-2.5GHz tranceiver with much better range (about 1000 meters in the open). The operating voltage is 1.9v to 3.6v and it uses SPI communication. You can get these modules with an antenna for extra range, so if you have a central device it can be useful to equip it with the antenna and use the smaller modules for the nodes.

On my modules, the antenna version had a pinout silkscreen and the other version did not, but they are the same. A word of warning, one of my modules arrived with the VIN/GND pins soldered together. I didn’t notice the short until I tried to use the module and it failed. Be sure to check the pins before use.

NRF24L01+ > Nano/Uno
1 GND > GND
2 VCC > 3.3V
3 CE (Chip Enable) > Any digital pin, check library & shield schematics / 8
4 CSN (Ship Select Not) > Any digital pin, check library / 10
5 SCK (Serial Clock) > 13 (SCK)
6 MOSI > 11 (MOSI)
7 MISO > 12 (MISO)
8 IRQ (interrupt) > N/A

I may have mentioned elsewhere I originally thought about using these with Digispark, but the 3.3V operating voltage and the number of needed pins deterred me. An Arduino Nano is a good fit, as it has a 3.3V pin and the NRF24L01’s pins are 5V tolerant. The connections will be the same for the transmitter and receiver Arduinos. We can use Paul Stoffregen’s Radiohead library here and client/server examples are available

Examples > RadioHead > nrf24 > nrf24_server
Examples > RadioHead > nrf24 > nrf24_client

Whatever library you use, check to see how CE and CSN are defined. I found my wireless breakout shield was mapping CE to 9, and the default in RadioHead was 8, so that had to be remapped through the RH_NRF24 object: RH_NRF24 nrf24(9,10);

I had a little trouble figuring out how to send temperature and humidity data, but neato3000’s code example was very helpful.

If you have connectivity issues, consider soldering a 10uf capactior between the GND #1 (cap positive) and VCC #2 (cap netgative) pins. See:
https://www.instructables.com/id/NRF24L01-Fixing-Connection-Issues/
https://www.youtube.com/watch?v=jfaFbjgwprI

Example for sending humidity data:

#include <RH_NRF24.h> //https://github.com/PaulStoffregen/RadioHead/
#include <DHT.h>  //https://github.com/adafruit/DHT-sensor-library
#include <SPI.h>

const byte dhtDataPin = 6;
unsigned long currentTime = 0;
unsigned long previousReadingTime = 0;
unsigned long readingDelay = 600000; //10 minutes

RH_NRF24 nrf24;
DHT dht(dhtDataPin, DHT22);

void setup(){
  Serial.begin(9600);
  while (!Serial)
    ;
  dht.begin();
  if (!nrf24.init())
    Serial.println("init failed");
  // Defaults after init are 2.402 GHz (channel 2), 2Mbps, 0dBm
  if (!nrf24.setChannel(1))
    Serial.println("setChannel failed");
  if (!nrf24.setRF(RH_NRF24::DataRate2Mbps, RH_NRF24::TransmitPower0dBm))
    Serial.println("setRF failed");
}

void loop(){
  currentTime = millis();
  if((currentTime - previousReadingTime) > readingDelay){
    int humidity = dht.readHumidity();
    uint8_t data[] = "Hello World!";
    data[0] = highByte(humidity);
    data[1] = lowByte(humidity);
    nrf24.send(data, sizeof(data));
    nrf24.waitPacketSent();
    previousReadingTime = currentTime;
  }
}

Receiving code, trimmed to remove unrelated display module stuff:

#include <RH_NRF24.h> // https://github.com/PaulStoffregen/RadioHead/
#include <SPI.h> // Needed to compile RadioHead

...

RH_NRF24 nrf24(9,10);

void setup(){
  Serial.begin(9600);
  while (!Serial)
    ; // wait for serial port to connect. Needed for Leonardo only
  if (!nrf24.init())
    Serial.println("init failed");
  // Defaults after init are 2.402 GHz (channel 2), 2Mbps, 0dBm
  if (!nrf24.setChannel(1))
    Serial.println("setChannel failed");
  if (!nrf24.setRF(RH_NRF24::DataRate2Mbps, RH_NRF24::TransmitPower0dBm))
    Serial.println("setRF failed");
}

void loop() {
  uint16_t input[1] = {0};
  int digit2;
  int digit1;
  if (nrf24.available()){
    uint8_t buf[RH_NRF24_MAX_MESSAGE_LEN];
    uint8_t len = sizeof(buf);
    if (nrf24.recv(buf, &len)){
      input[0] = buf[0] << 8;
      input[0] = input[0] | buf[1];
      digit2 = (input[0]) % 10;
      digit1 = (input[0]/10) % 10;
    }
    else {
      Serial.println("Receiver failed");
    }
  }
  tm1637.display(0,digit1);
  tm1637.display(1,digit2);
  tm1637.display(2,R);
  tm1637.display(3,H);
}