Отправка числа с плавающей запятой из python в arduino
Я пытаюсь отправить число с плавающей запятой из скрипта Python в Arduino. Я не знаю, как это сделать, особенно питоническим способом.
Небольшое исследование привело меня к очень похожему вопросу: Как отправлять числа в Arduino UNO через Python 3 и COM порт модуля Я смутно понимаю, почему это будет работать для int, но не знаю, как это изменить.
1) В этом вопросе имеет смысл преобразовать в char, отправить, а затем преобразовать обратно в int путем приведения к Arduino, я не могу придумать, как это сделать для числа с плавающей запятой.
2) Почему они все равно конвертируются в Char?
3) Какой код мне запустить на arduino, чтобы вернуть это обратно в число с плавающей запятой?
4) Можно ли использовать побитовые операторы для чисел с плавающей запятой?
Я новичок в Python, а также в низкоуровневом программировании. Я также знаю, что python и низкий уровень не очень хорошо сочетаются. Я использую Linux, но в идеале мне нужно кроссплатформенное решение. Хотя я бы предпочел, чтобы это заработало, а потом не беспокоился о кроссплатформенности.
@Aaron, 👍0
2 ответа
Лучший ответ:
В этом вопросе имеет смысл преобразовать в 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)) {
...
Можно ли использовать побитовые операторы для чисел с плавающей запятой?
... Ну... нет... потому что после этого они не обязательно останутся действительными числами с плавающей запятой.
Числа с плавающей запятой (должны) храниться в формате 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++.
- Не удается получить данные из кода Python
- Невозможно правильно отобразить два значения с плавающей точкой из pyserial на ЖК-дисплее Arduino.
- Float печатается только 2 десятичных знака после запятой
- Не удается связаться с ардуино с помощью python (Windows)
- Последовательная связь Arduino с Python: отправка массива
- Построение графика на Python с использованием Tkinter Canvas
- Как отправить целое число через pyserial с Python на Arduino и получить тот же результат?
- Сброс последовательного порта Arduino в последовательном мониторе и Python
Спасибо за такой быстрый ответ, это именно то, что я хочу, но эта строка не работает: я не совсем уверен, что я здесь делаю неправильно, 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