Как прочитать структуру данных, отправленных последовательно из Arduino? - PullRequest
0 голосов
/ 19 февраля 2020

Я изо всех сил пытаюсь прочитать структуру двоичных данных с помощью Python3, отправляемого последовательно от Arduino Mega 2560.

Код Arduino:

char userInput;
bool ledState = false;

typedef struct 
{
  unsigned long  logTimeStart;
  unsigned long  frequencyOne;
  unsigned long  frequencyTwo;
  unsigned long  frequencyThree;
  unsigned long  frequencyFour;
  unsigned short int  revPowerOne;
  unsigned short int  revPowerTwo;
  unsigned short int  revPowerThree;
  unsigned short int  revPowerFour;
  unsigned short int  tempSensor; 
} SDLogger;

SDLogger dataLog;

void setup() 
{

  Serial.begin(9600);
  bitWrite(DDRB, 7, HIGH); // Set LED DDR high on port B, pin 7

  dataLog.logTimeStart = millis();
  dataLog.frequencyOne = 4000000000;       // PREDEFINED VALUES FOR TESTING
  dataLog.frequencyTwo = 4000000000;      
  dataLog.frequencyThree = 4000000000;
  dataLog.frequencyFour = 4000000000;
  dataLog.revPowerOne = 65000;             // PREDEFINED VALUES FOR TESTING
  dataLog.revPowerTwo = 65000;
  dataLog.revPowerThree = 65000;
  dataLog.revPowerFour = 65000;
  dataLog.tempSensor = 65000;

  Serial.println("<Arduino is ready>");
}

void loop() 
{
  checkForSerialMessage();
  delay(1000);
}

void checkForSerialMessage()
{
  Serial.println("checking serial...");
  if (Serial.available() > 0) 
  {
     userInput = Serial.read();

     if (userInput == 'a')
     {
      ledState = !ledState;
      bitWrite(PORTB, 7, ledState);
      Serial.println("led");    
     } 

     if (userInput == 'b')
     {
        Serial.write((byte*)&dataLog, sizeof(dataLog));
     }
  }
}

Я считаю, что размер структуры составляет 30 байтов. Моя цель состоит в том, чтобы Arduino периодически проверял буфер на наличие определенного c символа. Когда этот символ получен, Arduino отправляет определенную структуру данных моему интерфейсу python, который затем распаковывается и декодируется во что-то читаемое людьми. Я написал альтернативную команду, которая включает встроенный светодиод Arduino. Это было сделано, чтобы понять простое последовательное взаимодействие между программным обеспечением. Кажется, что светодиодный переключатель работает должным образом, но не команды struct.

Python Код

from tkinter import *
from struct import *
import serial
import time

ser = serial.Serial('COM5', baudrate=9600, timeout=1)
root = Tk() # root widget, this has to be first before any other widgets.

BINARY_STRFORMAT = "LLLLLHHHHH"         # Format to match arduino struct
print(calcsize(BINARY_STRFORMAT))       # RESULT IS 30

def toggleLED():
    ser.write(b'a')
    arduinoData = ser.readline().decode('ascii')  # readline functions will read until it sees a newline \n
                                                  #  .decode('ascii')
    print(arduinoData)

def toggleSerial():
    ser.write(b'b')
    arduinoData = ser.readline()
    print(arduinoData)
    unpacked = unpack(BINARY_STRFORMAT, arduinoData)


# in tkinter, everything is a widget:
header = Label(root, text="Read data from Arduino")
led_on = Button(root, text="led on", command=toggleLED)
read_serial = Button(root, text="enable data stream", command=toggleSerial)

# showing Label widget onto screen
header.pack()
led_on.pack()
read_serial.pack()


root.mainloop()

Когда я запускаю код python, я могу использовать свой элементарный tkinter GUI для переключения светодиода Arduino. Но когда я пытаюсь запросить структуру данных, я получаю структурную ошибку:

struct.error: unpack requires a buffer of 30 bytes

Я попытался прочитать документацию pySerial, чтобы посмотреть, смогу ли я улучшить способ получения моих последовательных данных, но не смог найти структурные ссылки. Я не понимаю, как структура отправляется / принимается и как ее следует читать в python.

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

1 Ответ

0 голосов
/ 19 февраля 2020

Обновление: благодаря @martineau и @Edward мы узнали, что Serial.println() записывает данные на тот же порт, который пытается передать / получить структуру данных. Это перекрытие мешало способности python GUI анализировать и декодировать двоичную структуру. Когда Serial.println() был удален, python GUI получил ожидаемую 30-байтовую структуру.

...