Help Needed - nrf24l01 SimpleRxAckPayload example byRobin2

I am trying to communicate using 1 master and six slaves. The master is ESP8266 with nrf24l01 and the slaves are pro micro with nrf24l01 radios.

I have followed Robin2’s excellent examples found here
; https://forum.arduino.cc/index.php?topic=421081.15

My master recieves mqtt messages and transmits them to the corresponding slave based on the content of the message e.g Tx/1sp/255 will transmit this string to slave 1. The idea is for the slave to decode the message and carry out the corresponding action. This is for model train control.

My master seems to be working fine and I get acknowledge messages back from all 6 slaves.

The problem is that I cannot read any data on the slave side. I am using the SimpleRxAckPayload example from Robin2 without modification. I suspect that the problem may have something to do with the fact that I am transmitting a String (Char Array) but have no idea how to fix or even debug this.

Master

//wifi and MQTT library
#include <ESP8266WiFi.h>
#include <PubSubClient.h>

// MultiTxAckPayload - the master or the transmitter
//   works with 6 Arduinos as slaves
//     each slave should the SimpleRxAckPayload program
//       from adress {'R','x','A','A','A'}
//         to adress {'R','x','A','A','F'}
#include <SPI.h>
#include <nRF24L01.h>
#include <RF24.h>

//wifi network settings.
const char* ssid = "xxxxx";
const char* password = "xxxxx";
const char* mqtt_server = "xxxxx";
char dataToSend[10] = "";
String msg;

WiFiClient espClient;
PubSubClient client(espClient);
char returnmsg[50];
int direct = 0;

//Radio control pins
#define CE_PIN   4  //9
#define CSN_PIN 15  //10

const byte numSlaves = 6;
const byte slaveAddress[numSlaves][5] = {
        // each slave needs a different address
                            {'R','x','A','A','A'},
                            {'R','x','A','A','B'},
                            {'R','x','A','A','C'},
                            {'R','x','A','A','D'},
                            {'R','x','A','A','E'},
                            {'R','x','A','A','F'}
                        };

RF24 radio(CE_PIN, CSN_PIN); // Create a Radio

//callback handles mqtt subscribe messages
void callback(char* topic, byte* payload, unsigned int length) {

msg = topic;
//convert payload to int for pwm
payload[length] = '\0';
String s = String((char*)payload);
msg = msg + "/" + s;

int str_len = msg.length()+ 1;
msg.toCharArray(dataToSend, str_len);
send();
//client.publish("Tx/connect", dataToSend);

}

//~ char dataToSend[10] = "Message 0";
//char dataToSend[10] = "ToSlvN  0";
char txNum = '0';
int ackData[2] = {-1, -1}; // to hold the two values coming from the slave
bool newData = false;

unsigned long currentMillis;
unsigned long prevMillis;
unsigned long txIntervalMillis = 1000; // send once per second

//===============

void setup() {
    Serial.begin(9600);
    Serial.println("SimpleTxAckPayload Starting");

       setup_wifi();
  client.setServer(mqtt_server, 1883);
  client.setCallback(callback);

    radio.begin();
    radio.setDataRate( RF24_250KBPS );
radio.setPALevel(RF24_PA_HIGH);
    radio.enableAckPayload();

    radio.setRetries(3,5); // delay, count
        // radio.openWritingPipe(slaveAddress); -- moved to loop()
}

//=============

void loop() {

          //fix this so it doesn't block radio when connection is lost
if (!client.connected()) {
    reconnect();
  }
  client.loop();
}
//================

void send() {

  bool rslt;
char i = msg.charAt(3);
switch(i)
{

  case '1':
             // open the writing pipe with the address of a slave
        radio.openWritingPipe(slaveAddress[1]);
        rslt = radio.write( &dataToSend, sizeof(dataToSend) );
        break;
    case '2':
            // open the writing pipe with the address of a slave
        radio.openWritingPipe(slaveAddress[2]);
        rslt = radio.write( &dataToSend, sizeof(dataToSend) );
        break;
      case '3':
            // open the writing pipe with the address of a slave
        radio.openWritingPipe(slaveAddress[3]);
        rslt = radio.write( &dataToSend, sizeof(dataToSend) );
        break;
      case '4':
            // open the writing pipe with the address of a slave
        radio.openWritingPipe(slaveAddress[4]);
        rslt = radio.write( &dataToSend, sizeof(dataToSend) );
        break;
      case '5':
            // open the writing pipe with the address of a slave
        radio.openWritingPipe(slaveAddress[5]);
        rslt = radio.write( &dataToSend, sizeof(dataToSend) );
        break;
      case '6':
              // open the writing pipe with the address of a slave
        radio.openWritingPipe(slaveAddress[6]);
        rslt = radio.write( &dataToSend, sizeof(dataToSend) );
        break;
}

            // Always use sizeof() as it gives the size as the number of bytes.
            // For example if dataToSend was an int sizeof() would correctly return 2

        Serial.print("  ========  For Slave ");
        Serial.print(i);
        Serial.println("  ========");
        Serial.print("  Data Sent ");
        Serial.print(dataToSend);
        if (rslt) {
            if ( radio.isAckPayloadAvailable() ) {
                radio.read(&ackData, sizeof(ackData));
                newData = true;
            }
            else {
                Serial.println("  Acknowledge but no data ");
            }
        }
        else {
            Serial.println("  Tx failed");
        }
        showData();
        Serial.print("\n");
 }


//=================

void showData() {
    if (newData == true) {
        Serial.print("  Acknowledge data ");
        Serial.print(ackData[0]);
        Serial.print(", ");
        Serial.println(ackData[1]);
        Serial.println();
        newData = false;
    }
}

//================

void setup_wifi() {
  delay(10);
//  connecting to WiFi network
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
  }
}

//reconnect wifi if connection lost
void reconnect() {
  // Loop until we're reconnected
  while (!client.connected()) {
    if (client.connect("GatewayClient")) {
      // Once connected, publish an announcement...
      client.publish("Gateway/connect", "Wifi Connected");
      // ... and resubscribe to topics
      client.subscribe("Tx/#");
    } else {
//            Wait 1 seconds before retrying
      delay(1000);
    }
  }
}

Slave

// SimpleRxAckPayload- the slave or the receiver

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

#define CE_PIN   9
#define CSN_PIN 10

const byte thisSlaveAddress[5] = {'R','x','A','A','A'};

RF24 radio(CE_PIN, CSN_PIN);

char dataReceived[10]; // this must match dataToSend in the TX
int ackData[2] = {109, -4000}; // the two values to be sent to the master
bool newData = false;

//==============

void setup() {

    Serial.begin(9600);

    Serial.println("SimpleRxAckPayload Starting");
    radio.begin();
    radio.setDataRate( RF24_250KBPS );
    radio.openReadingPipe(1, thisSlaveAddress);

    radio.enableAckPayload();
    
    radio.startListening();

    radio.writeAckPayload(1, &ackData, sizeof(ackData)); // pre-load data
}

//==========

void loop() {
    getData();
    showData();
}

//============

void getData() {
    if ( radio.available() ) {
        radio.read( &dataReceived, sizeof(dataReceived) );
        updateReplyData();
        newData = true;
    }
}

//================

void showData() {
    if (newData == true) {
        Serial.print("Data received ");
        Serial.println(dataReceived);

        Serial.print(" ackPayload sent ");
        Serial.print(ackData[0]);
        Serial.print(", ");
        Serial.println(ackData[1]);
        newData = false;
    }
}

//================

void updateReplyData() {
    ackData[0] -= 1;
    ackData[1] -= 1;
    if (ackData[0] < 100) {
        ackData[0] = 109;
    }
    if (ackData[1] < -4009) {
        ackData[1] = -4000;
    }
    radio.writeAckPayload(1, &ackData, sizeof(ackData)); // load the payload for the next time
}

Have you given each slave a different address?

If this was my problem I would start with a simple TX program without any WiFi and make sure it could send a message to each slave in turn.

Wireless problems can be very difficult to debug so get the wireless part working on its own before you start adding any other features.

...R

Thanks for the quick reply.

I managed to solve the problem.

dataToSend[10] needs to be DataToSend[11] on both Tx and Rx to cater for the string terminator.

The Slave address needs to be specified as a byte, my program was returning an ascii char.

I solved this by doing

byte i = msg.charAt(3)-'1';