Последовательная связь 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)

Теперь перейдем к проблеме:

  1. Значения, напечатанные в оболочке Python, совершенно неверны, включая отрицательные значения.
  2. Если я использую >BBB вместо >iii, я получаю правильный результат, но не могу выйти за пределы 255, предела целого числа. Здесь также есть небольшая загвоздка: первые два набора дают отрицательные значения, а затем все становится хорошо.
  3. Кроме того, есть ли способ прервать запущенный цикл void?

Любая помощь приветствуется.

, 👍2

Обсуждение

Это может помочь прояснить некоторые заблуждения: https://hackingmajenkoblog.wordpress.com/2016/02/01/reading-serial-on-the-arduino/, @Majenko


2 ответа


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

6

Если я использую >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]);
}
,

1

Можно гораздо проще отправить массив между Python и Arduino, используя взаимосовместимые библиотеки SerialTransfer.h и pySerialTransfer. Использование подобных библиотек обеспечивает надежную и надежную связь между Python и Arduino.

SerialTransfer.h устанавливается с помощью диспетчера библиотек Arduino IDE и содержит множество примеров. Пакет pySerialTransfer можно установить с помощью pip.

,