Best way to poll multiple sensors over wireless

I’m new to Arduino, I want to use a Raspberry pi to collect DHT11/DHT22 sensors thru out and around the house with Arduinos communicating thru nrf24l01 modules.

I was thinking of having the RPi poll the individual Arduinos and have them immediately read into an array and send it back to the RPI for logging. This would allow timestamping(by the RPi) and I wouldn’t have to worry about packet collisions from Arduinos sending unsolicited data at the same time. I do not need to send constant readings, more likely than not I will adjust the rate via the RPi to read each sensor every 1-5 minutes.

My question is are there any major pitfalls to this way of implementing the process or am I missing something that would greatly simplify this project? I would like to run the Arduinos on battery so in a second phase I would like to put them in a low power state until the radio receives data and wakes the Arduino if possible.

Is the most efficient way to return data to the RPi by putting all sensor data into an array so it goes in a single packet?

-John

I’m not familiar with the nRF24 modules, but generally speaking you listen to nodes rather than poll. Then you only accept data from whitelisted devices. You can poll, but that means ALL of your sensors are listening.

Pushing data from your sensors could make the overall workflow simpler.

Have each sensor transmit at intervals ranging from 1 to 5 minutes. If the message is short and contains a sensor ID, then the chance of collisions is very small and it is trivial to keep track of the data source.

That is how most home weather stations work.

For low power operation, study this excellent tutorial.https://www.gammon.com.au/power The $2 eBay Pro Mini clones are great for this, as you can very easily remove the voltage regulator and power LED, and have the equivalent of a "bare bones" Arduino.

WeMos D1 mini is another option. 2.4GHz radio, 4MB flash for data, NTP for timestamps, all in one. Leo..

Thanks for the replies so far:

Czu001 - The RF24 lib for nrf24l01 modules uses discrete addresses allowing up to 6 slave nodes to a single master “hub”. It only polls one address at a time.

JRemington -Since the Arduinos have no RTC I wanted to stay away from random unsolicited data stream(plus its an opportunity to learn about 2 way control.

Wawa - I already have rf24 modules and several nanos to work with, plus I’m already somewhat familiar with them now. I’m going to stick to those.

Does anyone know how the RF24 lib determines how long to wait before resending a lost packet?

I'm in favour of polling as it eliminates the need to make provision for data collisions. It also provides a convenient means to identify a failed slave.

Have a look at this Simple nRF24L01+ Tutorial. It includes an example for a master and 2 slaves that can easily be extended to a larger number of slaves.

...R

I took a look at the nRF24L01 library, and I can see how polling is probably easier to get going for sure. The rub with polling is 1) Scaling your sensor network 2) Power consumption of the sensors is generally higher.

1 and #2 are directly related to each other. Think about having 50 sensor nodes and your hub is polling each one-by-one all of the time for data. The hub reaches a point where it takes too long to poll all 50 nodes.

In a push model, the order in which data comes in is arbitrary. Instead of coordinating your sensors and hub, you simply sleep your sensors and your hub just listens for new data. Anyways, it doesn't really matter with a small number of nodes.

Having said that, the nRF24L01 library seems to be geared more towards a "connected" network topology since you explicitly open a read/write pipe to an addressed node. Best of luck!

A polled network is a poor choice for battery powered sensor nodes.

czu001: I took a look at the nRF24L01 library, and I can see how polling is probably easier to get going for sure. The rub with polling is 1) Scaling your sensor network 2) Power consumption of the sensors is generally higher.

1 and #2 are directly related to each other. Think about having 50 sensor nodes and your hub is polling each one-by-one all of the time for data. The hub reaches a point where it takes too long to poll all 50 nodes.

I can see how polling may seem less than ideal if the remote sensors need to run on a battery ... BUT ...

There will be little difference between {A} the time taken to poll 50 nodes and {B} the time taken to receive data from 50 nodes. If the data is sent frequently (say 5 times per second for each of the 50 nodes or 250 messages per second) then if the sending is unregulated there will be a significant risk of a data collision which will slow things down.

On the other hand, if (as you say) you are content to read each sensor once every 5 minutes you could arrange for the sensors to wake up for 1 second in every 5 minutes and listen for a polling call from the master. Even if they all happened to be awake at the same time the master could easily collect data from 50 in 1 second - a round trip message and acknowledgement takes a few millisecs. This way the sensors could be asleep for 299 out of 300 seconds. By the way I am assuming the master polls all the time even when the sensors are asleep as that means there is no need to coordinate the polling with the wake-up time

...R

you could arrange for the sensors to wake up for 1 second in every 5 minutes and listen for a polling call from the master.

Possibly, with an accurate RTC per sensor, all appropriately synchronized.

jremington: Possibly, with an accurate RTC per sensor, all appropriately synchronized.

That is not at all necessary in my vision of the thing. The millis() timer (or the WatchDog) would be perfectly adequate.

Imagine that someone calls your name once every minute throughout the night (and assume the sound is not sufficient to wake you). For some other reason you wake up at some random time - say 0237 - and you hear your name being called. You would also hear it if you had happened to wake at 0319. There is no need for you to wake up at any specific time. The only requirement is that, when you do wake up, you stay awake until you hear your name - which should happen in not more than 1 minute.

...R

The millis() timer (or the WatchDog) would be perfectly adequate.

Obviously, you haven't tried doing something like this.

jremington: Obviously, you haven't tried doing something like this.

I have, and it works - but it was some time ago.

Did you read all of Reply #10 ? I think I added to it while you were writing.

...R

Different horses for different courses. High data throughout from multiple nodes will be a different solution than 1-5 minute intervals.

Robin2 in your scenario I think the difference is that the hub is ignoring the screams until it’s their turn. Which could lead to an unnecessary amount of time screaming. Unless of course you synchronize the hub and sensors. High throughput is a different animal I think though.

It’s a trade off. Polling will definitely let you know if there’s an issue with a particular node pretty quickly and easily; whereas, listening means you need to monitor a little differently on the hub. But you really are burning execution cycles on polling for intervals of 1-5 minutes.

Thank you every one for the all the input so far. I’m looking at less than a dozen nodes and only a few reports per hour from each. The RF24 allows for some error checking and I can sleep the nodes after a successful transmission to save power.

RTC would be a really nice way to coordinate the nodes for this and many other projects but adds cost and complexity.

For the time being I’ll probably just use the ample supply of 1 amp USB walwarts I have laying around from various amazon products.

I have other projects I’d like to build with 2 way communications so this is a good stepping stone even if I don’t end up with maximum efficiency.

Lots of good info and stuff I hadn’t thought of , thanks everyone.

ok so I hacked together some code, mostly from Robin2’s linked tutorial, but i am getting a TX failure on the main hub.

Output looks like:

======== For Slave 0 ========

  • Data Request Sent: Send Data*
  • Tx failed*
  • ======== For Slave 1 ========*
  • Data Request Sent: Send Data*
  • Tx failed*

The “Send Data” is just the trigger and the sensor data is regularly updated on the Ack package so its fairly current when it Acks the hubs data.

A second set of eyes would be appreciated. My apologizes for the very messy code.

Below is the control hub code -

// MultiTxAckPayload - the master or the transmitter
//   works with n Arduinos as slaves
//     each slave should use the dht11node program
//       one with the adress {'R','x','A','A','A'}
//          the other with {'R','x','A','A','B'}
//            the next with {'R','x','A','A','C'} ..... ETC

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


#define CE_PIN   9
#define CSN_PIN 10

const byte numSlaves = 2; //Adjust number of slaves here
const byte slaveAddress[numSlaves][5] = {
        // each slave needs a different address
                            {'R','x','A','A','A'},
                            {'R','x','A','A','B'}
                        };

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

 float h = 0; //humidity
 float t = 0; //temp C
 float f = 0; //temp F
 float hic = 0; // heat index C
 float hif = 0; // heat index F

char dataToSend[10] = ("Send Data"); // fixed data request messege
char txNum = '0';  // tx/rx loop count 
int ackData[5] = {h, t, f, hic, hif}; // to hold the values coming from the slave
bool newData = false;

unsigned long currentMillis;
unsigned long prevMillis;
unsigned long txIntervalMillis = 6000; // send once 6 second

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

void setup() {

    Serial.begin(9600);
    Serial.println("Sensor Hub Starting");
    radio.begin();
    radio.setDataRate( RF24_250KBPS );

    radio.enableAckPayload();

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

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

void loop() {

    currentMillis = millis();
    if (currentMillis - prevMillis >= txIntervalMillis) {
        send();
        
    }
        // showData(); -- moved into send()
}

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

void send() {

        // call each slave in turn
    for (byte n = 0; n < numSlaves; n++){

            // open the writing pipe with the address of a slave
        radio.openWritingPipe(slaveAddress[n]);

            // Set messege to be sent
        dataToSend[10] = ("Send Data");

        bool rslt;
        rslt = radio.write( &dataToSend, sizeof(dataToSend) );
            // 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(n);
        Serial.println("  ========");
        Serial.print("  Data Request Sent: ");
        Serial.print(dataToSend);
        Serial.print('\n');
        
        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");
    }

    prevMillis = millis();
 }


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

void showData() {
    if (newData == true) {
        Serial.print("  Sensor Data ");
        Serial.print("Humdity: ");
        Serial.print(ackData[0]);
        Serial.print(",  Temp C: ");
        Serial.print(ackData[1]);
        Serial.print(",  Temp F: ");
        Serial.print(ackData[2]);
        Serial.print('\n');
        Serial.print("Heat Index(C):  ");
        Serial.print(ackData[3]);
        Serial.println(", Heat Index(F):  ");
        Serial.print(ackData[4]);
        
        newData = false;
    }
}

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

//void updateMessage() {
//        // so you can see that new data is being sent
//    txNum += 1;
//    if (txNum > '9') {
//        txNum = '0';
//    }
//    dataToSend[8] = txNum;
//}

and the sensor node code :

// For 3 pin DHT sensors
// NOTE: If using a board with 3.3V logic like an Arduino Due connect pin 1
// to 3.3V instead of 5V!
// Connect pin 1 (on the left) of the sensor to +5V
// Connect pin 2 (in the middle) of the sensor to whatever your DHTPIN is
// Connect pin 3 (on the right) of the sensor to GROUND



#include "DHT.h"  //Import DHT lib

// Uncomment whatever type you're using!
#define DHTTYPE DHT11   // DHT 11
//#define DHTTYPE DHT22   // DHT 22  (AM2302), AM2321
//#define DHTTYPE DHT21   // DHT 21 (AM2301)

#define DHTPIN 2     // Digital pin connected to the DHT sensor

DHT dht(DHTPIN, DHTTYPE); // set up DHT sensor

// import radio libraries
#include <SPI.h>
#include <nRF24L01.h>
#include <RF24.h>

// Set CE, CSN pin number
#define CE_PIN   9
#define CSN_PIN 10

//Create radio address
//Give each slave node a different address by changing last letter in address 
const byte thisSlaveAddress[5] = {'R','x','A','A','A'};

//Create radio object
RF24 radio(CE_PIN, CSN_PIN);

//Create variables to store sensor data
 float h = 0; //humidity
 float t = 0; //temp C
 float f = 0; //temp F
 float hic = 0; // heat index C
 float hif = 0; // heat index F
 
//Create data structure
char dataReceived[10]; // this must match dataToSend in the TX
int ackData[5] = {h, t, f, hic, hif}; // 5 values to be returned
bool newData = false;


void setup() {
  Serial.begin(9600); // open serial for writing
  dht.begin();        // start sensor
  
  Serial.println("DHT initialized, Starting radio");
  Serial.println('\n');
    radio.begin();
    radio.setDataRate( RF24_250KBPS );
    radio.openReadingPipe(1, thisSlaveAddress);
    
  Serial.println("Radio initialzed, loading ack data");
  Serial.println('\n');
  
  radio.enableAckPayload();
    
  radio.startListening();

  radio.writeAckPayload(1, &ackData, sizeof(ackData)); // pre-load data
  
  Serial.println(F("Setup Complete"));
}

void loop() {

  // Read sensor data, update Ack then check for data request. If data request == TRUE send Ack.
  


  readSensor(); // get sensor data
  loadAck(); // update Ack data
  checkRadio(); // check radio for data request 
  
}
//********

void readSensor(){
  
  // Reading temperature or humidity takes about 250 milliseconds!
  // Sensor readings may also be up to 2 seconds 'old' (its a very slow sensor)
  h = dht.readHumidity();
  // Read temperature as Celsius (the default)
  t = dht.readTemperature();
  // Read temperature as Fahrenheit (isFahrenheit = true)
  f = dht.readTemperature(true);

  // Compute heat index in Fahrenheit (the default)
  hif = dht.computeHeatIndex(f, h);
  // Compute heat index in Celsius (isFahreheit = false)
  hic = dht.computeHeatIndex(t, h, false);


//  Serial.print(F("Humidity: "));
//  Serial.print(h);
//  Serial.print(F("%  Temperature: "));
//  Serial.print(t);
//  Serial.print(F("°C "));
//  Serial.print(f);
//  Serial.print(F("°F  Heat index: "));
//  Serial.print(hic);
//  Serial.print(F("°C "));
//  Serial.print(hif);
//  Serial.println(F("°F"));
  
}

//**************

void loadAck(){
   
   ackData[0] = (h);
   ackData[1] = (t);
   ackData[2] = (f);
   ackData[3] = (hic);
   ackData[4] = (hif);

// check ack data    
Serial.print(ackData[0]);
Serial.print('\n');
Serial.print(ackData[1]);
Serial.print('\n');
Serial.print(ackData[2]);
Serial.print('\n');
Serial.print(ackData[3]);
Serial.print('\n');
Serial.print(ackData[4]);
Serial.print('\n');
Serial.print('\n');
   
   radio.writeAckPayload(1, &ackData, sizeof(ackData)); // load the payload for the next time
}


//*****************

void checkRadio() {
    if ( radio.available() ) {
        radio.read( &dataReceived, sizeof(dataReceived) );
//        delay(5000);
//       } else{
//          delay(2500);
        }
}

Ffjohn: ok so I hacked together some code, mostly from Robin2's linked tutorial, but i am getting a TX failure on the main hub.

Did you get the code in my Tutorial working with no changes except to set appropriate addresses if you need more.? If not then that is the place to start.

When that works then you can add other features checking that it still works after every change.

...R

Robin2,

I did and it worked great, I may revert some changes today to try and check various other functions. I was able to vet most of the code with serial output hence the extra Serial-print everywhere. Part of my problem is the section where the failure seems to be, I honestly don't understand all of the code. I've been trying to find references and piece together usage of a few items so I understand what is happening thru the entire code.

In particular Im having a hard time finding reference material on the Ack function and how it is all handled as well as any limitations.

Im not clear on weather there are any constraints on the below line that i may have over looked.

char dataToSend[10] = ("Send Data");

I don't need a loop counter so I wrote that out of your code and I suspect in altering that function call ( updateData()) that I may have introduced the problem.

Assumptions i am working on ( please correct me if I am wrong):

  1. Writing to radio causes radio to send with no further action needed
  2. Once Ack data is loaded, no other command is needed for Ack to function except to receive a messege.
  3. I can fit all of the specified data into a single packet.

-John

Ffjohn: In particular Im having a hard time finding reference material on the Ack function and how it is all handled as well as any limitations.

If you can be more specific about what you are uncertain about I may be able to help.

Assumptions i am working on ( please correct me if I am wrong):

  1. Writing to radio causes radio to send with no further action needed
  2. Once Ack data is loaded, no other command is needed for Ack to function except to receive a messege.
  3. I can fit all of the specified data into a single packet.

That seems to be correct, but it is a series of very brief statements and you may have other stuff in mind that complicates things.

On point 3, an nFR24 message can hold 32 bytes of data.

In your slave program this makes no sense

float h = 0; //humidity
 float t = 0; //temp C
 float f = 0; //temp F
 float hic = 0; // heat index C
 float hif = 0; // heat index F

//Create data structure
char dataReceived[10]; // this must match dataToSend in the TX
int ackData[5] = {h, t, f, hic, hif}; // 5 values to be returned

You have defined some float values so why don't you have an array of floats?

Also, rather than try to initialize the array before setup() why not just call the function loadAck() from within setup()

My general feeling is that you made too many changes to my Tutorial code before you tested to see if things were still working. Progress in very mall steps with lots of testing.

...R

OK everybody, it finally works. I could not get it running with array of floats so I had to go back to ints, it loses a bit of resolution but at least it is working.

The control “hub” requests data from each sensor individually at the specified interval. If there is no answer you will get a printout showing which nodes are down.

Robin2, if you know any reason why float may have caused a problem, I’m always open to improving the code. Thank you for all the help and of course all of the code this is based on.

The “nodes” I made are an Arduino Nano V3, generic 3 pin DHT11, and generic nRF24L01+PA+LNA. I also used generic nRF24L01+ for prototyping and bench testing and they worked well also.

Below is the code for the HUB or Master:

// Many thanks to Robin2, whos code composes the majority of this program and whos help
// was invaluble in finishing it. Sensor code is from DHT Sensor Library - many thanks to
// ladyada for the examples. 

// REQUIRES the following Arduino libraries:
// - DHT Sensor Library: https://github.com/adafruit/DHT-sensor-library
// - Adafruit Unified Sensor Lib: https://github.com/adafruit/Adafruit_Sensor
// - RF24 by TMRh20
// DHThub - the master or the transmitter
//   works with n Arduinos as slaves
//     each slave should use the DHTnode program
//       one with the adress {'R','x','A','A','A'}
//          the other with {'R','x','A','A','B'}
//            the next with {'R','x','A','A','C'} ..... ETC

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


#define CE_PIN   9
#define CSN_PIN 10

const byte numSlaves = 1; //Adjust number of slaves here
const byte slaveAddress[numSlaves][5] = {
        // each slave needs a different address
                            {'R','x','A','A','A'}//,
                            //{'R','x','A','A','B'},
                            // add address for each slave here
                        };

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


char dataToSend[10] = ("Send Data"); // fixed data request messege
int ackData[5]; // to hold the values coming from the slave
bool newData = false;

unsigned long currentMillis;
unsigned long prevMillis;
unsigned long txIntervalMillis = 10000; // send once 10 second

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

void setup() {
   
    Serial.begin(9600);
    Serial.println("Sensor Hub Starting");
    
    radio.begin();
    radio.setDataRate( RF24_250KBPS );

    radio.enableAckPayload();

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

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

void loop() {

    currentMillis = millis();
    if (currentMillis - prevMillis >= txIntervalMillis) {
        send();
        
    }
        // showData(); -- moved into send()
}

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

void send() {

        // call each slave in turn
    for (byte n = 0; n < numSlaves; n++){

            // open the writing pipe with the address of a slave
        radio.openWritingPipe(slaveAddress[n]);

           
// success of radio.write below is solely determined by a properly recieved Ack response
        bool rslt;
        rslt = radio.write( &dataToSend, sizeof(dataToSend) ); 

            // 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(n);
        Serial.println("  ========");
        Serial.print("Data Request Sent: ");
        Serial.print(dataToSend);
        Serial.print('\n');

        
        if (rslt) {  // if rslt == true because radio.write was successful ....
                if ( radio.isAckPayloadAvailable() ) { // check for ackPayload from node
                radio.read(&ackData, sizeof(ackData));
                newData = true;
              
             } 
             else {
                Serial.println("  Acknowledge but no data ");
            }
        }
            else {
            Serial.println("  Tx failed"); // can print with a good TX but no Ack recieved
        }
        showData();
        Serial.print("\n");
    }

    prevMillis = millis(); // resets interval timer
 }


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

void showData() {
    if (newData == true) {
        Serial.println("Sensor Data ");
        Serial.print("  Humdity: ");
        Serial.print(ackData[0]);
        Serial.println("%");
        Serial.print("  Temp C: ");
        Serial.print(ackData[1]);
        Serial.print(",  Temp F: ");
        Serial.println(ackData[2]);
        Serial.print("  Heat Index(C): ");
        Serial.print(ackData[3]);
        Serial.print(", Heat Index(F): ");
        Serial.print(ackData[4]);
        Serial.print('\n');
        Serial.print('\n');
        
        newData = false;
    }
}

And the NODE or Slave code:

// Many thanks to Robin2, whos code composes the majority of this program and whos help
// was invaluble in finishing it. Sensor code is from DHT Sensor Library - many thanks to
// ladyada for the examples. 

// REQUIRES the following Arduino libraries:
// - DHT Sensor Library: https://github.com/adafruit/DHT-sensor-library
// - Adafruit Unified Sensor Lib: https://github.com/adafruit/Adafruit_Sensor
// - RF24 by TMRh20

// For 3 pin DHT sensors
// NOTE: If using a board with 3.3V logic like an Arduino Due connect pin 1
// to 3.3V instead of 5V!
// Connect pin 1 (on the left) of the sensor to +5V
// Connect pin 2 (in the middle) of the sensor to whatever your DHTPIN is
// Connect pin 3 (on the right) of the sensor to GROUND



#include "DHT.h"  //Import DHT lib

// Uncomment whatever type you're using!
#define DHTTYPE DHT11   // DHT 11
//#define DHTTYPE DHT22   // DHT 22  (AM2302), AM2321
//#define DHTTYPE DHT21   // DHT 21 (AM2301)

#define DHTPIN 2     // Digital pin connected to the DHT sensor

DHT dht(DHTPIN, DHTTYPE); // set up DHT sensor

// import radio libraries
#include <SPI.h>
#include <nRF24L01.h>
#include <RF24.h>

// Set CE, CSN pin number
#define CE_PIN   9
#define CSN_PIN 10

//Create radio address
//Give each slave node a different address by changing last letter in address 
const byte thisSlaveAddress[5] = {'R','x','A','A','A'};

//Create radio object
RF24 radio(CE_PIN, CSN_PIN);
 
//Create data structure
char dataReceived[10]; // this must match dataToSend in the TX
int ackData[5];
bool newData = false;


void setup() {
  Serial.begin(9600); // open serial for writing
  dht.begin();        // start sensor
  
  Serial.println("DHT initialized, Starting radio");
  Serial.println('\n');
    
  radio.begin();
  radio.setDataRate( RF24_250KBPS );
  radio.openReadingPipe(1, thisSlaveAddress);
  
  radio.enableAckPayload();
  radio.startListening();

  Serial.println(F("Setup Complete"));
  
}

void loop() {

  loadAck(); // update Ack data
  getData(); // check radio for data request 

  if (newData = true){
    showData();
  }
  
}


//**************

void loadAck(){
   
   ackData[0] = dht.readHumidity();                  // Read Humidity
   ackData[1] = dht.readTemperature();               // Temp C
   ackData[2] = dht.readTemperature(true);           // Temp F
   ackData[3] = dht.computeHeatIndex(ackData[1], ackData[0], false);  // Heat Index C
   ackData[4] = dht.computeHeatIndex(ackData[2], ackData[0]);         // Heat Index F

   radio.writeAckPayload(1, &ackData, sizeof(ackData)); // load the payload for the next time
   
   Serial.print('\n');
   Serial.print('\n');
   Serial.print("Updating ackPayload: ");
   Serial.print('\n');
   Serial.print(ackData[0]);
   Serial.print('\n');
   Serial.print(ackData[1]);
   Serial.print('\n');
   Serial.print(ackData[2]);
   Serial.print('\n');
   Serial.print(ackData[3]);
   Serial.print('\n');
   Serial.print(ackData[4]);
   Serial.print('\n');
   Serial.print("Size of ackData:  ");
   Serial.print(sizeof(ackData));
   Serial.print('\n');
   Serial.print("Waiting on hub for data request.....");

  
   delay(2500); // delay between ackData updates, set to < HUB request interval
}


//*****************
// Checks radio for data request and automatically sends ackData if true
void getData() {
      if ( radio.available() ) {
        radio.read( &dataReceived, sizeof(dataReceived) );
        newData = true;
    }
 }

 //***************** 
 // confirms and displays Data RX and  that Ack was  TX
 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;
        
    }
}

-John

DHThub_1_0.ino (4.07 KB)

DHTnode_1_0.ino (3.87 KB)