Неверные значения, поступающие от Arduino в RPi по последовательной связи

Я пытаюсь записать четыре значения, относящиеся к энергии (ток, мощность, энергия и пиковый спрос), с помощью программного обеспечения, подключенного от моего Arduino UNO к моему Raspberry Pi 4. Однако происходят две вещи:

  1. Все значения должны быть разными, но они выводятся на терминал RPi так, как будто они идентичны.

  2. Кажется, что значения, которые я пишу, сливаются вместе (?), создавая бессмысленное значение. Например, если значения, которые я отправляю, равны 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 часов, но безрезультатно.

, 👍1

Обсуждение

`печать на терминале RPi, как будто они идентичны"... почему ты удивляешься? ... похоже, что вы устанавливаете для всех четырех одно и то же значение .... вместо этого выведите значение "received_data"., @jsotola

@jsotola Я получаю шестнадцатеричный код ASCII при печати received_data. Я думаю, я просто не уверен, как проанализировать значения, которые я хочу получить от этого, и назначить их четырем различным переменным., @phosphorescent

0.24 не является int. Ваш код python ожидает только int (и считывает первые байты received_data четыре раза)., @Mat


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 вместо двоичного кода.

,