0

I'm trying to do wireless thermometer on max31865 arduino and nrf24l01 but I'm having problem sending whole data struct I can send int or char arrays but when I try to send whole struct I got output as

id: 131073 temperature: 0

Is there error in my code or there is some issue with differences in how arduino and raspberry store data? I don't really have experience in this so my question is how do I send struct that contain two fields of int or there is some better way? I need to transmit id and temperature in one package.

Transmitter code(Arduino)

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

#define RREF      430.0
#define RNOMINAL  100.0

typedef struct{
  int id = 100;
  int temperature = 100;
}
temp;

temp data;

bool radioNumber = 0;
int i =0;
Adafruit_MAX31865 thermo = Adafruit_MAX31865(10, 11, 12, 13);
RF24 radio(7,8);

byte addresses[][6] = {"1Node","2Node"};
bool role = 0;

void setup() {
  Serial.begin(115200);
  thermo.begin(MAX31865_3WIRE);
  radio.begin();
  radio.setChannel(125);
  radio.setPALevel(RF24_PA_MIN);
  radio.powerUp();
  radio.setDataRate(RF24_1MBPS);
  if(radioNumber){
    radio.openWritingPipe(addresses[1]);
    radio.openReadingPipe(1,addresses[0]);
  }else{
    radio.openWritingPipe(addresses[0]);
    radio.openReadingPipe(1,addresses[1]);
  }
  radio.stopListening();
}

void loop() {
      data.id = 1;
      data.temperature = 2;                                   
    //int temp = 2; //thermo.temperature(RNOMINAL, RREF);
    Serial.println(temp);   
    if (!radio.write( &data, sizeof(data) )){
        Serial.println(F("failed"));
     }
     delay(1000);
}

Receiver code(Raspberry pi b3+)

#include <cstdlib>
#include <iostream>
#include <sstream>
#include <string>
#include <unistd.h>
#include <RF24/RF24.h>

using namespace std;

typedef struct{
        int id = 99;   // debug value
        int temperature = 99;
}
temp;

RF24 radio(22,0);
temp data;

bool radioNumber = 1;
const uint8_t pipes[][6] = {"1Node", "2Node"};

int main(int argc, char** argv)
{
    radio.begin();
    radio.setChannel(125);
    radio.setPALevel(RF24_PA_MIN);
    radio.setDataRate(RF24_1MBPS);
    radio.setRetries(15, 15);
    radio.printDetails();
    if (!radioNumber) {
        radio.openWritingPipe(pipes[0]);
        radio.openReadingPipe(1, pipes[1]);
    } else {
        radio.openWritingPipe(pipes[1]);
        radio.openReadingPipe(1, pipes[0]);
    }

    radio.startListening();

    while (1) {
            if (radio.available()) {
                int tem = 0;
                while (radio.available()) {
                    radio.read(&data, sizeof(data));
                }
                cout << tem  << "  " << "id: "<< data.id<< " temperatura: " << data.temperature << endl;
                delay(925);

            }
        }
    return 0;
}

EDIT: Ok after running sizeof(data) on both devices, I notice that structs have different size 4 bytes for arduino and 8 for raspberry. So change on raspberry side to

typedef struct{
  uint16_t id = 100;
  uintt16_t temperature = 100;
}
temp;

And this is working but, may I ask why int have various size on arduino and raspberry?

1 Answer 1

4

Your problem is that you are communicating between an 8-bit and a 32-bit architecture.

On an 8-bit architecture int is 16 bits. On a 32-bit it's 32 bits. Why the difference? Because "it is". It's how it's always been since the dawn of C. The concept of int is a flexible idea with no fixed defined size - the size is largely defined by the architecture and the compiler. Although conventions now dictate that an int will be 16 bits on an 8-bit system and 32-bits on a 32-bit system.

You can think of it as the integer size being the same as the internal register width of the processor but with a lower bound of 16 bits.

This is precisely why the fixed width integer types uint16_t etc exist - so that you can enforce the same data size on different architectures.

Incidentally you should also be aware of the endianness of your systems. In your case they are both "little endian", but "big" (and even "middle") endian systems also exist. This defines what order each byte of an integer (and other multi-byte data types) is stored in memory. If you send an integer from a little-endian to a big-endian system and don't apply any transformation to the data to reverse the bytes then the values will be completely wrong.

2
  • Thank you for such comprehensive answer, I was aware of big/little endian systems but I never thought about differences in architectures like you mentioned. Now I think I got this next step is to somehow manage with the noise. Again thanks for the nice answer Aug 20, 2020 at 17:53
  • Had the same issue between an atmega328p and an esp8266, scratched my head for a good couple of hours before stumbling upon this, wouldn't have thought about it, even though it makes perfect sense! Thank you! Oct 6, 2022 at 16:26

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.