Отправка числа с плавающей запятой из python в arduino

Я пытаюсь отправить число с плавающей запятой из скрипта Python в Arduino. Я не знаю, как это сделать, особенно питоническим способом.

Небольшое исследование привело меня к очень похожему вопросу: Как отправлять числа в Arduino UNO через Python 3 и COM порт модуля Я смутно понимаю, почему это будет работать для int, но не знаю, как это изменить.

1) В этом вопросе имеет смысл преобразовать в char, отправить, а затем преобразовать обратно в int путем приведения к Arduino, я не могу придумать, как это сделать для числа с плавающей запятой.

2) Почему они все равно конвертируются в Char?

3) Какой код мне запустить на arduino, чтобы вернуть это обратно в число с плавающей запятой?

4) Можно ли использовать побитовые операторы для чисел с плавающей запятой?

Я новичок в Python, а также в низкоуровневом программировании. Я также знаю, что python и низкий уровень не очень хорошо сочетаются. Я использую Linux, но в идеале мне нужно кроссплатформенное решение. Хотя я бы предпочел, чтобы это заработало, а потом не беспокоился о кроссплатформенности.

, 👍0


2 ответа


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

0

В этом вопросе имеет смысл преобразовать в char, отправить, а затем преобразовать обратно в int путем приведения к Arduino, я не могу придумать, как это сделать для числа с плавающей запятой.

Вместо спецификатора формата B для байта без знака используйте f для числа с плавающей запятой одинарной точности. AVR-GCC не поддерживает числа с двойной точностью, поэтому не беспокойтесь о d.

Почему они все равно конвертируются в Char?

Нет. Вы конвертируете его в байты (отсюда префикс b в представлении значения), чтобы последовательный протокол, ориентированный на байты, мог его передать. В Python 2.x str уже содержит байты, поэтому префикс не требуется.

Какой код мне запустить на Arduino, чтобы вернуть это обратно в число с плавающей запятой?

Используйте Serial.readBytes(), чтобы сбросить байты из последовательного соединения в переменную float.

float f;
 ...
if (Serial.readBytes((char*)&f, sizeof(f)) != sizeof(f)) {
   ...

Можно ли использовать побитовые операторы для чисел с плавающей запятой?

... Ну... нет... потому что после этого они не обязательно останутся действительными числами с плавающей запятой.

,

Спасибо за такой быстрый ответ, это именно то, что я хочу, но эта строка не работает: я не совсем уверен, что я здесь делаю неправильно, err msg: ser.write(struct.pack(@f,volt_out )) ^ SyntaxError: неверный синтаксис, @Aaron

Формат должен быть указан как строка. struct.pack('...', ...), @Ignacio Vazquez-Abrams

Спасибо, это работает :) Я изменил код стороны arduino while(!Serial.available()); поплавок ф; Serial.readBytes((char*)&f, sizeof(f)); оператор if показался мне немного избыточным в моей настройке, @Aaron


1

Числа с плавающей запятой (должны) храниться в формате IEEE 754.

Если вы просто записываете двоичные байты числа с плавающей запятой в последовательную строку, должна быть возможность распаковать их на другом конце.

Для этого (Arduino C/C++) создайте указатель из вашей переменной, приведя ее адрес к char*. Void*, вероятно, тоже подойдет.

 float my_value = 22.812;
 my_port.write((const char *)&my_value, sizeof(float)/*4*/);

И распаковка - есть несколько способов сделать это, но мне нравится:

 float incoming_value;
 unsigned char buffer[4];

 // Если мы прочитали достаточно байтов, распаковываем его
 if (my_serial.readBytes(buffer, sizeof(float)) == sizeof(float))
     memcpy(&incoming_value, buffer, sizeof(float));
 else
     // Ошибка ввода/вывода - нет данных, недостаточно байтов и т.д.
     incoming_value = 0

С другой стороны (python), байты лучше всего обрабатывать с помощью модуля struct. Это займется упаковкой и распаковкой для вас.

import struct
...

try:
    ieee754_data = my_serial.read(4)
    my_float = struct.unpack('f', ieee754_data)
catch:
    # Ошибка ввода/вывода или ненужные данные
    my_float = 0.0

И упаковка:

 ieee754_data = struct.pack('f', my_float)
 try:
     my_serial.write(ieee754_data)
 catch:
     pass #TODO - I/O Error

Еще одно замечание. Вы можете рассмотреть возможность использования двойных значений вместо чисел с плавающей запятой для большей точности. У чисел с плавающей запятой Python уже есть точность двойника C/C++.

,