Отправка структуры данных с 2 полями int из Arduino в Raspberry через NRF24L01

Я пытаюсь сделать беспроводной термометр на max31865 arduino и nrf24l01, но у меня проблемы с отправкой всей структуры данных. Я могу отправлять массивы int или char, но когда я пытаюсь отправить всю структуру, я получаю вывод как

id: 131073 temperature: 0

Есть ли ошибка в моем коде или есть какая-то проблема с различиями в том, как arduino и raspberry хранят данные? У меня действительно нет опыта в этом, поэтому мой вопрос: как мне отправить структуру, содержащую два поля int, или есть лучший способ? Мне нужно передать id и температуру одним пакетом.

Код передатчика (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);
}

Код приемника (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;
}

ИЗМЕНИТЬ: Хорошо, после запуска sizeof(data) на обоих устройствах я заметил, что структуры имеют разный размер: 4 байта для arduino и 8 байт для малины. Так что переходите на малиновую сторону на

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

И это работает, но могу я спросить, почему int имеют разный размер на arduino и raspberry?

, 👍0


1 ответ


Лучший ответ:

4

Ваша проблема в том, что вы взаимодействуете между 8-битной и 32-битной архитектурой.

В 8-битной архитектуре int равен 16 битам. На 32-битной это 32 бита. Почему разница? Потому что "это". Так было всегда, начиная с зари C. Концепция int — это гибкая идея без фиксированного определенного размера — размер в значительной степени определяется архитектурой и компилятором. Хотя соглашения теперь диктуют, что int будет 16-битным в 8-битной системе и 32-битным в 32-битной системе.

Вы можете думать об этом как о целочисленном размере, равном ширине внутреннего регистра процессора, но с нижней границей 16 бит.

Именно поэтому существуют целочисленные типы с фиксированной шириной uint16_t и т. д., чтобы можно было обеспечить одинаковый размер данных на разных архитектурах.

Кстати, вы также должны знать о порядке байтов ваших систем. В вашем случае они оба "little endian", но "big" (и даже "средние") системы с порядком байтов также существуют. Это определяет, в каком порядке каждый байт целого числа (и других многобайтовых типов данных) хранится в памяти. Если вы отправите целое число из системы с прямым порядком байтов в систему с обратным порядком байтов и не примените к данным никаких преобразований для реверсирования байтов, значения будут совершенно неправильными.

,

Спасибо за такой исчерпывающий ответ, я знал о системах с прямым и обратным порядком байтов, но я никогда не думал о различиях в архитектурах, о которых вы упомянули. Теперь я думаю, что я получил этот следующий шаг, чтобы как-то справиться с шумом. Еще раз спасибо за хороший ответ, @StrudzonyWedrowiec

Если бы у меня была такая же проблема между atmega328p и esp8266, я пару часов ломал голову, прежде чем наткнулся на это, я бы не подумал об этом, хотя это имеет смысл! Спасибо!, @Sorin Grecu