Последовательная связь Arduino с Python: отправка массива
Я немного новичок в Arduino и Python. Моя цель — отправить команды Arduino для запуска шагового двигателя. Мне нужно отправить массив, содержащий параметры. После консультации со многими более ранними сообщениями, такими как:
https://stackoverflow.com /questions/27639605/send-a-list-of-data-from-python-to-arduino-using-pyserial
Отправить несколько значений int из Python в Arduino с помощью pySerial
Я написал код для Arduino:
long incoming[3];
void setup() {
pinMode(13, OUTPUT);
Serial.begin(9600);
Serial.println("Ready");
}
void loop() {
if(Serial.available()) {
for (int i = 0; i < 3; i++) {
incoming[i] = Serial.read();
}
Serial.println(incoming[0]);
Serial.println(incoming[0]);
Serial.println(incoming[2]);
}
}
И код Python(2.7):
from time import sleep
import serial
import struct
ser = serial.Serial('COM6', 9600)
while True:
ser.write(struct.pack('>iii',2000,10,220))
print ser.readline()
sleep(.5)
Теперь перейдем к проблеме:
- Значения, напечатанные в оболочке Python, совершенно неверны, включая отрицательные значения.
- Если я использую >BBB вместо >iii, я получаю правильный результат, но не могу выйти за пределы 255, предела целого числа. Здесь также есть небольшая загвоздка: первые два набора дают отрицательные значения, а затем все становится хорошо.
- Кроме того, есть ли способ прервать запущенный цикл void?
Любая помощь приветствуется.
@kiran007, 👍2
Обсуждение2 ответа
Лучший ответ:
Если я использую >BBB вместо >iii... Это потому, что "B" - это байт. Таким образом, вы отправляете 3 байта:
struct.pack("BBB", 1, 2, 3)
\x01\x02\x03
"i" — это int и имеет размер 4, поэтому вы отправляете 4*3 = 12 байтов:
struct.pack("iii", 1, 2, 3)
\x01\x00\x00\x00\x02\x00\x00\x00\x03\x00\x00\x00
Serial.read()
считывает по 1 байту за раз, поэтому вам нужно прочитать 4 байта для каждого значения.
Вот функция для чтения 32-битного целого числа. Недостатки этого метода заключаются в том, что: а) он будет блокироваться до тех пор, пока не будут прочитаны 4 байта. И б) невозможно определить, были ли потеряны некоторые данные. Существуют более надежные способы отправки данных с помощью символов начала сообщения, конца сообщения и контрольной суммы. Кроме того, функция предполагает, что данные сначала отправляются с младшим разрядом. Но я просто приведу это здесь в качестве примера.
// Вспомогательный макрос для объединения 4 байтов
#define TO_INT32(a,b,c,d) (((d)<<24)|((c)<<16)|((b)<<8)|(a))
int32_t read_int()
{
uint32_t result[4];
for (int i = 0; i < 4; i++) {
// Ждем данных на порту
while (!Serial.available());
result[i] = Serial.read();
}
return TO_INT32(result[0], result[1], result[2], result[3]);
}
Можно гораздо проще отправить массив между Python и Arduino, используя взаимосовместимые библиотеки SerialTransfer.h и pySerialTransfer. Использование подобных библиотек обеспечивает надежную и надежную связь между Python и Arduino.
SerialTransfer.h устанавливается с помощью диспетчера библиотек Arduino IDE и содержит множество примеров. Пакет pySerialTransfer можно установить с помощью pip.
- Сброс последовательного порта Arduino в последовательном мониторе и Python
- Последовательная связь между python и arduino
- Почему нужно использовать latin-1 вместо utf-8 при использовании python с arduino?
- серийные данные портятся
- Как игнорировать значения мусора при последовательной связи между Arduino и Python
- В чем разница, когда ардуино был отключен от сети, и когда последовательный порт был закрыт?
- Отладка различного поведения последовательного приема/отправки между Uno и Mega
- Как исправить UnicodeDecodeError при использовании Serial.println
Это может помочь прояснить некоторые заблуждения: https://hackingmajenkoblog.wordpress.com/2016/02/01/reading-serial-on-the-arduino/, @Majenko