Как восстановить структуру в python из списка чисел pyserialtransfer - PullRequest
2 голосов
/ 22 апреля 2020

Я пытаюсь установить двусторонний обмен данными между моим ноутбуком и моим Arduino, передавая общую структуру туда-сюда, но у меня возникают проблемы с распаковкой байтов, возвращенных из Arduino. Используя pySerialTransfer, кажется, rxBuff возвращает список чисел, которые я не могу понять, как преобразовать в байтовую строку для struct.unpack для рендеринга в числа, с которых я начал.

В настоящее время Код Arduino просто получает данные и выплевывает их обратно, без каких-либо преобразований или действий на стороне Arduino. Вот мой код Arduino:

#include "SerialTransfer.h"

SerialTransfer myTransfer;

struct POSITION {
  long id;
  float azimuth;
  float altitude;
} position;


void setup()
{
  Serial.begin(9600);
  myTransfer.begin(Serial);
}

void loop()
{
  if(myTransfer.available())
  {

    myTransfer.rxObj(position, sizeof(position));

    myTransfer.txObj(position, sizeof(position));
    myTransfer.sendData(sizeof(position));

  }
  else if(myTransfer.status < 0)
  {
    Serial.print("ERROR: ");

    if(myTransfer.status == -1)
      Serial.println(F("CRC_ERROR"));
    else if(myTransfer.status == -2)
      Serial.println(F("PAYLOAD_ERROR"));
    else if(myTransfer.status == -3)
      Serial.println(F("STOP_BYTE_ERROR"));
  }
}

И мой код python:

import time
import struct
from pySerialTransfer import pySerialTransfer


def StuffObject(txfer_obj, val, format_string, object_byte_size, start_pos=0):
  """Insert an object into pySerialtxfer TX buffer starting at the specified index.

  Args:
    txfer_obj: txfer - Transfer class instance to communicate over serial
    val: value to be inserted into TX buffer
    format_string: string used with struct.pack to pack the val
    object_byte_size: integer number of bytes of the object to pack
    start_pos: index of the last byte of the float in the TX buffer + 1

  Returns:
    start_pos for next object
  """
  val_bytes = struct.pack(format_string, *val)
  for index in range(object_byte_size):
    txfer_obj.txBuff[index + start_pos] = val_bytes[index]
  return object_byte_size + start_pos


if __name__ == '__main__':
  try:
    link = pySerialTransfer.SerialTransfer('/dev/cu.usbmodem14201', baud=9600)

    link.open()
    time.sleep(2) # allow some time for the Arduino to completely reset
    base = time.time()

    while True:
      time.sleep(0.2)

      sent = (4, 1.2, 2.5)
      format_string = 'iff'
      format_size = 4+4+4
      StuffObject(link, sent, format_string, format_size, start_pos=0)
      link.send(format_size)

      start_time = time.time()
      elapsed_time = 0
      while not link.available() and elapsed_time < 2:
        if link.status < 0:
          print('ERROR: {}'.format(link.status))
        else:
          print('.', end='')
        elapsed_time = time.time()-start_time
      print()

      response =  link.rxBuff[:link.bytesRead]
      print(response)
      response = struct.unpack(format_string, response)

      print('SENT: %s' % str(sent))
      print('RCVD: %s' % str(response))
      print(' ')

  except KeyboardInterrupt:
    link.close()

Когда я запускаю код python, я получаю следующую ошибку:

Traceback (most recent call last):
  File "double_float.py", line 54, in <module>
    response = struct.unpack(format_string, response)
TypeError: a bytes-like object is required, not 'list'

Но перед самой ошибкой я печатаю ответ: [4, 0, 0, 0, 154, 153, 153, 63, 0, 0, 32, 64].

Как мне преобразовать этот список во что-то, что struct.unpack может использовать? Или как мне распаковать этот список цифр c напрямую? Большое спасибо!

1 Ответ

0 голосов
/ 22 апреля 2020

Это то, что вы ищете:

import struct
data = [4, 0, 0, 0, 154, 153, 153, 63, 0, 0, 32, 64]
binary_str = bytearray(data)
result = struct.unpack("<lff", binary_str)
print(result)

Вывод

(4, 1.2000000476837158, 2.5)
...