Nextion Nrf24L01+ remote for neopixel troublshooting

Hello everyone,

My project is a wireless remote control for a neopixel 8 led stick. A Nextion display is used with 3 buttons. When button is pressed a number (0,1 or 2) is sent to an Uno. The Uno sends a message to a nano wirelessly through two Nrf24L01 radios with a value (100, 101 or 111) representing the button touched. Based on this, leds turn 1 of 3 light displays.

My problem is that after about 20mins the leds stop, all leds turn off.

I have also noticed that when I disconnect uno(transmitter) the leds on the nano freeze.

I would like for a chosen led animation to continue indefinitely or until another option is chosen. As well as if the remote (transmitter) is out of range, leds will continue displaying.

Transmitter sketch:

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


int SentMessage[1] = {000}; // Used to store value before being sent through the NRF24L01

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(void) {

  Serial.begin(9600);



  radio.begin(); // Start the NRF24L01
  radio.openWritingPipe(pipe); // Get NRF24L01 ready to transmit
}

void loop(void) {

  if (Serial.available() > 0)               //If we receive something...
  {
    String Received = Serial.readString();  //Save the received String in the Received variable
    if (int(Received[0]) == 1)              //If  character  "Received" is "1"

      SentMessage[0] = 100;                 //send message "100"
    radio.write(SentMessage, 1);


    if (int(Received[0]) == 0)              //If the character of "Received" is "0"

      SentMessage[0] = 111;                 //send message "111"
    radio.write(SentMessage, 1);



    if (int(Received[0]) == 2)              //If the first character of "Received" is "2"

      SentMessage[0] = 101;                 //send message "101"
    radio.write(SentMessage, 1);

  }

}

Receiver sketch:

#include <Adafruit_NeoPixel.h>

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



#define PIXEL_PIN    6    // Digital IO pin connected to the NeoPixels.

#define PIXEL_COUNT 8 //number of LEDs


Adafruit_NeoPixel strip = Adafruit_NeoPixel(PIXEL_COUNT, PIXEL_PIN, NEO_GRB + NEO_KHZ800);




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
int ReceivedMessage[1] = {000};

void setup() {
 
  strip.begin();
  strip.show(); // Initialize all pixels to 'off'

  radio.begin(); // Start the NRF24L01

  radio.openReadingPipe(1, pipe); // Get NRF24L01 ready to receive

  radio.startListening(); // Listen to see if information received

}

void loop() {

   if (radio.available())
         
    radio.read(ReceivedMessage, 1);
    
  if (ReceivedMessage[0] == 101) //number sent by transmitter
    
    colorWipe(strip.Color(255, 0, 0), 50);  // led animation

    if (ReceivedMessage[0] == 100)
  theaterChase(strip.Color(127,   0,   0), 50); // led animation
   

     if (ReceivedMessage[0] == 111)
      rainbow(20);

 
}

//Led show

// Fill the dots one after the other with a color
void colorWipe(uint32_t c, uint8_t wait) {
  for(uint16_t i=0; i<strip.numPixels(); i++) {
    strip.setPixelColor(i, c);
    strip.show();
    delay(wait);
  }
}

void rainbow(uint8_t wait) {
  uint16_t i, j;

  for(j=0; j<256; j++) {
    for(i=0; i<strip.numPixels(); i++) {
      strip.setPixelColor(i, Wheel((i+j) & 255));
    }
    strip.show();
    delay(wait);
  }
}



//Theatre-style crawling lights.
void theaterChase(uint32_t c, uint8_t wait) {
  for (int j=0; j<10; j++) {  //do 10 cycles of chasing
    for (int q=0; q < 3; q++) {
      for (int i=0; i < strip.numPixels(); i=i+3) {
        strip.setPixelColor(i+q, c);    //turn every third pixel on
      }
      strip.show();

      delay(wait);

      for (int i=0; i < strip.numPixels(); i=i+3) {
        strip.setPixelColor(i+q, 0);        //turn every third pixel off
      }
    }
  }
}



// Input a value 0 to 255 to get a color value.
// The colours are a transition r - g - b - back to r.
uint32_t Wheel(byte WheelPos) {
  WheelPos = 255 - WheelPos;
  if(WheelPos < 85) {
    return strip.Color(255 - WheelPos * 3, 0, WheelPos * 3);
  }
  if(WheelPos < 170) {
    WheelPos -= 85;
    return strip.Color(0, WheelPos * 3, 255 - WheelPos * 3);
  }
  WheelPos -= 170;
  return strip.Color(WheelPos * 3, 255 - WheelPos * 3, 0);
}

Any gurus can point me in right direction? Thank you for your time.
Mike.

I am not a guru (unless I found a problem with your receive code), but it looks to me that if the radio is not available, nothing happens. All of your calls to the effects are inside of if(radio.available());.

If the radio doesn't respond with an expected code, as if the receiver is just slightly out of range, then it will never do anything until the radio is back in range.

Try this:

void loop() {
  if (radio.available()) radio.read(ReceivedMessage, 1);
  if (ReceivedMessage[0] == 101 || ReceivedMessage[0] == 100 || ReceivedMessage[0] == 111 ) 
  iMessage = ReceivedMessage[0];
 
  switch (iMessage) {
    case 101:
      colorWipe(strip.Color(255, 0, 0), 50);  // led animation
      break;
    case 100:
      theaterChase(strip.Color(127,   0,   0), 50); // led animation
      break;
    case 111:
      rainbow(20);
      break;
    default:
      rainbow(20);
      break;
  }
}

This way, if the radio is out of range or receives a bogus code, then the last code will execute until the radio gets another good code. The default is probably redundant.

But, I am highly confused with your int declaration. Do you really intend ReceivedMessage to be an array of one integer?

int ReceivedMessage[1] = {000};
    if (int(Received[0]) == 1)              //If  character  "Received" is "1"

      SentMessage[0] = 100;                 //send message "100"
    radio.write(SentMessage, 1);


    if (int(Received[0]) == 0)              //If the character of "Received" is "0"

      SentMessage[0] = 111;                 //send message "111"
    radio.write(SentMessage, 1);



    if (int(Received[0]) == 2)              //If the first character of "Received" is "2"

      SentMessage[0] = 101;                 //send message "101"
    radio.write(SentMessage, 1);

I think all that ifs should have a {} to control the radio.writes too.
You are sending three messages with possible different commands on each serial command now.

Sending and receiving a single byte from and to a one element integer array is very strange at least.
And this byte will be transported with 31 zeros padding just to pollute the medium.

The "if" is a problem here, I like the switch approach, but a quick test returned "iMessage not declared in this scope." But I thank you, I will go the switch route.

I had curly brackets with the "ifs" but if I remember correctly they caused an issue with an "else" statement anyway you are right, I need to put them back.

No I don't like the int declaration myself, I am looking at a different way to package the data.

But I thank you, after some work, I will report back as to how things went...

Change

iMessage = ReceivedMessage[0];

to

int iMessage = ReceivedMessage[0];

My problem is that after about 20mins the leds stop, all leds turn off.

Using String class on something as small as an UNO or Nano will sometimes do that. Switch to reading into an array of char and you might come out better.

It’s probably also not helpful that your led routines are all blocking. So you’re ignoring your radio most of the time. Are you sure you’re not sending stuff to it while you ignore it?

Those led effect functions you’re using are meant as a demonstration. A way to see how to write colors to the leds. They’re not generally any good for any actual program because they block.

knock on wood its working :o

So I can unplug Uno completely and LEDs continue their show on nano. They don't stop anymore.

I added a serial.print at receiver end and strange thing that even though I press button once, serial reports continuously: 100,100,100...

Sketch needs some cleanup still but I am sharing it here.

Yes the led sketch is blocking (with all the delays) thanks for pointing that out, I can work on that. I know its blocking because sometimes I have to press button several times before any effect takes place.

#include <Adafruit_NeoPixel.h>

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



#define PIXEL_PIN    6    // Digital IO pin connected to the NeoPixels.

#define PIXEL_COUNT 8 //number of LEDs


Adafruit_NeoPixel strip = Adafruit_NeoPixel(PIXEL_COUNT, PIXEL_PIN, NEO_GRB + NEO_KHZ800);




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
int ReceivedMessage[1];

void setup() {
  Serial.begin(115200);
  strip.begin();
  strip.show(); // Initialize all pixels to 'off'

  radio.begin(); // Start the NRF24L01

  radio.openReadingPipe(1, pipe); // Get NRF24L01 ready to receive

  radio.startListening(); // Listen to see if information received

}

void loop() {
  if (radio.available()) radio.read(ReceivedMessage, 1);

  int iMessage = ReceivedMessage[0];
  Serial.println(iMessage);

  if (ReceivedMessage[0] == 101 || ReceivedMessage[0] == 100 || ReceivedMessage[0] == 111 )

    switch (iMessage) {
      case 101:
        colorWipe(strip.Color(255, 0, 0), 50);  // led animation
        break;
      case 100:
        theaterChase(strip.Color(127,   0,   0), 50); // led animation
        break;
      case 111:
        rainbow(20);
        break;
      default:
        rainbow(20);
        break;
    }

  else {}

}

//Led show

// Fill the dots one after the other with a color
void colorWipe(uint32_t c, uint8_t wait) {
  for (uint16_t i = 0; i < strip.numPixels(); i++) {
    strip.setPixelColor(i, c);
    strip.show();
    delay(wait);
  }
}

void rainbow(uint8_t wait) {
  uint16_t i, j;

  for (j = 0; j < 256; j++) {
    for (i = 0; i < strip.numPixels(); i++) {
      strip.setPixelColor(i, Wheel((i + j) & 255));
    }
    strip.show();
    delay(wait);
  }
}



//Theatre-style crawling lights.
void theaterChase(uint32_t c, uint8_t wait) {
  for (int j = 0; j < 10; j++) { //do 10 cycles of chasing
    for (int q = 0; q < 3; q++) {
      for (int i = 0; i < strip.numPixels(); i = i + 3) {
        strip.setPixelColor(i + q, c);  //turn every third pixel on
      }
      strip.show();

      delay(wait);

      for (int i = 0; i < strip.numPixels(); i = i + 3) {
        strip.setPixelColor(i + q, 0);      //turn every third pixel off
      }
    }
  }
}



// Input a value 0 to 255 to get a color value.
// The colours are a transition r - g - b - back to r.
uint32_t Wheel(byte WheelPos) {
  WheelPos = 255 - WheelPos;
  if (WheelPos < 85) {
    return strip.Color(255 - WheelPos * 3, 0, WheelPos * 3);
  }
  if (WheelPos < 170) {
    WheelPos -= 85;
    return strip.Color(0, WheelPos * 3, 255 - WheelPos * 3);
  }
  WheelPos -= 170;
  return strip.Color(WheelPos * 3, 255 - WheelPos * 3, 0);
}

Thank you!