Отправка структуры данных с 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?
1 ответ
Лучший ответ:
Ваша проблема в том, что вы взаимодействуете между 8-битной и 32-битной архитектурой.
В 8-битной архитектуре int
равен 16 битам. На 32-битной это 32 бита. Почему разница? Потому что "это". Так было всегда, начиная с зари C. Концепция int
— это гибкая идея без фиксированного определенного размера — размер в значительной степени определяется архитектурой и компилятором. Хотя соглашения теперь диктуют, что int
будет 16-битным в 8-битной системе и 32-битным в 32-битной системе.
Вы можете думать об этом как о целочисленном размере, равном ширине внутреннего регистра процессора, но с нижней границей 16 бит.
Именно поэтому существуют целочисленные типы с фиксированной шириной uint16_t
и т. д., чтобы можно было обеспечить одинаковый размер данных на разных архитектурах.
Кстати, вы также должны знать о порядке байтов ваших систем. В вашем случае они оба "little endian", но "big" (и даже "средние") системы с порядком байтов также существуют. Это определяет, в каком порядке каждый байт целого числа (и других многобайтовых типов данных) хранится в памяти. Если вы отправите целое число из системы с прямым порядком байтов в систему с обратным порядком байтов и не примените к данным никаких преобразований для реверсирования байтов, значения будут совершенно неправильными.
- Как автоматически сбросить nrf24l01+ с кодом?
- Подключение Arduino Nano к Raspberry Pi Zero
- Как автоматически сбросить модуль NRF24L01
- Питание Arduino Mega 2560 от Raspberry Pi Usb
- Ошибка в связи I2C Между Arduino и Raspberry Pi
- Использование аналогового входа для чтения кнопки
- Преобразование строки в массив символов
- Реализовать связь Visible Light с помощью Arduino
Спасибо за такой исчерпывающий ответ, я знал о системах с прямым и обратным порядком байтов, но я никогда не думал о различиях в архитектурах, о которых вы упомянули. Теперь я думаю, что я получил этот следующий шаг, чтобы как-то справиться с шумом. Еще раз спасибо за хороший ответ, @StrudzonyWedrowiec
Если бы у меня была такая же проблема между atmega328p и esp8266, я пару часов ломал голову, прежде чем наткнулся на это, я бы не подумал об этом, хотя это имеет смысл! Спасибо!, @Sorin Grecu