nRF24L01 radio modules for three channels RF link ( Solved #16)

I have a MAIN control box with a 4L x 20C LCD and is the main machine controller.

I have a REMOTE unit that has a cloned 4L x 20C LCD at a distance of 20m from MAIN. This REMOTE is like a relay station - it has to beam back RFID data and a Pressure sensor data to the MAIN when requested.

Even though the RFID and Pressure sensor units can directly link to MAIN as they are not very far ( less than 25M from MAIN) the operator needs to look at the MAIN display, so the REMOTE unit is anyway needed with a cloned MAIN display.

Look at the attached sketch.

Now my question is which should be MASTER transmitter ? I feel that the REMOTE unit can be the master transmitter with three RF channels and all with Auto Ack Payload enabled so that there is no XMIT / RECV mode switchovers. Or any other efficient means of doing this ??

I am using this library for RF24 : http://tmrh20.github.io/RF24/index.html

I would use as master the unit that gathers data from the others as then it can control all the communication. It probably also means that the nRF24 code on the slaves can be identical and relatively simple.

The second example in this Simple nRF24L01+ Tutorial can be extended to communicate with multiple slaves.

...R

Thanks so much Robin.

Looks like you have improved the Tutorial - what I liked the most was small snippets that are not in the main documentation. Like the Ack Payload cannot be more than 32 bytes..

I guess you are referring me to check the post #2 in the thread " Two way transmission using Ack Payload concept"

Will do that and revert in case of any issues. And as you mentioned I can make the MAIN UNIT as my master. But the issue will be the REMOTE UNIT which acts a relay center between the two sensor slaves and besides it also has a Keypad and the status of these 4 keys need to be sent back to MAIN along with sensor data. So the REMOTE will need to act as MASTER to the two sensor slaves but as a SLAVE to the MAIN UNIT. I am a bit stuck here.

( Due to practical limitations, I cannot directly query the two sensor slaves from the MAIN UNIT - though the distance is not large they will be obscured by metal machine structures to the MAIN UNIT. Whereas the REMOTE UNIT has full visibility of them and also the MAIN UNIT )

So what do you think is the best setup ?

Mogaraghu:
Will do that and revert in case of any issues. And as you mentioned I can make the MAIN UNIT as my master. But the issue will be the REMOTE UNIT which acts a relay center between the two sensor slaves and besides it also has a Keypad and the status of these 4 keys need to be sent back to MAIN along with sensor data. So the REMOTE will need to act as MASTER to the two sensor slaves but as a SLAVE to the MAIN UNIT. I am a bit stuck here.

( Due to practical limitations, I cannot directly query the two sensor slaves from the MAIN UNIT - though the distance is not large they will be obscured by metal machine structures to the MAIN UNIT. Whereas the REMOTE UNIT has full visibility of them and also the MAIN UNIT )

I don't have a clear picture of the system. Is it like this

                                   /------------------------C
              A-------------------B
                                   \------------------------D

If that is the case I would treat A, C and D as slaves of B

The concept of master and slave is only relevant as far as the radio code is concerned. The Arduinos can act in any role that your system requires.

...R

Yes the sketch what you made is right.

The only complication is due to B. This needs to relay the query from A to the slaves C and D and then pass back the response to A along with some user push button status. So in this transaction B is slave to A but a master to C and D.

Let me see ... if C and D can directly communicate with A, then simply all three ( B,C,D) can be slaves to A. Maybe that's what I will try first. And since I am using the nRF24L01 modules in all cases with the regulated 3.3V supply module, I am sure I can consistently achieve atleast 50m?

Mogaraghu:
The only complication is due to B. This needs to relay the query from A to the slaves C and D and then pass back the response to A along with some user push button status.

I can't see any problem with that. B sends a message to A and when it gets the response it sends messages to C and D.

So in this transaction B is slave to A but a master to C and D.

I think you are being confused into thinking that the wireless roles (master and slave) must be the same as the logical roles of the different devices. They can be completely different.

Think of B as a youthful telegram-boy (back to the 1930's) taking messages between the others. He may do the hard work but he contributes nothing to the "expertise".

...R

Its clear now...I have copied your sample code and modified it to use for three slaves. I have created two more new slave addresses and also modified the send() function to handle the three different transmissions to three slaves.

void setup() {

  Serial.begin(9600);
  Serial.println(F("Source File /mnt/sdb1/SGT-Prog/Arduino/ForumDemos/nRF24Tutorial/SimpleTxAckPayload.ino"));
  Serial.println("SimpleTxAckPayload Starting");

  radio.begin();
  radio.setDataRate( RF24_250KBPS );

  radio.enableAckPayload();

  radio.setRetries(3, 5); // delay, count
  radio.openWritingPipe(slaveAddress0);
  radio.openWriringPipe(slaveAddress1);
  radio.openWritingPipe(slaveAddress2);

}

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

void loop() {

  currentMillis = millis();
  if (currentMillis - prevMillis >= txIntervalMillis) {
    send0();
    send1();
    send2();
  }
 }

I guess the above approach is right ?? Or should i bring in some delay between each send ?

I tried the second example in Simple nRF24L01 Tutorial.

After correcting a small bug in the updateReplyData() it worked OK. Except that occasionally I get a Tx Failed message. ( Both Tx and Rx modules are nearby each other )

What could cause this ? Refer attachment of the Serial monitor. There are two failure instances. ( I am using the nRF24L01 with the 5V to 3.3V regulator module)

I would not rely on every message being successful. However I have not generally had problems. My usual testing has both nRF24s on the same table.

This makes no sense

  radio.openWritingPipe(slaveAddress0);
  radio.openWriringPipe(slaveAddress1);
  radio.openWritingPipe(slaveAddress2);

On the last line will have any effect as it will overwrite the others. You need to set the address immediately before sending a message to a slave.

If you still have problems post the complete master and slave programs.

...R

On the last line will have any effect as it will overwrite the others. You need to set the address immediately before sending a message to a slave.

Thats a learning. Thanks. I have created a 2 Channel example transmitter and also a matching receiver for the first channel as an example and have posted both here. Kindly let me know if they are OK as coded or need to be improved ?

The Transmitter code :

/*
  2 Channel Radio Transmitter sketch using nRF24L01 modules...
*/


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

/****************** User Config ***************************/
/* Hardware configuration: Set up nRF24L01 radio on SPI bus plus pins 7,8 */
RF24 radio(7, 8); // For RRDUINO pcb. But use the UNO pin numbers
/**********************************************************/

byte slaveAddress1[6] = "RxAAA";                               // Radio pipe addresses for Slave no 1.
byte slaveAddress2[6] = "RxBBB";                               // Radio pipe addresses for Slave no 2.


unsigned long dataToSend_Ch1, dataToSend_Ch2 ;
unsigned long ackData_Ch1, ackData_Ch2 ;

void setup() {

  Serial.begin(115200);
  Serial.println(F("*** STARTING TRANSMITTER *** "));

  // Setup and configure radio
  radio.begin();
  radio.setDataRate( RF24_250KBPS );
  radio.enableAckPayload();                                    // Allow optional ack payloads
  radio.setRetries(3, 5);                                      // Delay, count 
}

//$$$$$$$$$$$$$$$$$$$$$$$$$$$$
void loop(void)
{
  send_Ch1();
  send_Ch2();

  delay(1000);                                               // Transmitt data once every second..
}

//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

void send_Ch1() {

  bool rslt;
  radio.openWritingPipe(slaveAddress1); 
                         
  rslt = radio.write( &dataToSend_Ch1, sizeof(dataToSend_Ch1) );
  Serial.print("Ch1_Data Sent ");
  Serial.print(dataToSend_Ch1);
  if (rslt) {
    if ( radio.isAckPayloadAvailable() ) {
      radio.read(&ackData_Ch1, sizeof(ackData_Ch1));
      Serial.print("Ch1_Acknowledge..");
      Serial.println( ackData_Ch1 );
    }
    else {
      Serial.println("Ch1_Acknowledge but no data ");
    }
    dataToSend_Ch1 ++;                                     // Update data for demo...
  }
  else {
    Serial.println("  Ch1_Tx failed");
  }
}

//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

void send_Ch2() {

  bool rslt;
  radio.openWritingPipe(slaveAddress2); 
                         
  rslt = radio.write( &dataToSend_Ch2, sizeof(dataToSend_Ch2) );
  Serial.print("Ch1_Data Sent ");
  Serial.print(dataToSend_Ch2);
  if (rslt) {
    if ( radio.isAckPayloadAvailable() ) {
      radio.read(&ackData_Ch2, sizeof(ackData_Ch2));
      Serial.print("Ch1_Acknowledge..");
      Serial.println( ackData_Ch2 );
    }
    else {
      Serial.println("Ch2_Acknowledge but no data ");
    }
    dataToSend_Ch2 ++;
  }
  else {
    Serial.println("  Ch2_Tx failed");
  }
}

The Receiver code :

/*
  Single channel receiver  to be used with nRF24_3Ch_Transmitter.ino
*/


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

/****************** User Config ***************************/
/* Hardware configuration: Set up nRF24L01 radio on SPI bus plus pins 7,8 */
RF24 radio(7, 8);
/**********************************************************/

byte myAddress[6] = "RxAAA";                     // Radio pipe addresses of this receiver- must match with one in Tx code Slave1.

unsigned long timeOut;
unsigned long recvData ;
unsigned long ackData_Ch1 = 0 ;

void setup()
{
  Serial.begin(115200);
  Serial.println(F("*** STARTING RECIEVER *** "));

  // Setup and configure radio
  radio.begin();
  radio.setDataRate( RF24_250KBPS );
  radio.openReadingPipe(1, myAddress);
  radio.enableAckPayload();
  radio.writeAckPayload(1, &ackData_Ch1, sizeof(ackData_Ch1)); // pre-load data for first acknowledgement

  radio.startListening();
}

//****************************************************
void loop(void)
{
  if ( radio.available())                            // Read  available payload
  {
    radio.read( &recvData, sizeof(recvData));        //Get the data to process at this point...
    Serial.println ( recvData);
    // Since this is a call-response. Respond directly with an ack payload with dynamic data.

    ackData_Ch1 = recvData ;                          // Update ackData for tracking
    radio.writeAckPayload(1, &ackData_Ch1, sizeof(ackData_Ch1)); // This is the information from Rx to Tx module...
    timeOut = millis();
  }
  else
  {
    if ( millis() - timeOut > 2000 )
    {
      Serial.println ( "Time out fault!! ");
    }
  }
}

That looks like it should work. But there would be a lot less typing (and scope for errors) if you did something like

for (byte n =0; n < numSlaves; n++ ) {
   bool rslt;
   radio.openWritingPipe(slaveAddress[n]);
                         
   rslt = radio.write( &dataToSend_Ch, sizeof(dataToSend_Ch) );
   // etc

or (alternatively)

for (byte n =0; n < numSlaves; n++ ) {
  send_Ch(slaveAddress[n];
}

...R

Thanks for the optimization tips for the code.

Right now all is fine expect for a small issue ... I am doing a transmission once every 100ms. The Transmission fails at random for a cycle in between. Not sure why. I am right now operating with MAX_PWR setting and Retries (5,10).

See the attached screen shot of the Tx module. Is it because i am sending just 4 bytes per transmission or doing wrong anywhere else. The code is the same as you said was OK with the above changes on Power level and Retries.

Both TX and RX modules are running off regulated power supplies.

What do you think i can do to improve the transmission reliability ??

Did some more trials - but this time with a Tx payload of a structure as below :

struct dataStruct {
unsigned int rawAnalogData[2];
bool digitalInput[1];
bool digitalOutput[1];
byte rawAnalogCommand[1];
} txDataStream;

Also captured the round trip time. This time around the number of Tx was very few - hardly any to be frank. Ok this could be not a correct indicator of anything but coincidence.. But the round trip time was all over the place - see the attachment - earlier the same code had produced reasonably good timing of 700 to 800 microseconds.

I am at a complete loss as to whats going on. Does this make meaning to you ?

Please post text output as text not as pictures that have to be downloaded.

Also, i suspect your latest output comes from programs you have not posted.

I have discovered that if you are using dynamic payloads (which are automatic with the ackPayload system) then you MUST read all the data that has been received. There is a function getDynamicPayloadSize() that can be used to check.

...R

I tried the code which I said was behaving very erratic but with radio.enableDynamicPayloads(); on both the Tx and Rx module as below. The transmission is far more stable now with a rare Tx Failed case. You think this correction helped ??

Tx module :

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

/****************** User Config ***************************/
/* Hardware configuration: Set up nRF24L01 radio on SPI bus plus pins 7,8 */
RF24 radio(7, 8); // For RRDUINO pcb. But use the UNO pin numbers
/**********************************************************/

byte slaveAddress1[6] = "RxAAA";                               // Radio pipe addresses for Slave no 1.
byte slaveAddress2[6] = "RxBBB";                               // Radio pipe addresses for Slave no 2.


unsigned long dataToSend_Ch1, dataToSend_Ch2 ;
unsigned long ackData_Ch1, ackData_Ch2 ;

byte Ch1_OKLed = 5;
byte Ch2_OKLed = 6; 

void setup() {

  Serial.begin(9600);
  Serial.println(F("*** STARTING TRANSMITTER *** "));

  // Setup and configure radio
  radio.begin();
  radio.setDataRate( RF24_250KBPS );
  radio.enableAckPayload();                                    // Allow optional ack payloads
  radio.enableDynamicPayloads();                               // Ack payloads are dynamic payloads
  radio.setRetries(5, 10);                                     // Delay, count 

  pinMode( Ch1_OKLed, OUTPUT ); 
  pinMode( Ch2_OKLed, OUTPUT ); 
  digitalWrite(Ch1_OKLed, LOW);
  digitalWrite(Ch2_OKLed, LOW);
}

//$$$$$$$$$$$$$$$$$$$$$$$$$$$$
void loop(void)
{
  send_Ch1();
  //send_Ch2();

  delay(1000);                                               // Transmitt data once every second..
}

//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

void send_Ch1() {

  bool rslt;
  radio.openWritingPipe(slaveAddress1); 
                         
  rslt = radio.write( &dataToSend_Ch1, sizeof(dataToSend_Ch1) );
  Serial.print("Ch1_Data Sent ");
  Serial.print(dataToSend_Ch1);
  if (rslt) {
    if ( radio.isAckPayloadAvailable() ) {
      radio.read(&ackData_Ch1, sizeof(ackData_Ch1));
      Serial.print("Ch1_Acknowledge..");
      Serial.println( ackData_Ch1 );
    }
    else {
      Serial.println("Ch1_Acknowledge but no data ");
    }
    dataToSend_Ch1 ++;                                     // Update data for demo...
    digitalWrite(Ch1_OKLed, HIGH);
  }
  else {
    Serial.println("  Ch1_Tx failed");
    digitalWrite(Ch1_OKLed, LOW);
  }
}

Rx Module :

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

/****************** User Config ***************************/
/* Hardware configuration: Set up nRF24L01 radio on SPI bus plus pins 7,8 */
RF24 radio(7,8);
/**********************************************************/

byte myAddress[6] = "RxAAA";                     // Radio pipe addresses of this receiver- must match with one in Tx code Slave1.

unsigned long timeOut;
unsigned long recvData ;
unsigned long ackData_Ch1 = 0 ;

void setup()
{
  Serial.begin(9600);
  Serial.println(F("*** STARTING RECIEVER *** "));

  // Setup and configure radio
  radio.begin();
  radio.setDataRate( RF24_250KBPS );
  radio.enableDynamicPayloads();                // Ack payloads are dynamic payloads
  radio.openReadingPipe(1, myAddress);                        
  radio.enableAckPayload();
  radio.writeAckPayload(1, &ackData_Ch1, sizeof(ackData_Ch1)); // pre-load data for first acknowledgement

  radio.startListening();
}

//****************************************************
void loop(void)
{
  if ( radio.available())                            // Read  available payload
  {
    radio.read( &recvData, sizeof(recvData));        //Get the data to process at this point...
    Serial.println ( recvData);
    // Since this is a call-response. Respond directly with an ack payload with dynamic data.

    ackData_Ch1 = recvData ;                          // Update ackData for tracking
    radio.writeAckPayload(1, &ackData_Ch1, sizeof(ackData_Ch1)); // This is the information from Rx to Tx module...
    timeOut = millis();
  }
  else
  {
    if ( millis() - timeOut > 2000 )
    {
      Serial.println ( "Time out fault!! ");
    }
  }

As you can see its far more stable now - of course I do get an odd Tx Failed message but for my application maybe I can manage as i update the link once every 100ms and none of my process are that fast.

*** STARTING TRANSMITTER ***
Ch1_Data Sent 0Ch1_Acknowledge..43
Ch1_Data Sent 1Ch1_Acknowledge..0
Ch1_Data Sent 2Ch1_Acknowledge..1
Ch1_Data Sent 3Ch1_Acknowledge..2
Ch1_Data Sent 4Ch1_Acknowledge..3
Ch1_Data Sent 5Ch1_Acknowledge..4
Ch1_Data Sent 6Ch1_Acknowledge..5
Ch1_Data Sent 7Ch1_Acknowledge..6
Ch1_Data Sent 8Ch1_Acknowledge..7
Ch1_Data Sent 9Ch1_Acknowledge..8
Ch1_Data Sent 10Ch1_Acknowledge..9
Ch1_Data Sent 11Ch1_Acknowledge..10
Ch1_Data Sent 12Ch1_Acknowledge..11
Ch1_Data Sent 13Ch1_Acknowledge..12
Ch1_Data Sent 14Ch1_Acknowledge..13
Ch1_Data Sent 15Ch1_Acknowledge..14
Ch1_Data Sent 16Ch1_Acknowledge..15
Ch1_Data Sent 17Ch1_Acknowledge..16
Ch1_Data Sent 18Ch1_Acknowledge..17
Ch1_Data Sent 19Ch1_Acknowledge..18
Ch1_Data Sent 20Ch1_Acknowledge..19
Ch1_Data Sent 21Ch1_Acknowledge..20
Ch1_Data Sent 22Ch1_Acknowledge..21
Ch1_Data Sent 23Ch1_Acknowledge..22
Ch1_Data Sent 24Ch1_Acknowledge..23
Ch1_Data Sent 25Ch1_Acknowledge..24
Ch1_Data Sent 26Ch1_Acknowledge..25
Ch1_Data Sent 27Ch1_Acknowledge..26
Ch1_Data Sent 28Ch1_Acknowledge..27
Ch1_Data Sent 29Ch1_Acknowledge..28
Ch1_Data Sent 30Ch1_Acknowledge..29
Ch1_Data Sent 31Ch1_Acknowledge..30
Ch1_Data Sent 32Ch1_Acknowledge..31
Ch1_Data Sent 33Ch1_Acknowledge..32
Ch1_Data Sent 34Ch1_Acknowledge..33

I have tried your programs on my Unos and they seem perfectly reliable to me - with or without the line radio.enableDynamicPayloads();

I note that you are not using Pin10 for CSN and in that case I suggest you put pinMode(10, OUTPUT); into setup() before radio.begin(). It ensures that the Uno operates as the SPI master.

Maybe you have some external interfernce (from WiFi or Bluetooth for example). Have you tried using a different channel with your nRF24s?

...R

Robin ....it finally got resolved. The channel seemed to be the issue - i fixed it to 108 and it became perfect. Tried with 100ms link rate and it was absolutely fine with not a single failure.

A big thanks to you for persistent and relevant support !

So here is the final code for 2-Ch Transmit and one sample Receive module :

Transmit module :

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

/****************** User Config ***************************/
/* Hardware configuration: Set up nRF24L01 radio on SPI bus plus pins 7,8 */
RF24 radio(7, 8); // For RRDUINO pcb. But use the UNO pin numbers
/**********************************************************/

byte slaveAddress1[6] = "RxAAA";                               // Radio pipe addresses for Slave no 1.
byte slaveAddress2[6] = "RxBBB";                               // Radio pipe addresses for Slave no 2.


unsigned long dataToSend_Ch1, dataToSend_Ch2 ;
unsigned long ackData_Ch1, ackData_Ch2 ;

byte Ch1_OKLed = 5;
byte Ch2_OKLed = 6;
byte pinSS     = 10; 

void setup() {

  Serial.begin(9600);
  Serial.println(F("*** STARTING TRANSMITTER *** "));

  // Setup and configure radio
  radio.begin();
  radio.setChannel(108);                                      // Above most Wifi Channels
  radio.setDataRate( RF24_250KBPS );
  radio.enableAckPayload();                                    // Allow optional ack payloads
  radio.enableDynamicPayloads();                               // Ack payloads are dynamic payloads
  radio.setRetries(5, 10);                                     // Delay, count 
  radio.printDetails();
  pinMode( Ch1_OKLed, OUTPUT ); 
  pinMode( Ch2_OKLed, OUTPUT ); 
  pinMode( pinSS, OUTPUT );
  digitalWrite(Ch1_OKLed, LOW);
  digitalWrite(Ch2_OKLed, LOW);
}

//$$$$$$$$$$$$$$$$$$$$$$$$$$$$
void loop(void)
{
  send_Ch1();
  send_Ch2();

  delay(100);                                               // Transmitt data once every second..
}

//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

void send_Ch1() {

  bool rslt;
  radio.openWritingPipe(slaveAddress1); 
                         
  rslt = radio.write( &dataToSend_Ch1, sizeof(dataToSend_Ch1) );
  Serial.print("Ch1_Data Sent ");
  Serial.print(dataToSend_Ch1);
  if (rslt) {
    if ( radio.isAckPayloadAvailable() ) {
      radio.read(&ackData_Ch1, sizeof(ackData_Ch1));
      Serial.print("Ch1_Acknowledge..");
      Serial.println( ackData_Ch1 );
    }
    else {
      Serial.println("Ch1_Acknowledge but no data ");
    }
    dataToSend_Ch1 ++;                                     // Update data for demo...
    digitalWrite(Ch1_OKLed, HIGH);
  }
  else {
    Serial.println("  Ch1_Tx failed");
    digitalWrite(Ch1_OKLed, LOW);
  }
}

//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

void send_Ch2() {

  bool rslt;
  radio.openWritingPipe(slaveAddress2); 
                         
  rslt = radio.write( &dataToSend_Ch2, sizeof(dataToSend_Ch2) );
  Serial.print("Ch1_Data Sent ");
  Serial.print(dataToSend_Ch2);
  if (rslt) {
    if ( radio.isAckPayloadAvailable() ) {
      radio.read(&ackData_Ch2, sizeof(ackData_Ch2));
      Serial.print("Ch1_Acknowledge..");
      Serial.println( ackData_Ch2 );
    }
    else {
      Serial.println("Ch2_Acknowledge but no data ");
    }
    dataToSend_Ch2 ++;
    digitalWrite(Ch2_OKLed, HIGH);
  }
  else {
    Serial.println("  Ch2_Tx failed");
    digitalWrite(Ch2_OKLed, LOW);
  }
}

Receive Module :

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

/****************** User Config ***************************/
/* Hardware configuration: Set up nRF24L01 radio on SPI bus plus pins 7,8 */
RF24 radio(7,8);
/**********************************************************/

byte myAddress[6] = "RxAAA";                     // Radio pipe addresses of this receiver- must match with one in Tx code Slave1.

unsigned long timeOut;
unsigned long recvData ;
unsigned long ackData_Ch1 = 0 ;
byte pinSS = 10; 

void setup()
{
  Serial.begin(9600);
  Serial.println(F("*** STARTING RECIEVER *** "));
  pinMode( pinSS, OUTPUT); 
  // Setup and configure radio
  radio.begin();
  radio.setChannel(108);                      // Above most Wifi Channels
  radio.setDataRate( RF24_250KBPS );
  radio.enableDynamicPayloads();                // Ack payloads are dynamic payloads
  radio.openReadingPipe(1, myAddress);                        
  radio.enableAckPayload();
  radio.writeAckPayload(1, &ackData_Ch1, sizeof(ackData_Ch1)); // pre-load data for first acknowledgement
  
  radio.startListening();
}

//****************************************************
void loop(void)
{
  if ( radio.available())                            // Read  available payload
  {
    radio.read( &recvData, sizeof(recvData));        //Get the data to process at this point...
    Serial.println ( recvData);
    // Since this is a call-response. Respond directly with an ack payload with dynamic data.

    ackData_Ch1 = recvData ;                          // Update ackData for tracking
    radio.writeAckPayload(1, &ackData_Ch1, sizeof(ackData_Ch1)); // This is the information from Rx to Tx module...
    timeOut = millis();
  }
  else
  {
    if ( millis() - timeOut > 2000 )
    {
      Serial.println ( "Time out fault!! ");
    }
  }
}

Gald you have it solved and thanks for the feedback.

...R