Data transmision issue from Arduino pro mini to ESP32 via nrf24l01

Hi. I try to replace Arduino mega receiver by ESP32 wroom-32 but I have problem with getting correct data structure.

I use Aduino Pro mini with DHT and nrf24L01 to transmit temperature/humidity data to Arduino mega receiver with nrf24L01.

After replace Arduino Mega by ESP32 wroom-32, using the same code (nrf24 CE, CSN had been changed of course) received data are not correct. It seems like data struct compatibility issue between Arduino and ESP. I tried few rf24 libraries including a software SPI library.

Posted/received data:
typedef struct {
int unit_id;
char parameter[4];
float value;
} myData;

nrf24 is connected to ESP32 correctly and works fine.

I made some test with the same code to check transmissions between: Arduino and Arduino, Arduino and ESP, ESP and ESP:

  • Arduino pro mini -> Arduino Mega - received data ok;
  • Arduino pro mini -> ESP32 wroom-32 - wrong received data;
  • ESP8266 -> ESP32 wroom-32 - received data ok.


Screen from Arduino IDE monitor;
ESP32 wroom-32 as receiver;
Arduino pro mini (e.g. "unit 18: 69414403 :: v|0.00" - not correct) and ESP8266 (e.g. "unit 13 :: deb|1.00" - correct) as transmitter.

My Test code below.

Transmitter code

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

const int UNIT_ID  = 13;
typedef struct {
  int unit_id;        // Sensor unit ID UNIT_ID.
  char parameter[4];  // Parameter name.
  float value;        // Value.
} myData;
const uint64_t address_center = 0xF9A3F7BBE00L; 
RF24 radio(2, 4);  // ESP2866
//RF24 radio(9, 10);  // Arduino pro mini 3.3V
int counter = 0;

void setup()
{
  Serial.begin(115200);

  // Radio initialize.
  radio.begin();
  radio.setPALevel(RF24_PA_HIGH);    // RF24_PA_MIN, RF24_PA_LOW, RF24_PA_HIGH or RF24_PA_MAX.
  radio.setChannel(108);              // Above most Wifi Channels.
  radio.setDataRate(RF24_250KBPS);    // RF24_250KBPS, RF24_1MBPS, RF24_2MBPS
  radio.openWritingPipe(address_center);
  radio.stopListening();
//  radio.printDetails();
}

void loop()
{
  counter++;
  postData("deb", counter);
  delay(5000);
}

bool postData(char* parameter, float value)
{
  // Prepare data to send.
  myData post_data;
  post_data.unit_id = UNIT_ID;
  strncpy(post_data.parameter, parameter, sizeof(post_data.parameter));
  post_data.value = value;

  bool result = radio.write(&post_data, sizeof(myData));
  if (result)
  {
    return true;
  }
  return false;
}

Receiver coed:

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

/**
* Receiver nRF24L01 config.
*/
RF24 radio(4, 5); // CE, CSN
const uint64_t address_getway    = 0xF9A3F7BBE00L;

/**
* Data structure received from sensors.
*/
struct unitDataStructure {
  int id;
  char parameter[4];
  float value;
};

void setup() {
  Serial.begin(115200);

  // Initialize RF24 Radio.
  radio.begin();
  radio.setPALevel(RF24_PA_HIGH);      // RF24_PA_MIN or RF24_PA_MAX
  radio.setChannel(108);              // Above most Wifi Channels
  radio.setDataRate(RF24_250KBPS);    // RF24_250KBPS, RF24_1MBPS, RF24_2MBPS
  radio.openReadingPipe(1, address_getway);
  radio.startListening();
  radio.printDetails();
}

void loop() {
  unitDataStructure unitData;

  // Received radio data.
  if ( radio.available() ) {
    radio.read(&unitData, sizeof(unitDataStructure));
    Serial.println("<- unit " + String(unitData.id) + ": " + String(unitData.parameter) + "|" + String(unitData.value)); 
  }
}

There is indeed an issue moving structures between 8bit and 32bit systems.

Discussed here;

Thanks. That's the source of the problem.

I changed int to int8_t in data structure for unit ID, but I didn't figure out what would be the best replacement to use instead of float - the values in float are not correct on the receiver side (I get 0.00).

I tried to convert values from float to int and then back to float (e.g. transmitter: 23.01 * 100 -> receiver: 2301 / 100) but int8_t is to small, int16_t or int32_t doesn't work between Arduino pro mini and ESP32 (I don't receive correct data for sending value).

I used "char value[8];" to (float to char -> char to float) and that works but I thing it's not a good practice.

Now I have on both sides:

struct unitDataStructure {
  int8_t id;
  char parameter[4];
  char value[8];
};

Use

struct unitDataStructure {
  int8_t id;
  char parameter[4];
  char value[8];
} __attribute__((packed, aligned(1)));

to stop the ESP to align struct members on 32bit bounderies.

Thank you. Both above comments were helpful.

As a solution of my problem I used on ESP32-wroom-32 receiver side struct:

struct unitDataStructure {
int8_t id;
char parameter[4];
float value;
} attribute((packed, aligned(1)));

and on Arduino Pro Mini transmitter side:

struct unitDataStructure {
int8_t id;
char parameter[4];
float value;
};