Отправка значений с плавающей запятой из Python в Arduino с использованием последовательной связи

Мне нужно отправить массив чисел с плавающей запятой из Python в Arduino Mega. Для этого я прочитал много источников [это это это это это] это] и еще много ссылок на то же самое, на что я ссылался. Но не в состоянии решить эту проблему.

Я попытался отправить углы в Arduino через python и вернуть эти значения в python для печати.

Ниже приведен код Python, в котором я пытаюсь отправить массив с именем angle и пытается распечатать значения, полученные от Arduino.

import cv2
import numpy as np
import serial
import struct
import time

ser = serial.Serial('COM3', 9600, timeout = 1)
time.sleep(2)
if(ser.isOpen() == False):
    ser.open()
print('com3 is open', ser.isOpen())   

angle = [120.2,154.2,14.25]
ser.write(struct.pack('>fff', 10.5,11.9,48.2)) # B for interger and f for float
#ser.write(struct.pack('>f', angle)) # B for interger and f for float


time.sleep(2)
ser.flush()


data = ser.readline()
data = str(data.decode("utf"))
print(data)

ser.close()

Ниже приведен код Arduino:

float f1; float f2; float f3; 

void setup() {
  // put your setup code here, to run once:
Serial.begin(9600);

Serial.println("Arduino is in parseFloat!");
}

void loop() {

  if (Serial.available() > 0)
  {
    d1 = Serial.parseFloat(); d2 = Serial.parseFloat(); d3 = Serial.parseFloat(); 

    ad = d1 +2.5;
    Serial.println(ad)
  }
delay(2000);
}

Ошибка, которую я получил, такова: Я не получил никаких ошибок или предупреждений, но также нет выходных данных для команд печати, как показано на рисунке ниже.

Мне нужна помощь, чтобы отправить значения в Arduino с помощью python.

, 👍1

Обсуждение

Похоже, вы отправляете двоичный файл вместо текста., @Edgar Bonet

Вы не даете Arduino время на перезагрузку после открытия последовательного порта и перед отправкой ему каких-либо данных..., @Majenko


1 ответ


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

2

Здесь происходят две вещи.

Прежде всего, если вы посмотрите метод readline() в Python, на который ссылается руководствопо PySerial, вы увидите следующее:

readline(size=- 1, /)

Прочитайте и верните одну строку из потока. Если указан размер, то будет считано не более байтов размера.
Для двоичных файлов в качестве разделителя строк всегда используется b'\n'; для текстовых файлов аргумент новой строки для функции open() может использоваться для выбора распознанных разделителей строк.

В вашей программе вы фактически отправляете более одной строки обратно на последовательный порт из Arduino. Первая строка - это кодированное в формате ASCII сообщение "Arduino находится в parseFloat!". Второй - это тестовый расчет с плавающей запятой. Если вы не учитываете тот факт, что ожидаете несколько "строк" от последовательного порта, вы не увидите тестовый расчет, потому что на самом деле вы его не читаете. Для закодированных данных в нем указано, что строка заканчивается символом '\n' /цифрой (10).

Попробуйте изменить "println" на "print" в вашей программе Arduino и добавить другое сообщение либо в настройках, либо в цикле. Запустите свою программу на Python. Что ты видишь? Теперь измените "печать" обратно на "println". Запустите свою программу на Python еще раз. Что вы видите сейчас?

Во-вторых, Эдгар Бонет указывает на вторую проблему. Метод write() в PySerial API требует, чтобы данные представляли собой массив байтов, но именно так вы их кодируете. Похоже, что последовательный класс Arduino ожидает байтовый массив в кодировке ASCII, а не байтовый массив с плавающей запятой (числа с плавающей запятой кодируются как число с плавающей запятой одинарной точности), которое вы отправляете.

Если вы измените свой код на что-то вроде этого (например):

angle = [120.2,154.2,14.25]
ser.write(str(angle).encode('utf-8'))

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

,

Удалив println, я успешно отправляю и получаю значения., @Naseeb Gill