Преобразование float в байт, от Arduino до Raspberry Pi i2c
Я пытаюсь отправить значение температуры с датчика DHT на raspberry pi через I2C. Как лучше всего это сделать?. Значение temp - это float, и я думаю, что должен преобразовать его в байт и отправить с помощью Wire.write() в малину, не так ли?. Прямо сейчас я отправляю байты из raspberry (с Python) в Arduino (C++).: Python:
from smbus import SMBus
import time
address = 0x8
bus = SMBus(1)
While True:
bus.write_byte(address, 4)
time.sleep(1)
print(bus.ready_byte(address))
Код Arduino:
#include <Wire.h>
#include <DHT.h>
...
void setup() {
dht.begin();
Wire.begin(0x8);
Wire.onReceive(receiveEvent);
}
void receiveEvent () {
float temp = dht1.readTemperature();
delay(1000);
byte tempByte[4] = {temp, 0, 0, 0};
Wire.write(tempByte[0]);
}
Таким образом, малина печатает 0.
Спасибо за любую помощь.
@Guille, 👍2
Обсуждение1 ответ
Лучший ответ:
Прежде всего, если вы хотите, чтобы Arduino отправлял данные в качестве ведомого устройства, он должен
делать это onRequest ()
, а не onReceive()
. Таким образом:
void setup() {
Wire.begin(0x08);
Wire.onRequest(handleRequest);
}
Далее, как указал Крисл в комментарии, вы не должны задерживаться в
обработчике onRequest
. Я бы пошел дальше и сказал, что вы
даже не должны вызывать dht1.readTemperature ()
, так как это может занять слишком много времени
в контексте прерывания. Вместо этого попросите основной цикл
периодически запрашивать датчик и всегда иметь в наличии последние данные:
volatile float temperature; // последнее действительное значение
void loop() {
float new_temperature = dht1.readTemperature();
noInterrupts();
temperature = new_temperature;
interrupts();
// ...
}
Обратите внимание, что последнее значение обновляется с отключенными прерываниями. Это делается для того, чтобы избежать гонки данных, которая может произойти, если Arduino получит запрос во время обновления значения. Обратите также внимание, что прерывания отключаются в течение очень короткого времени: как раз того времени, которое необходимо для обновления переменной.
Наконец, чтобы отправить данные, вы можете использовать версию Wire.write ()
, которая
принимает буфер произвольной длины:
void handleRequest() {
Wire.write((uint8_t *) &temperature, sizeof temperature);
}
Температура будет отправлена LSB-first, как float, отформатированный в соответствии с IEEE 754. Raspberry Pi должен быть в состоянии переварить его в том же формате.
Большое тебе спасибо, Эдгар!!!.
Сейчас я пытаюсь прочитать значение IEEE 754 из Raspberry Pi, используя Python3, но пока безуспешно. Я новичок в этих технологиях, так что извините за мое невежество. С Python 3 я читаю это из автобуса с:
float bus.read_byte_data(address, 4) # это возвращает массив типа: ["205","104"] при значении температуры 25.20
float bus.read_byte(адрес) # это возвращает случайные числа из 3 цифр, например 204, 104 и т. Д.
Не уверен, что Python3-правильный выбор здесь, может быть, вы могли бы порекомендовать что-то еще лучше. Еще раз спасибо., @Guille
Я не знаю Python, и здесь это не по теме. Если вы принудительно установили значение "температура" равным 25, вы должны прочитать байты 0x00, 0x00, 0xc8 и 0x41 в таком порядке. Как вы собираете их на ПК-это вопрос для другого сайта., @Edgar Bonet
- Ошибка в связи I2C Между Arduino и Raspberry Pi
- Отправка и получение различных типов данных через I2C в Arduino
- Путаница между SPI и I2C для SSD1306 OLED
- Отправка строки из RPi в Arduino - Рабочий код
- Ошибка при компиляции: 'class TwoWire' has no member named 'setClock'
- Как отправлять и получать данные с Arduino Uno на Arduino Mega с помощью I2C?
- Проблемные данные I2C к датчику GY955/BNO055 (Китай)
- Сбросить соединение I2C с arduino в качестве ведомого
Пожалуйста, удалите задержку из функции обратного вызова onReceive. Он выполняется внутри ISR. Задержка там не работает, @chrisl