Uniostar
Published © GPL3+

Arduino Nrf24lo1 Range Expander (Relay Node)

Boost your Arduino nRF24L01 range 2 times with this simple relay node! Extend wireless communication with low power use.

IntermediateFull instructions provided3 hours74
Arduino Nrf24lo1 Range Expander (Relay Node)

Things used in this project

Hardware components

Arduino UNO
Arduino UNO
×2
Arduino Nano R3
Arduino Nano R3
×1
nRF24 Module (Generic)
×3
Capacitor 10 µF
Capacitor 10 µF
×3
RGB Diffused Common Cathode
RGB Diffused Common Cathode
×1
Resistor 1k ohm
Resistor 1k ohm
×1
Velleman AA 4 Battery Shield
×1
AA Batteries
AA Batteries
×1

Software apps and online services

Arduino IDE
Arduino IDE

Hand tools and fabrication machines

Soldering iron (generic)
Soldering iron (generic)

Story

Read more

Schematics

Receiver Schematic

Transmitter Schematic

Expander (Relay Node)

Code

Expander Code

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

#define redPin 4
#define greenPin 5
#define bluePin 6

RF24 radio(7, 8);  // CE, CSN
const byte fromTxAddress[6] = "88888";
const byte toRxAddress[6]   = "97777";

volatile bool wakeFlag = false;
unsigned long lastPacketTime = 0;

int data = 0;

void setup() 
{
  Serial.begin(9600);

  pinMode(redPin, OUTPUT);
  pinMode(greenPin, OUTPUT);
  pinMode(bluePin, OUTPUT);

  digitalWrite(bluePin, HIGH);
  
  radio.begin();
  radio.setPALevel(RF24_PA_LOW);
  radio.setDataRate(RF24_250KBPS);
  radio.setChannel(108);
  radio.openWritingPipe(toRxAddress);
  radio.openReadingPipe(1, fromTxAddress);
  radio.startListening();

  delay(1000);

  // Attach interrupt on falling edge (IRQ is active LOW)
  pinMode(2, INPUT_PULLUP);
  attachInterrupt(digitalPinToInterrupt(2), wakeUp, FALLING);
}

void loop() 
{
  if (millis() - lastPacketTime > 3000) {
    wakeFlag = false;
  }

  // Enter deep sleep until IRQ wakes us up
  if (!wakeFlag) 
  {
    digitalWrite(greenPin, LOW);
    digitalWrite(redPin, HIGH);
    LowPower.powerDown(SLEEP_FOREVER, ADC_OFF, BOD_OFF);
  }

  digitalWrite(greenPin, HIGH);
  digitalWrite(redPin, LOW);

  // Now we're awake — check if radio has data
  if (radio.available()) 
  {
    lastPacketTime = millis();

    radio.read(&data, sizeof(data));
    radio.stopListening();
    delay(5);
    radio.startListening();
  }
}

void wakeUp() 
{
  wakeFlag = true;
}

Receiver Code

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

RF24 radio(7, 8); // CE, CSN
const byte fromTransmitter[6] = "77777";
const byte fromRelay[6] = "97777";

int data = 0;

void setup() {
  Serial.begin(9600);

  radio.begin();
  radio.setPALevel(RF24_PA_MIN);
  radio.setDataRate(RF24_250KBPS);
  radio.setChannel(108);
  radio.openReadingPipe(1, fromTransmitter);
  radio.openReadingPipe(2, fromRelay);
  radio.startListening();
}

void loop() 
{
  uint8_t pipeNum;

  if (radio.available(&pipeNum)) 
  {
    radio.read(&data, sizeof(data));

    Serial.print("Data: ");
    Serial.print(data);
    Serial.print(" | From pipe: ");
    Serial.println(pipeNum);
  }
}

Transmitter Code

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

RF24 radio(7, 8); // CE, CSN

const byte receiverAddress[6] = "77777";
const byte relayAddress[6] = "88888";

int data = 0;

bool isReceiver = true;
unsigned long lastCheckTime = 0;

void setup() 
{
  Serial.begin(9600);

  radio.begin();
  radio.setPALevel(RF24_PA_MIN);
  radio.setDataRate(RF24_250KBPS);
  radio.setChannel(108);
  radio.setAutoAck(true); 
  radio.openWritingPipe(receiverAddress);
  radio.stopListening();
}

void loop() 
{
  // Read analog and digital inputs
  data = analogRead(A0);
  
  bool success = radio.write(&data, sizeof(data));

  if (!success && isReceiver) 
  {
    radio.openWritingPipe(relayAddress);
    isReceiver = false;
    lastCheckTime = millis();
  }
  else if (isReceiver)
  {
    // Sent to receiver
  }
  else 
  {
    radio.write(&data, sizeof(data));

    if (millis() - lastCheckTime >= 1000) 
    {
      radio.openWritingPipe(receiverAddress);
      bool checkSuccess = radio.write(&data, sizeof(data));
      
      if (checkSuccess) 
      {
        isReceiver = true;
      } 
      else 
      {
        radio.openWritingPipe(relayAddress);
      }
      
      lastCheckTime = millis();
    }
    else 
    {
      radio.write(&data, sizeof(data));
    }
  }
}

Credits

Uniostar
10 projects • 8 followers
Electrical Engineering Undergrad Student specialized in low-level programming, IoT projects, and microcontroller electronics.

Comments