Hello gents,
i have been successfully using the examples of NRF24L01 communication by the tutorial from Robin2 - Simple nRF24L01+ Tutorial
So Robin2: Many, many thanks also from my end to this very good tutorial!
In my use case 3 slaves send back a status value and an ID Nr. to the TX (Master).
The Master will actuate a servo depending from slave ID and "active" status. If more than one slave sends back "active" the master will focus on who came first.
Now comes the problem: I simply add a 4th slave to the communication and all replies turn "empty". That means that ackData[] is somehow not containing correct status and ID.
Also interessing is that the ID is transferred when i restart or reset master Node. After reset of the slaves also the ID gets lost.
Please also see the code for master, one slave and the serial monitor output.
Other slaves differ of course only from Adress and ID.
I have carefully tried to find any other issue here but unfortunately no problem compareable.
Would be great if someone can bring some light into here because I have no clue where even to start.
~Adrian
Master:
#include <SPI.h>
#include <nRF24L01.h>
#include <RF24.h>
#include <Servo.h>
#define CE_PIN 4
#define CSN_PIN 5
//each slave or receiver has its own address
const byte numSlaves = 4;
const byte slaveAddress[numSlaves][5] = {
{'R','B','G','0','1'},
{'R','B','G','0','2'},
{'R','B','G','0','3'},
{'R','B','G','0','4'}
};
Servo myServo;
RF24 radio(CE_PIN, CSN_PIN); // Create a Radio
char RequestData[10] = "RBG ID 0";
int16_t ackData[2] = {0, 0}; // to hold the two values coming from the slaves
bool newReply = false;
int pos = 10; // value for initial servoposition
int M_Counter;
int M_ID;
unsigned long currentMillis;
unsigned long prevMillis;
unsigned long txIntervalMillis = 500; // send once per 0,5 second
//===============
void setup() {
myServo.attach(16,600,2500); //Attach Servo to Pin D0, high-pulse range from 0,6ms - 2,5ms
myServo.write(pos);
Serial.begin(9600);
radio.begin();
radio.setDataRate( RF24_250KBPS );
radio.setPALevel(RF24_PA_LOW);
radio.enableAckPayload();
radio.setPayloadSize(sizeof(ackData));
radio.setRetries(5,5); // delay, count
// 5 gives a 1500 µsec delay which is needed for a 32 byte ackPayload
}
//=============
void loop() {
currentMillis = millis();
if (currentMillis - prevMillis >= txIntervalMillis) {
sendRequest();
if(M_Counter == 1){
ApplyData();
}
M_Counter = 0;
M_ID = 0;
}
}
//================
void sendRequest() {
for(byte n = 0; n < numSlaves; n++){
// open the writing pipe with the address of a slave
radio.stopListening();
radio.openWritingPipe(slaveAddress[n]);
// include the slave number in the message
RequestData[7] = n + '0';
bool rslt;
rslt = radio.write( &RequestData, sizeof(RequestData) );
// Always use sizeof() as it gives the size as the number of bytes.
// For example if RequestData was an int sizeof() would correctly return 3
Serial.println();
Serial.print("====================");
Serial.print("\n");
Serial.print("Request sent to ");
Serial.print(RequestData);
Serial.print("\n");
if(rslt){
if (radio.available() ) { //used instead of 'radio.isAckPayloadAvailble()' shall not make a difference
radio.read(&ackData, sizeof(ackData));
newReply = true;
}
else {
Serial.println(" Acknowledge but no data ");
}
}
else {
Serial.println(" Transmission failed");
}
if(validateStatus(ackData[0])){ // Display the ID and status of the Slave-RBG and return true if status is "1"
M_Counter += 1;
M_ID = ackData[1];
}
}
prevMillis = millis();
}
//=================
bool validateStatus(int status){
bool check = false;
if (newReply == true) {
Serial.print("RBG Status = ");
Serial.print(ackData[0]);
Serial.print("; RBG-Num: ");
Serial.println(ackData[1]);
if(status == 1){
check = true;
}
newReply = false;
}
return check;
}
void ApplyData() {
//will clean this by "switch case" later on.
if(M_ID == 1){
pos = 10;
}
if(M_ID == 2){
pos = 71;
}
if(M_ID == 3){
pos = 128;
}
if(M_ID == 4){
pos = 184; //168,75° corresonds to 270° - translation from CrownGear to BevelGear = 1.6 - correction factor: 24° = 15
}
Serial.print("Servoposition: ");
Serial.print(pos);
myServo.write(pos);
delay(500);
}
Slave(s):
// RBG - one slave or one receiver
#include <SPI.h>
#include <nRF24L01.h>
#include <RF24.h>
#define CE_PIN 4
#define CSN_PIN 5
const byte thisSlaveAddress[5] = {'R','B','G','0','1'}; // This address must be changed for every slave
RF24 radio(CE_PIN, CSN_PIN);
char ReqReceived[10]; // this must match RequestData in the TX (Transmitter)
int16_t ackData[2] = {0, 0}; // the two values to be sent to the master
bool newReq = false;
bool invIR;
int Tbutton = 16; // Taster set to Pin D0
//==============
void setup() {
pinMode(Tbutton, INPUT); // Test button defined as input
Serial.begin(9600);
radio.begin();
radio.setDataRate( RF24_250KBPS );
radio.setPALevel(RF24_PA_LOW);
radio.openReadingPipe(1, thisSlaveAddress);
radio.enableAckPayload();
//radio.setPayloadSize(sizeof(ackData));
radio.startListening();
radio.writeAckPayload(1, &ackData, sizeof(ackData)); // pre-load data
}
//==========
void loop() {
getData();
showData(); //only to display data transfer status for development
}
//============
void getData() {
if ( radio.available() ) {
radio.read( &ReqReceived, sizeof(ReqReceived) );
updateReplyData();
newReq = true;
}
}
//================
void showData() {
if (newReq == true) {
Serial.print("Request received ");
Serial.println(ReqReceived);
Serial.print(" RBG Status sent: ");
Serial.print(ackData[0]);
Serial.print("; RBG Num: ");
Serial.println(ackData[1]);
newReq = false;
}
}
//================
void updateReplyData() {
invIR = !digitalRead(Tbutton); // Invert signal from optical sensor as it returns LOW as actuation
ackData[0] = invIR;
ackData[1] = 1; // Fix ID of RBG-01 - must be changed for every RBG
radio.writeAckPayload(1, &ackData, sizeof(ackData)); // load the payload for the next time
Serial Monitor before switch off slaves:
Serial Monitor after switch off-on slaves:





