通过 USB 从 Python 到 Arduino 的通信

Posted

技术标签:

【中文标题】通过 USB 从 Python 到 Arduino 的通信【英文标题】:Communication from Python to Arduino over USB 【发布时间】:2016-08-03 19:26:26 【问题描述】:

我正在尝试与 Arduino 进行交流。我使用 python 和 pyserial 通过 USB 进行通信。正如您在下面的源代码中看到的那样,我正在尝试向 Arduino 发送一个字节数组,其中包含两个 LED 条的一些信息。但是 Arduino 没有收到正确的信息。看起来字节数组已转换或信息丢失。

我整天都在寻找解决方案,但没有任何效果。希望你们能帮我解决这个问题。

提前致谢。

Python 代码

import sys
import serial
import time

HEADER_BYTE_1 = 0xBA
HEADER_BYTE_2 = 0xBE


def main():
    ser = serial.Serial('/dev/ttyUSB0', 57600)
    message =  'header': [None]*2, 'colors': [None]*6, 'checksum': 0x00 
    message['header'][0] = HEADER_BYTE_1
    message['header'][1] = HEADER_BYTE_2
    # first led
    message['colors'][0] = 0xFF
    message['colors'][1] = 0xFF
    message['colors'][2] = 0xFF

    # second led
    message['colors'][3] = 0x00
    message['colors'][4] = 0x00
    message['colors'][5] = 0x00

    # create checksum
    for color in message['colors']:
        for bit in bytes(color):
            message['checksum'] ^= bit

    # write message to arduino
    cmd = convert_message_to_protocol(message)
    ser.write(cmd)
    print(cmd)

    time.sleep(5)
    # read response from arduino
    while True:
        response = ser.readline()
        print(response)


def convert_message_to_protocol(message):
    cmd = bytearray()
    for header in message['header']:
        cmd.append(header)

    for color in message['colors']:
        cmd.append(color)

    cmd.append(message['checksum'])

    return cmd

if __name__ == '__main__':
    main()

Arduino 代码

const int kChannel1FirstPin = 3;
const int kChannel1SecondPin = 5;
const int kChannel1ThirdPin = 6;

const int kChannel2FirstPin = 9;
const int kChannel2SecondPin = 10;
const int kChannel2ThirdPin = 11;

// Protocol details (two header bytes, 6 value bytes, checksum)

const int kProtocolHeaderFirstByte = 0xBA;
const int kProtocolHeaderSecondByte = 0xBE;

const int kProtocolHeaderLength = 2;
const int kProtocolBodyLength = 6;
const int kProtocolChecksumLength = 1;

// Buffers and state

bool appearToHaveValidMessage;
byte receivedMessage[6];

void setup() 
  // set pins 2 through 13 as outputs:
  pinMode(kChannel1FirstPin, OUTPUT);
  pinMode(kChannel1SecondPin, OUTPUT);
  pinMode(kChannel1ThirdPin, OUTPUT);

  pinMode(kChannel2FirstPin, OUTPUT);
  pinMode(kChannel2SecondPin, OUTPUT);
  pinMode(kChannel2ThirdPin, OUTPUT);

  analogWrite(kChannel1FirstPin, 255);
  analogWrite(kChannel1SecondPin, 255);
  analogWrite(kChannel1ThirdPin, 255);

  analogWrite(kChannel2FirstPin, 255);
  analogWrite(kChannel2SecondPin, 255);
  analogWrite(kChannel2ThirdPin, 255);

  appearToHaveValidMessage = false;

  // initialize the serial communication:
  Serial.begin(57600);



void loop () 

  int availableBytes = Serial.available();

  Serial.println(availableBytes);

  if (!appearToHaveValidMessage) 
    // If we haven't found a header yet, look for one.
    if (availableBytes >= kProtocolHeaderLength) 
      Serial.println("right size");
      // Read then peek in case we're only one byte away from the header.
      byte firstByte = Serial.read();
      byte secondByte = Serial.peek();

      if (firstByte == kProtocolHeaderFirstByte &&
          secondByte == kProtocolHeaderSecondByte) 

          Serial.println("Right Header");
          // We have a valid header. We might have a valid message!
          appearToHaveValidMessage = true;

          // Read the second header byte out of the buffer and refresh the buffer count.
          Serial.read();
          availableBytes = Serial.available();
      
    
  

  if (availableBytes >= (kProtocolBodyLength + kProtocolChecksumLength) && appearToHaveValidMessage) 

    // Read in the body, calculating the checksum as we go.
    byte calculatedChecksum = 0;

    for (int i = 0; i < kProtocolBodyLength; i++) 
      receivedMessage[i] = Serial.read();
      calculatedChecksum ^= receivedMessage[i];
    

    byte receivedChecksum = Serial.read();

    if (receivedChecksum == calculatedChecksum) 
      // Hooray! Push the values to the output pins.

      analogWrite(kChannel1FirstPin, receivedMessage[0]);
      analogWrite(kChannel1SecondPin, receivedMessage[1]);
      analogWrite(kChannel1ThirdPin, receivedMessage[2]);

      analogWrite(kChannel2FirstPin, receivedMessage[3]);
      analogWrite(kChannel2SecondPin, receivedMessage[4]);
      analogWrite(kChannel2ThirdPin, receivedMessage[5]);


      Serial.print("OK");
      Serial.write(byte(10));

     else 

      Serial.print("FAIL");
      Serial.write(byte(10));
    

    appearToHaveValidMessage = false;
  

示例

Python 中生成的字节数:b'\xba\xbe\xff\xff\xff\x00\x00\x00\x00'

在 Arduino 上接收到的字节数:b'L\xc30\r\n'

【问题讨论】:

【参考方案1】:

将波特率更改为 9600 已修复通信

【讨论】:

以上是关于通过 USB 从 Python 到 Arduino 的通信的主要内容,如果未能解决你的问题,请参考以下文章

从 Arduino Yun 上的 USB 接口获取 MIDI 音符

无法通过 USB 向 Arduino 发送/接收数字来控制电机

通过串行更改值的计算机到 Arduino mega

将串行从 Raspberry 传递到 Arduino USB HID

Microsoft Visual C++ 2010 和 Arduino UNO 之间通过 USB 进行串行通信

串行 Mac OS X 不断冻结/锁定/消失 USB 到 Arduino