nRF24 / RF24

OSI Layer 2 driver for nRF24L01 on Arduino & Raspberry Pi/Linux Devices
https://nrf24.github.io/RF24
GNU General Public License v2.0
2.21k stars 1.02k forks source link

Send and Receive multiple Arrays #795

Closed akilakavinda closed 2 years ago

akilakavinda commented 2 years ago

I'm doing research for Weather Station. For that, I need to send a large number of values which will be more than 32 Bytes. Since the Max Payload is about 32 Bytes, I tried sending those data by using 2 Arrays (Tx and Rx codes are below-mentioned). But it didn't give an output what I anticipated. My requirement is to send all those values at once (using any method) and use all those values in different places in the receiver programme. Therefore, highly appreciate help in this scenario.

Transmitter Code

#include <Wire.h>
#include <SPI.h>
#include <Adafruit_BME280.h>
#include <Adafruit_BMP085.h>
#include <nRF24L01.h>
#include <RF24.h>
#include "DHT.h"

float Weather_Data_01[6];
float Weather_Data_02[5];
#define DHTPIN 2
#define DHTTYPE DHT22

Adafruit_BME280 bme; // I2C
Adafruit_BMP085 bmp;
DHT dht(DHTPIN, DHTTYPE);

RF24 radio(7, 8); // CE, CSN

const byte address[6] = "00001";
unsigned int counter = 0;
void setup() {
  Serial.begin(9600);
  //Serial.println(F("BMP280 test"));
  bmp.begin();
  bme.begin();
  dht.begin();
  radio.begin();
  radio.openWritingPipe(address);
  radio.setPALevel(RF24_PA_MIN);
  radio.stopListening();

}

void loop() {

  counter = counter + 1;
  Weather_Data_01[0] = bme.readTemperature();
  Weather_Data_01[1] = bmp.readTemperature();
  Weather_Data_01[2] = dht.readTemperature();
  Weather_Data_01[3] = bme.readHumidity();
  Weather_Data_01[4] = dht.readHumidity();
  Weather_Data_01[5] = dht.computeHeatIndex(dht.readTemperature(), dht.readHumidity(), false);
  Weather_Data_02[0] = bme.readPressure() / 100;
  Weather_Data_02[1] = bmp.readPressure() / 100;
  Weather_Data_02[2] = bme.readAltitude(1013.25);
  Weather_Data_02[3] = bmp.readAltitude();
  Weather_Data_02[4] = counter;

  radio.write(&Weather_Data_01, sizeof(Weather_Data_01));
  radio.write(&Weather_Data_02, sizeof(Weather_Data_02));
  Serial.println();
  delay(2000);
}

Receiver Code

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

float Weather_Data_01[6];
float Weather_Data_02[5];

RF24 radio(4, 5); // CE, CSN

const byte address[6] = "00001";

void setup() {
  Serial.begin(9600);
  radio.begin();
  radio.openReadingPipe(0, address);
  radio.setPALevel(RF24_PA_MIN);
  radio.startListening();
}

void loop() {
  if (radio.available()) {
    radio.read(&Weather_Data_01, sizeof(Weather_Data_01));
    radio.read(&Weather_Data_02, sizeof(Weather_Data_02));
        Serial.print(Weather_Data_01[0]);
        Serial.print("°C\t");
        Serial.print(Weather_Data_01[1]);
        Serial.print("°C\t");
        Serial.print(Weather_Data_01[2]);
        Serial.print("°C\t");
        Serial.print(Weather_Data_01[3]);
        Serial.print("%\t");
        Serial.print(Weather_Data_01[4]);
        Serial.print("%\t");
        Serial.print(Weather_Data_01[5]);
        Serial.print("°C\t");
        Serial.print(Weather_Data_02[0]);
        Serial.print(" hPa\t");
        Serial.print(Weather_Data_02[1]);
        Serial.print(" hPa\t");
        Serial.print(Weather_Data_02[2]);
        Serial.print("m\t");
        Serial.print(Weather_Data_02[3]);
        Serial.print("m\t");
        Serial.println(Weather_Data_02[4]);
 }
}
2bndy5 commented 2 years ago

I haven't looked at your code (yet), but you could try using RF24Network because it has builtin capability to send payloads (aka "network messages") of up to 144 bytes; RF24Network lib fragments large messages into 32 byte payloads. Are you using an ATTiny (there's some default limitations in RF24Network for ATTiny MCUs)?

akilakavinda commented 2 years ago

I'm using Arduino Mega2560 as Transmitter and ESP32 as Receiver. I include the code in the question itself now.

2bndy5 commented 2 years ago

wait a minute! A float occupies 4 bytes. So,

float Weather_Data_01[6]; // allocates 24 bytes
float Weather_Data_02[5]; // allocates 20 bytes

These should fit in 2 transmissions. You want to transmit it all at once? That's not possible with this radio. The 32 byte limit is a hardware limit not a library limit.

2bndy5 commented 2 years ago
  if (radio.available()) {
    radio.read(&Weather_Data_01, sizeof(Weather_Data_01));
    radio.read(&Weather_Data_02, sizeof(Weather_Data_02));

this is likely the problem. available() is asserted for each received payload. So if it only receives 1 out of 2 payloads, then the data fetched by the second radio.read() is dummy data from the radio's empty FIFO.

what you need is


bool gotPayload1 = false;

void loop() {
  if (radio.availble()) {
    if (gotPayload1) {
      radio.read(&Weather_Data_02, sizeof(Weather_Data_02));
      gotPayload1 = false; // reset for the next pair of payloads
      /* do stuff with data from both arrays */
    }
    else {
      radio.read(&Weather_Data_01, sizeof(Weather_Data_01));
      gotPayload1 = true;
  }
}
2bndy5 commented 2 years ago

you could also send a payload ID number with each payload to help identify which one was received, but that would be starting to replicate RF24Network.

akilakavinda commented 2 years ago

That code worked and I was able to get what I anticipate from the output. Thank you very much and highly appreciate your tremendous help. Also, I was able to use more than 2 arrays to get the same output using the Switch statement. But, it's better to use Payload ID, because from time to time, the sequence of values gets changed.

I used this code in the receiver and if there is any other easy method to do the same, high appreciate help on that too.

bool gotPayload1 = false;
int ArrayID = 1;

void loop() {

  if (radio.available()) {
    if (gotPayload1) {
      radio.read(&Weather_Data_04, sizeof(Weather_Data_04));
      gotPayload1 = false; // reset for the next pair of payloads
      /* do stuff with data from both arrays */
     // I printer all values received from those arrays
    }

    else {

      switch (ArrayID) {
        case 1:
          radio.read(&Weather_Data_01, sizeof(Weather_Data_01));
          ArrayID = 2;
          break;
        case 2:
          radio.read(&Weather_Data_02, sizeof(Weather_Data_02));
          ArrayID = 3;
          break;
        case 3:
          radio.read(&Weather_Data_03, sizeof(Weather_Data_03));
          gotPayload1 = true;
          ArrayID = 1;
          break;
      }
    }
  }
}
2bndy5 commented 2 years ago

Glad to see we answered your first question ever on github. It is customary to close an issue that you opened if there is nothing more to be discussed. You can still comment here even if it is closed.

2bndy5 commented 2 years ago

if there is any other easy method to do the same

look up RF24Network. If you ever decide to get data from more than 1 weather station, then using RF24Network can simplify your program(s).

akilakavinda commented 2 years ago

Highly appreciate your support again. I'll look into RF24Network.