Неверные значения, поступающие от Arduino в RPi по последовательной связи
Я пытаюсь записать четыре значения, относящиеся к энергии (ток, мощность, энергия и пиковый спрос), с помощью программного обеспечения, подключенного от моего Arduino UNO к моему Raspberry Pi 4. Однако происходят две вещи:
Все значения должны быть разными, но они выводятся на терминал RPi так, как будто они идентичны.
Кажется, что значения, которые я пишу, сливаются вместе (?), создавая бессмысленное значение. Например, если значения, которые я отправляю, равны 0,24, 28, 0,05 и 71, они отображаются в терминале RPI следующим образом:
Ток: 54543878
Мощность: 54543878
Энергия: 54543878
Пиковая мощность: 54543878
Это фрагмент моего кода Arduino, который записывается в последовательное соединение Bluetooth (использует HC-06):
bluetoothSerial.write(RMSCurrent);
bluetoothSerial.write(RMSPower);
bluetoothSerial.write(kilos);
bluetoothSerial.write(peakPower);
Это фрагмент скрипта Python, который его получает:
while 1:
try:
received_data = bluetoothSocket.recv(1024)
RMSCurrent = int.from_bytes(received_data,byteorder='big')
RMSPower = int.from_bytes(received_data,byteorder='big')
kilos = int.from_bytes(received_data,byteorder='big')
peakPower = int.from_bytes(received_data,byteorder='big')
print("Current (A): %d" % RMSCurrent)
print("Power (W): %d" % RMSPower)
print("Energy (kWh): %d" % kilos)
print("Peak Demand: %d" % peakPower)
except KeyboardInterrupt:
print("keyboard interrupt detected")
break
bluetoothSocket.close()
У кого-нибудь есть какие-нибудь идеи о том, что происходит? Два моих значения являются плавающими, а два-целыми числами. Я пытался исправить это в течение последних 12 часов, но безрезультатно.
@phosphorescent, 👍1
Обсуждение1 ответ
Вы избавите себя от многих головных болей, отправив данные в формате ASCII вместо двоичного кода:
bluetoothSerial.print("RMSCurrent: ");
bluetoothSerial.println(RMSCurrent);
Конечно, затем вам придется проанализировать поток данных на стороне Python .
Если вы действительно хотите отправить двоичные данные, то имейте в виду, что функция записи()
используемый вами метод предназначен для отправки отдельных байтов. Каждое число
, которое вы записываете ()
, преобразуется в целое число (усекается, если оно с плавающей точкой),
уменьшается по модулю 256 до диапазона [0, 255], а затем отправляется в виде одного
байта. В этом процессе вы можете потерять довольно много информации.
Чтобы отправить двоичный объект размером больше байта, необходимо использовать перегрузку
функции записи ()
, которая принимает как указатель (адрес объекта), так и
количество байтов для отправки. Например:
bluetoothSerial.write((uint8_t *) &RMSCurrent, sizeof RMSCurrent);
Но тогда вы должны знать, что некоторые числовые типы не имеют одинакового двоичного представления на Arduino и на Pi. Например:
- значение
int
равно 2 байтам на Arduino и 4 байтам на Pi двойной
размер равен 4 байтам на Arduino и 8 байтам на Pi
Я рекомендую вам использовать только целочисленные типы фиксированного размера (uint16_t
и такие)
и с плавающей
точкой.
Кроме того, имейте в виду, что Arduino является маломощным, как и Pi, и в отличие от того, что в настоящее время предполагает ваш код Python.
О, и последовательная связь не имеет понятия о пакетах данных. Если при запуске программы на Python в последовательном буфере окажется какое-то оставшееся дерьмо , оно выйдет из синхронизации с Arduino, и вы будете читать только мусор. Есть способы обойти эту проблему (поиск “кадрирования пакетов”), но они добавляют довольно много сложности.
Как я уже сказал, вы избавите себя от многих головных болей, отправив данные в формате ASCII вместо двоичного кода.
- SoftwareSerial читается до тех пор, пока не станет пустым, работает только с задержкой
- Возможно ли использование двух модулей с последовательным интерфейсом на одном Arduino Uno?
- Как заставить Arduino печатать на Arduino IDE моего Mac через Bluetooth?
- Можно ли измерить скорость акселерометром? Насколько точно?
- AT-команда не отвечает на последовательный монитор
- Получить данные с сайта с помощью ESP8266 с помощью AT-команд
- Как отправить команду AT на sim800l с помощью SoftwareSerial
- SIM800L не регистрируется в сети
`печать на терминале RPi, как будто они идентичны"... почему ты удивляешься? ... похоже, что вы устанавливаете для всех четырех одно и то же значение .... вместо этого выведите значение "received_data"., @jsotola
@jsotola Я получаю шестнадцатеричный код ASCII при печати received_data. Я думаю, я просто не уверен, как проанализировать значения, которые я хочу получить от этого, и назначить их четырем различным переменным., @phosphorescent
0.24
не является int. Ваш код python ожидает только int (и считывает первые байты received_data четыре раза)., @Mat