nrf24l01+ - I can't make it work with 2 buttons and 2 LEDs

Hi

I am a newbie and am trying to do a project involving nrf24l01+ modules, pushbuttons, and LEDs. As my eventual code will have quite a lot of different things going on, I'm trying to build it up slowly. My first code with just one button and one LED connected wirelessly worked fine, but when I added a second button controlling a second LED (basically two different simple wireless button-LED circuits), only one of the buttons made its light turn on.

I replaced all components that could be causing the problem: the button, the LED, the wires, and the resistors. Nothing worked. I have been running around in circles trying to figure out why this isn't working because it feels like if the first code with just one button worked, this should.

Could someone take a look at my badly-written, newbie code and let me know where I'm going wrong. I've linked my code below:
tx
rx

Thanks in advance :slight_smile:

I've linked my code below:

and the links take you out of the forum

This would be better

Tx : Arduino Cloud
Rx : Arduino Cloud

or even better

Tx code
Rx code

or even better
Tx code

#include "nRF24L01.h" // NRF24L01 library created by TMRh20 https://github.com/TMRh20/RF24
#include "RF24.h"
#include "SPI.h"

#define RLED_PIN 7
#define LLED_PIN 6

int ReceivedMessage[1] = {000}; // Used to store value received by the NRF24L01
RF24 radio(9,10); // NRF24L01 SPI pins. Pin 9 and 10 on the Nano

const uint64_t pipe = 0xE6E6E6E6E6E6; // Needs to be the same for communicating between 2 NRF24L01 

void setup(void)
{
  radio.begin(); // Start the NRF24L01
  
  radio.openReadingPipe(1,pipe); // Get NRF24L01 ready to receive
  
  radio.startListening(); // Listen to see if information received
  
  pinMode(RLED_PIN, OUTPUT);
  pinMode(LLED_PIN, OUTPUT);
}

void loop(void)
{
  while (radio.available())
  {
    radio.read(ReceivedMessage, 1); // Read information from the NRF24L01

    if (ReceivedMessage[0] == 111) // Indicates switch is pressed
    {
      digitalWrite(RLED_PIN, HIGH);
    }
    
    if (ReceivedMessage[0] == 222){
      digitalWrite(LLED_PIN, HIGH);
    }
    else
    {
      digitalWrite(RLED_PIN, LOW);
      digitalWrite(LLED_PIN, LOW);
    }
    delay(2);
   }
}

Rx code

#include "nRF24L01.h" // NRF24L01 library created by TMRh20 https://github.com/TMRh20/RF24
#include "RF24.h"
#include "SPI.h"

#define RLED_PIN 7
#define LLED_PIN 6

int ReceivedMessage[1] = {000}; // Used to store value received by the NRF24L01
RF24 radio(9,10); // NRF24L01 SPI pins. Pin 9 and 10 on the Nano

const uint64_t pipe = 0xE6E6E6E6E6E6; // Needs to be the same for communicating between 2 NRF24L01 

void setup(void)
{
  radio.begin(); // Start the NRF24L01
  
  radio.openReadingPipe(1,pipe); // Get NRF24L01 ready to receive
  
  radio.startListening(); // Listen to see if information received
  
  pinMode(RLED_PIN, OUTPUT);
  pinMode(LLED_PIN, OUTPUT);
}

void loop(void)
{
  while (radio.available())
  {
    radio.read(ReceivedMessage, 1); // Read information from the NRF24L01

    if (ReceivedMessage[0] == 111) // Indicates switch is pressed
    {
      digitalWrite(RLED_PIN, HIGH);
    }
    
    if (ReceivedMessage[0] == 222){
      digitalWrite(LLED_PIN, HIGH);
    }
    else
    {
      digitalWrite(RLED_PIN, LOW);
      digitalWrite(LLED_PIN, LOW);
    }
    delay(2);
   }
}

However, I think that both of your links go to the Rx code anyway so all bets are off

My bad. Here are the links:

Tx
Rx

Not sure how to attach them any other way

nicohsmith:
Not sure how to attach them any other way

Please include your code in your Post like it was done in Reply #1?

Use the code button
codeButton.png

See How to use the forum

...R

Not sure how to attach them any other way

Please follow the advice on posting a programming question given in Read this before posting a programming question

In particular note the advice to Auto format code in the IDE and to use code tags when posting code here

Robin2:
Please include your code in your Post like it was done in Reply #1?

Yes, thanks for the helpful picture. Sorry for the hassle.

tx:

#include "nRF24L01.h" //NRF24L01 library created by TMRh20 https://github.com/TMRh20/RF24
#include "RF24.h"
#include "SPI.h"

#define RSwitchPin 3
#define LSwitchPin 2

int SentMessage[1] = {000}; 
RF24 radio(9,10); // NRF24L01 used SPI pins + Pin 9 and 10 on the NANO

const uint64_t pipe = 0xE6E6E6E6E6E6; // Needs to be the same for communicating between 2 NRF24L01 

void setup()
{
  pinMode(RSwitchPin, INPUT_PULLUP); 
  digitalWrite(RSwitchPin,HIGH); 
  pinMode(LSwitchPin, INPUT_PULLUP); 
  digitalWrite(LSwitchPin,HIGH); 
  
  radio.begin(); // Start the NRF24L01
  radio.openWritingPipe(pipe); // Get NRF24L01 ready to transmit
}

void loop()
{
  if (digitalRead(RSwitchPin) == LOW)    // If switch is pressed
  { 
      SentMessage[0] = 111;
      radio.write(SentMessage, 1);      // Send pressed data to NRF24L01
  }
  if (digitalRead(LSwitchPin) == LOW){
      SentMessage[0] = 222;
      radio.write(SentMessage, 1);      // Send pressed data to NRF24L01
  }
  else 
  {
      SentMessage[0] = 000;
      radio.write(SentMessage, 1);      // Send idle data to NRF24L01
  }
}

rx:

#include "nRF24L01.h" // NRF24L01 library created by TMRh20 https://github.com/TMRh20/RF24
#include "RF24.h"
#include "SPI.h"

#define RLED_PIN 7
#define LLED_PIN 6

int ReceivedMessage[1] = {000}; // Used to store value received by the NRF24L01
RF24 radio(9,10); // NRF24L01 SPI pins. Pin 9 and 10 on the Nano

const uint64_t pipe = 0xE6E6E6E6E6E6; // Needs to be the same for communicating between 2 NRF24L01 

void setup(void)
{
  radio.begin(); // Start the NRF24L01
  
  radio.openReadingPipe(1,pipe); // Get NRF24L01 ready to receive
  
  radio.startListening(); // Listen to see if information received
  
  pinMode(RLED_PIN, OUTPUT);
  pinMode(LLED_PIN, OUTPUT);
}

void loop(void)
{
  while (radio.available())
  {
    radio.read(ReceivedMessage, 1); // Read information from the NRF24L01

    if (ReceivedMessage[0] == 111) // Indicates switch is pressed
    {
      digitalWrite(RLED_PIN, HIGH);
    }
    
    if (ReceivedMessage[0] == 222){
      digitalWrite(LLED_PIN, HIGH);
    }
    else
    {
      digitalWrite(RLED_PIN, LOW);
      digitalWrite(LLED_PIN, LOW);
    }
    delay(2);
   }
}

I don't get what's going wrong with this. Only one LED turns on, the other just doesn't respond to the button.
Any help would really be appreciated.

You have a bunch of stuff wrong in this (from the TX) - and corresponding mistakes in the RX code

{
  if (digitalRead(RSwitchPin) == LOW)    // If switch is pressed
  { 
      SentMessage[0] = 111;
      radio.write(SentMessage, 1);      // Send pressed data to NRF24L01
  }
  if (digitalRead(LSwitchPin) == LOW){
      SentMessage[0] = 222;
      radio.write(SentMessage, 1);      // Send pressed data to NRF24L01
  }
  else 
  {
      SentMessage[0] = 000;
      radio.write(SentMessage, 1);      // Send idle data to NRF24L01
  }
}

If you want to read two buttons you should create an array with two elements

int SentMessage[2];

and save the values into it like this

SentMessage[0] = digitalRead(RSwitchPin);
SentMessage[1] = digitalRead(LSwitchPin);

and then send the arrray like this

radio.write(SentMessage, sizeof(SentMessage));

Note the use of sizeof() which returns the number of bytes in the variable. In your code you are sending an int which is two bytes long but your send instruction tells the radio to send a single byte radio.write(SentMessage, 1)

Note that sending the two values in a single message is much more reliable. It also means that the RX always knows which value is which.

Your TX sends messages as quickly as loop() can repeat - which is very very fast. Sending messages once every 200 millisecs (5 per second) should be ample and it allows time for the RX to process the data.

If you send a message at a regular interval it is easy for the RX to determine if the TX fails and take appropriate action.

On the RX side you should define ReceivedMessage to exactly match SentMessage in the TX program. And you should receive the data like this

radio.read(ReceivedMessage, sizeof(ReceivedMessage);

in which case ReceivedMessage[0] will have the state of the RSwitch and ReceivedMessage[1] will have the state of the LSwitch

...R

Robin2:

{

if (digitalRead(RSwitchPin) == LOW)    // If switch is pressed
 {
     SentMessage[0] = 111;
     radio.write(SentMessage, 1);      // Send pressed data to NRF24L01
 }
 if (digitalRead(LSwitchPin) == LOW){
     SentMessage[0] = 222;
     radio.write(SentMessage, 1);      // Send pressed data to NRF24L01
 }
 else
 {
     SentMessage[0] = 000;
     radio.write(SentMessage, 1);      // Send idle data to NRF24L01
 }
}




If you want to read two buttons you should create an array with two elements


int SentMessage[2];



and save the values into it like this


SentMessage[0] = digitalRead(RSwitchPin);
SentMessage[1] = digitalRead(LSwitchPin);



and then send the arrray like this


radio.write(SentMessage, sizeof(SentMessage));

Thanks so much that's really useful. To be honest I just took the code that worked for one button and thought ctrl c+v wouldn't change what was going on.
So just to clarify, is this code right?
tx:

#include "nRF24L01.h" //NRF24L01 library created by TMRh20 https://github.com/TMRh20/RF24
#include "RF24.h"
#include "SPI.h"

#define RSwitchPin 3
#define LSwitchPin 2

int SentMessage[2]; 
RF24 radio(9,10); // NRF24L01 used SPI pins + Pin 9 and 10 on the NANO

const uint64_t pipe = 0xE6E6E6E6E6E6; // Needs to be the same for communicating between 2 NRF24L01 

void setup()
{
  pinMode(RSwitchPin, INPUT_PULLUP); 
  digitalWrite(RSwitchPin,HIGH); 
  pinMode(LSwitchPin, INPUT_PULLUP); 
  digitalWrite(LSwitchPin,HIGH); 
  
  radio.begin(); // Start the NRF24L01
  radio.openWritingPipe(pipe); // Get NRF24L01 ready to transmit
}

void loop()
{
  
  SentMessage[0] = digitalRead(RSwitchPin);
  SentMessage[1] = digitalRead(LSwitchPin);
  radio.write(SentMessage, size of(SentMessage));
  delay(200);
}

rx:

#include "nRF24L01.h" // NRF24L01 library created by TMRh20 https://github.com/TMRh20/RF24
#include "RF24.h"
#include "SPI.h"

#define RLED_PIN 7
#define LLED_PIN 6

int ReceivedMessage[2]; // Used to store value received by the NRF24L01
RF24 radio(9,10); // NRF24L01 SPI pins. Pin 9 and 10 on the Nano

const uint64_t pipe = 0xE6E6E6E6E6E6; // Needs to be the same for communicating between 2 NRF24L01 

void setup()
{
  radio.begin(); // Start the NRF24L01
  
  radio.openReadingPipe(1,pipe); // Get NRF24L01 ready to receive
  
  radio.startListening(); // Listen to see if information received
  
  pinMode(RLED_PIN, OUTPUT);
  pinMode(LLED_PIN, OUTPUT);
}

void loop(void)
{
  while (radio.available())
  {
    radio.read(ReceivedMessage, 2); // Read information from the NRF24L01

    if (ReceivedMessage[0] == LOW) // Indicates switch is pressed
    {
      digitalWrite(RLED_PIN, HIGH);
    }
    
    if (ReceivedMessage[1] == LOW){
      digitalWrite(LLED_PIN, HIGH);
    }
    else
    {
      digitalWrite(RLED_PIN, LOW);
      digitalWrite(LLED_PIN, LOW);
    }
    delay(2);
   }
}

That looks OK. Does it work ?

SentMessage and ReceivedMessage could be byte variables rather than ints. Why send more data than you need ?

Another suggestion. You could replace this

    if (ReceivedMessage[0] == LOW) // Indicates switch is pressed
    {
      digitalWrite(RLED_PIN, HIGH);
    }

with

digitalWrite(RLED_PIN, !ReceivedMessage[0]);

then you don't need the else clause as both cases will be taken care of

UKHeliBob:
That looks OK. Does it work ?

SentMessage and ReceivedMessage could be byte variables rather than ints. Why send more data than you need ?

Another suggestion. You could replace this

    if (ReceivedMessage[0] == LOW) // Indicates switch is pressed

{
     digitalWrite(RLED_PIN, HIGH);
   }



with


digitalWrite(RLED_PIN, !ReceivedMessage[0]);



then you don't need the else clause as both cases will be taken care of

That is a way neater way of writing it.
I had that if clause in there because my final code will use an LED matrix instead, so the variables don't sub in as nicely.
Also, how come sending a byte variable sends less data than an int if the actual value is the same? (I've never actually been taught this stuff I've just pieced together a fractured knowledge from various projects)

nicohsmith:
Also, how come sending a byte variable sends less data than an int if the actual value is the same? (I've never actually been taught this stuff I've just pieced together a fractured knowledge from various projects)

In a computer program different amounts of memory can be set aside for variables.

The smallest allocation unit is an 8-bit byte which can hold values from 0 to 255 or an 8-bit char which can hold values from -128 to + 127.

If you need a larger range of values an int uses 2 bytes (16 bits) so it can store numbers between -32768 and +32767 or an unsigned int which can hold values between 0 and 65535. Note that 216 = 65536 but computers count from 0 hence 65535

For even larger numbers there is a long which uses 4 bytes (32 bits) which can store values from -2,147,483,648 to +2,147,483,647 (if I have copied correctly from my calculator. I leave it to you as an exercise to figure the range for an unsigned long.

Arduinos have very little memory space so you should always use the smallest data type that is suitable.

...R

Also, how come sending a byte variable sends less data than an int if the actual value is the same?

An int variable takes 2 bytes to hold a value even if the value is only 0 or 1 so sending each int variable causes 2 bytes to be sent. A byte, however, can hold values up to 255 in one byte and sending each byte variable causes 1 byte to be sent.

If you want to get really clever you could put the 0/1 values of the inputs in 2 bits of the same byte and only send one byte. This would, however, come at the expense of more code at each end. In fact you could send 8 separate 0/1 values as bits in a byte and still only send a single byte

UKHeliBob:
That looks OK. Does it work ?

No. I've just run it and I'm getting the same problem.
Only one of the LEDs turns on.
The buttons both definitely are't broken. Neither are the LEDs. The nrfs obviously are working because one of the LEDs connects.

I'm connecting both the buttons to the same ground (because the nrf24 uses the other one) so I added LEDs into each of the button circuits (they were the only diodes I had on me). I'm also connecting both of the slave LEDs to the same ground, for the same reason. Could that have something to do with it?

I cannot make sense of what you are describing

Please post a schematic. Drawing the circuit with pencil and paper and attaching a picture of it is good enough

UKHeliBob:
I cannot make sense of what you are describing

Please post a schematic. Drawing the circuit with pencil and paper and attaching a picture of it is good enough

I've attached circuit diagrams.
Substitute Uno for Nano Every. There's also the nrf24l01+ wires at D13,12,11,10,9 GND and 3.3V.

Only one of the rx leds lights up when its corresponding button is pressed, but both the tx leds do light up when their button is pressed.

Tx.png

Rx.png

Tx.png

Rx.png

What do you see if you print the state of both inputs on the Tx ?

so I added LEDs into each of the button circuits (they were the only diodes I had on me).

Why do you need diodes in the first place ? Connect one side of each switch together then to GND. Connect the other side of each switch to its own Arduino pin. No diodes/LEDs or resistors needed

UKHeliBob:
What do you see if you print the state of both inputs on the Tx ?

Ok so I set up serial communication and the Tx works just fine. The Rx's serial communication is unexpected.
Here's the code with serial comms:

#include "nRF24L01.h" // NRF24L01 library created by TMRh20 https://github.com/TMRh20/RF24
#include "RF24.h"
#include "SPI.h"

#define RLED_PIN 7
#define LLED_PIN 6

int ReceivedMessage[2]; // Used to store value received by the NRF24L01
RF24 radio(9,10); // NRF24L01 SPI pins. Pin 9 and 10 on the Nano

const uint64_t pipe = 0xE6E6E6E6E6E6; // Needs to be the same for communicating between 2 NRF24L01 

void setup()
{
  Serial.begin(9600);
  Serial.println("Rx Beginning");
  
  radio.begin(); // Start the NRF24L01
  
  radio.openReadingPipe(1,pipe); // Get NRF24L01 ready to receive
  
  radio.startListening(); // Listen to see if information received
  
  pinMode(RLED_PIN, OUTPUT);
  pinMode(LLED_PIN, OUTPUT);
}

void loop(void)
{
  while (radio.available())
  {
    radio.read(ReceivedMessage, sizeof(ReceivedMessage)) ; // Read information from the NRF24L01

    if (ReceivedMessage[0] == LOW) // Indicates switch is pressed
    {
      Serial.println(ReceivedMessage[0]);
      digitalWrite(RLED_PIN, HIGH);
    }
    
    if (ReceivedMessage[1] == LOW){
      digitalWrite(LLED_PIN, HIGH);
      Serial.println(ReceivedMessage[1]);
    }
    else
    {
      digitalWrite(RLED_PIN, LOW);
      digitalWrite(LLED_PIN, LOW);
      Serial.println("Nothing");
    }
    delay(2);
   }
}

Here's the serial monitor with, in order, no buttons, then RButton pressed, then LButton pressed, then both. The serial communication for no buttons, Lbutton and both buttons makes sense, but why is the Rbutton flickering on and off?

no buttons.PNG

Rbutton.PNG

Lbutton.PNG

both buttons.PNG

no buttons.PNG

Rbutton.PNG

Lbutton.PNG

both buttons.PNG

I cannot make much sense of your Fritzing picture. Can you please post a circuit diagram as previously suggested.

Note: you can copy the test from the Serial monitor by selecting it using the mouse then using Ctr/C to copy it to the clipboard to be posted here in code tags

UKHeliBob:
I cannot make much sense of your Fritzing picture. Can you please post a circuit diagram as previously suggested.

This is what is going on:
Button circuits:
Pin2 > Pushbutton1 > Ground
Pin3 > Pushbutton2 > Same Ground pin as Pushbutton 1
LED circuits:

Pin 7 > 4.7 kOhm resistor > LED1 > Ground
Pin 6 > 4.7 kOhm resistor > LED2 > Same ground pin as LED1

Hope that helps