NRF24L01 communication between 2arduinos to send 3 potentiometer values

Hi, I have estabelished a communication between two arduino pro mini boards using NRF24L01 chip on each arduino. First arduino is sending 3 potentiometer values. The second arduino is receiving those values and controlling 3 colors (RGB) on the RGB LED strip.

The problem is that the color isn't stable (three values are mixing and switching places) e.g. I turn on the red color and after a couple of minutes/seconds it changes to green or it just turns off and quickly turns on.

TRANSMITTER code:

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

int red[1];
int green[1];
int blue[1];


RF24 radio(9,10);
const uint64_t pipe = 0xE8E8F0F0E1LL;

void setup(){
  
  Serial.begin(9600);
  radio.begin();
  radio.openWritingPipe(pipe); 
  
  
}
void loop(){


  red[0] = analogRead(A1) / 4;
  green[0] = analogRead(A2) / 4;
  blue[0] = analogRead(A3) / 4;
  
  radio.write(red, sizeof(red)); 
  radio.write(green, sizeof(green));
  radio.write(blue, sizeof(blue));
  
    

}

RECEIVER code:

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

int red[1];
int blue[1];
int green[1];

int redVal;
int blueVal;
int greenVal;

int redOut = 3;
int blueOut = 5;
int greenOut = 6;

RF24 radio(9, 10);
const uint64_t pipe = 0xE8E8F0F0E1LL;

void setup() {

  Serial.begin(9600);
  pinMode (redOut, OUTPUT);
  pinMode (blueOut, OUTPUT);
  pinMode (greenOut, OUTPUT);

  radio.begin();
  radio.openReadingPipe(1, pipe);
  radio.startListening();

}
void loop() {

  if (radio.available()) {
    radio.read(red, sizeof(red));
    radio.read(blue, sizeof(blue));
    radio.read(green, sizeof(green));

    Serial.println(red[0]);
    Serial.println(blue[0]);
    Serial.println(green[0]);

    int redVal = red[0];
    int blueVal = blue[0];
    int greenVal = green[0];

    analogWrite(redOut, red);
    analogWrite(blueOut, blue);
    analogWrite(greenOut, green);

  }
}

You should put all three values into an array and send the array as a single radio.write(). That will ensure that the data is always received in the same order that it is sent.

Have a look at this Simple nRF24L01+ Tutorial.

...R

You may find that the pot values are bouncing, so that even when you don't turn the knob the reading is changing. I'm working on a sketch where the value of one pot is transmitted, and test to see if the new value is outside a range that allows for small variations:

potVal = analogRead(potPin); 
  if (potVal - 3 > potOldVal || potVal + 3 < potOldVal) {
...........
add code here

    potOldVal = potVal;
}

It ignores any change in value that's less than 3, which works with the pot I'm using, but you probably need to find what works for you by trial and error. This works nicely for me, although so far I've only got it showing changes on the serial monitor on the Rx, and not actually doing anything.

This is in addition to doing what Robin recommended.

Robin2:
You should put all three values into an array and send the array as a single radio.write(). That will ensure that the data is always received in the same order that it is sent.

Have a look at this Simple nRF24L01+ Tutorial.

...R

I checked your tutorial, it's great but I didn't find my solution. Can you write a code for creating an array in the master and for receiving the array in the slave?

Thank you for your help.

John_SB:
You may find that the pot values are bouncing, so that even when you don't turn the knob the reading is changing. I'm working on a sketch where the value of one pot is transmitted, and test to see if the new value is outside a range that allows for small variations:

potVal = analogRead(potPin); 

if (potVal - 3 > potOldVal || potVal + 3 < potOldVal) {
...........
add code here

potOldVal = potVal;
}



It ignores any change in value that's less than 3, which works with the pot I'm using, but you probably need to find what works for you by trial and error. This works nicely for me, although so far I've only got it showing changes on the serial monitor on the Rx, and not actually doing anything.

This is in addition to doing what Robin recommended.

Thank you for your response but I don't think that pot value bouncing is my problem here because sometimes i control the red color with one potentiometer but all of sudden it changes to the green color. That doesn't sound like a value bouncing problem to me. Correct me if I'm wrong.

kala444:
I checked your tutorial, it's great but I didn't find my solution.

I'm not surprised. I was not aware of your problem when I wrote it :slight_smile:

If you look at the first example the master sends an array of chars to the slave

char dataToSend[10] = "Message 0";

You can change that to

int dataToSend[3];

and put your values into the array.

Just make sure you have an identical array on the receiving side.

...R

Robin2:
I'm not surprised. I was not aware of your problem when I wrote it :slight_smile:

If you look at the first example the master sends an array of chars to the slave

char dataToSend[10] = "Message 0";

You can change that to

int dataToSend[3];

and put your values into the array.

Just make sure you have an identical array on the receiving side.

...R

Okay, but how do I put my values in the array?

I have tried this:

int data[3];

data[0] = red;             
data[1] = green;
data[2] = blue;

and it's giving me an error: 'data' does not name a type.

kala444:
I have tried this:

You need to post your complete program. When I put your code snippet in a program it compiled without an error.

...R

Okay, here is my code for transmitter:

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

int red;
int green;
int blue;

int data[3];

data[0] = red;             
data[1] = green;
data[2] = blue;


RF24 radio(9,10);
const uint64_t pipe = 0xE8E8F0F0E1LL;

void setup(){
  
  Serial.begin(9600);
  radio.begin();
  radio.openWritingPipe(pipe); 
  
  
}
void loop(){


  red[0] = analogRead(A1) / 4;
  green[0] = analogRead(A2) / 4;
  blue[0] = analogRead(A3) / 4;
  
  radio.write(red, sizeof(red)); 
  radio.write(green, sizeof(green));
  radio.write(blue, sizeof(blue));
  
    

}

Your use of arrays seems to be mixed up

This code puts the value 0 in each array element because that is the default value for the variables red, green etc

data[0] = red;             
data[1] = green;
data[2] = blue;

And you have no arrays called red[], green[] or blue[] so this code can't work

red[0] = analogRead(A1) / 4;
  green[0] = analogRead(A2) / 4;
  blue[0] = analogRead(A3) / 4;

It should be

data[0] = analogRead(A1) / 4;
  data[1] = analogRead(A2) / 4;
  data[2] = analogRead(A3) / 4;

If you liked you could create names like this

const byte red = 0;
const byte green = 1;
const byte blue = 2;

and then use them like this

data[red] = analogRead(A1) / 4;
  data[green] = analogRead(A2) / 4;
  data[blue] = analogRead(A3) / 4;

...R

in my case i would have enclosed the data in a single structure and then send it but for your case would like to correct some of your code

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

int data[2];

RF24 radio(9,10);
const uint64_t pipe = 0xE8E8F0F0E1LL;

void setup(){
red=1;
blue=2;
green=3;  
  Serial.begin(9600);
  radio.begin();
  radio.openWritingPipe(pipe); 
  
  
}
void loop(){


  data[red] = map(analogRead(A1) ,0,180,0,45);
  data[green] =map(analogRead(A2),0 ,180,0,45); 
  blue[blue] = map(analogRead(A3), 0, 180,0 ,45);
  
  radio.write(&data[], sizeof(data[])); 
    
}

and receiver code as

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

int data[2];
int red=0;
int blue=1;
int green=2;

int redVal;
int blueVal;
int greenVal;

int redOut = 3;
int blueOut = 5;
int greenOut = 6;

RF24 radio(9, 10);
const uint64_t pipe = 0xE8E8F0F0E1LL;

void setup() {

  Serial.begin(9600);
  pinMode (redOut, OUTPUT);
  pinMode (blueOut, OUTPUT);
  pinMode (greenOut, OUTPUT);

  radio.begin();
  radio.openReadingPipe(1, pipe);
  radio.startListening();

}
void loop() {

  if (radio.available()) {
    radio.read(&data[red], sizeof(data[red]));
    radio.read(&data[blue], sizeof(data[blue]));
    radio.read(&data[green], sizeof(data[green]));

    Serial.println(red[0]);
    Serial.println(blue[0]);
    Serial.println(green[0]);

    redVal = data[red];
    blueVal = data[blue];
    greenVal = data[green];

    analogWrite(redOut, redVal);
    analogWrite(blueOut, blueVal);
    analogWrite(greenOut, greenVal);

  }
}

try if it works

You could try it this way, I've not tried it out but complies and should work I used similar set up in another project.

TX code:

#include <SPI.h>
#include <nRF24L01.h>
#include <RF24.h>
#define CE_PIN   6
#define CSN_PIN 10
//#define CE_PIN   9
//#define CSN_PIN 10
RF24 radio(CE_PIN, CSN_PIN); // Create a Radio

const uint64_t pipeOut = 0xB3B4B5B6A3LL;//0xE8E8F0F0E1LL; //IMPORTANT: The same as in the receiver

struct MyData {
  int   RED;
  int   BLUE;
  int   GREEN;
};

MyData data;

void setup() {
  Serial.begin(9600);
  radio.begin();
  radio.setAutoAck(false);
  radio.setDataRate(RF24_250KBPS);
  radio.openWritingPipe(pipeOut);

}

void loop() {

  data.RED = analogRead(A1) / 4;
  data.BLUE = analogRead(A2) / 4;
  data.GREEN = analogRead(A3) / 4;

  radio.write(&data, sizeof(MyData));


}

RX code:

//####################################################
//# Include all the libraries                        #
//####################################################
#include  <Wire.h> //Wire libary 
#include <SPI.h>
#include <nRF24L01.h>
#include <RF24.h>
const uint64_t pipeIn =  0xB3B4B5B6A3LL;//0xE8E8F0F0E1LL64 bit encrypicted code
#define CE_PIN   9
#define CSN_PIN 10
RF24 radio(CE_PIN, CSN_PIN);

struct MyData {
  int RED_IN;
  int BLUE_IN;
  int GREEN_IN;

};
MyData data;

void setup()   /****** SETUP: RUNS ONCE ******/
{
  Serial.begin(9600);
  radio.begin();
  radio.setDataRate(RF24_250KBPS); // Both endpoints must have this set the same
  radio.setAutoAck(false);
  radio.openReadingPipe(1, pipeIn);
  radio.startListening();



}//--(end setup )---
void recvData()
{
  while ( radio.available() ) {
    radio.read(&data, sizeof(MyData));

  }
}

void loop()   /****** LOOP: RUNS CONSTANTLY ******/
{
  recvData();
  showData();

}




void showData() {
  Serial.print("RED IN VALUE:" );
  Serial.print(data.RED_IN);
  Serial.print(", ");
  Serial.print("BLUE IN VALUE:" );
  Serial.print(data.BLUE_IN);
  Serial.print(", ");
  Serial.print("GREEN IN VALUE:" );
  Serial.print(data.GREEN_IN);
  Serial.println("  ");


}

Robin2:
Your use of arrays seems to be mixed up

This code puts the value 0 in each array element because that is the default value for the variables red, green etc

data[0] = red;             

data[1] = green;
data[2] = blue;




And you have no arrays called red[], green[] or blue[] so this code can't work


red[0] = analogRead(A1) / 4;
 green[0] = analogRead(A2) / 4;
 blue[0] = analogRead(A3) / 4;




It should be


data[0] = analogRead(A1) / 4;
 data[1] = analogRead(A2) / 4;
 data[2] = analogRead(A3) / 4;




If you liked you could create names like this


const byte red = 0;
const byte green = 1;
const byte blue = 2;



and then use them like this


data[red] = analogRead(A1) / 4;
 data[green] = analogRead(A2) / 4;
 data[blue] = analogRead(A3) / 4;




...R

It's compiling now without a problem, but I have solved my problem by putting it all into a struct and sending it like that. Thank you for your responses :smiley:

Steveiboy:
You could try it this way, I've not tried it out but complies and should work I used similar set up in another project.

TX code:

#include <SPI.h>

#include <nRF24L01.h>
#include <RF24.h>
#define CE_PIN  6
#define CSN_PIN 10
//#define CE_PIN  9
//#define CSN_PIN 10
RF24 radio(CE_PIN, CSN_PIN); // Create a Radio

const uint64_t pipeOut = 0xB3B4B5B6A3LL;//0xE8E8F0F0E1LL; //IMPORTANT: The same as in the receiver

struct MyData {
  int  RED;
  int  BLUE;
  int  GREEN;
};

MyData data;

void setup() {
  Serial.begin(9600);
  radio.begin();
  radio.setAutoAck(false);
  radio.setDataRate(RF24_250KBPS);
  radio.openWritingPipe(pipeOut);

}

void loop() {

data.RED = analogRead(A1) / 4;
  data.BLUE = analogRead(A2) / 4;
  data.GREEN = analogRead(A3) / 4;

radio.write(&data, sizeof(MyData));

}




RX code:


//####################################################
//# Include all the libraries                        #
//####################################################
#include  <Wire.h> //Wire libary
#include <SPI.h>
#include <nRF24L01.h>
#include <RF24.h>
const uint64_t pipeIn =  0xB3B4B5B6A3LL;//0xE8E8F0F0E1LL64 bit encrypicted code
#define CE_PIN  9
#define CSN_PIN 10
RF24 radio(CE_PIN, CSN_PIN);

struct MyData {
  int RED_IN;
  int BLUE_IN;
  int GREEN_IN;

};
MyData data;

void setup()  /****** SETUP: RUNS ONCE ******/
{
  Serial.begin(9600);
  radio.begin();
  radio.setDataRate(RF24_250KBPS); // Both endpoints must have this set the same
  radio.setAutoAck(false);
  radio.openReadingPipe(1, pipeIn);
  radio.startListening();

}//--(end setup )---
void recvData()
{
  while ( radio.available() ) {
    radio.read(&data, sizeof(MyData));

}
}

void loop()  /****** LOOP: RUNS CONSTANTLY ******/
{
  recvData();
  showData();

}

void showData() {
  Serial.print("RED IN VALUE:" );
  Serial.print(data.RED_IN);
  Serial.print(", ");
  Serial.print("BLUE IN VALUE:" );
  Serial.print(data.BLUE_IN);
  Serial.print(", ");
  Serial.print("GREEN IN VALUE:" );
  Serial.print(data.GREEN_IN);
  Serial.println("  ");

}

Yep, this works like a charm!