8

我已经编写了一些代码来模拟我正在使用的一些硬件并将其上传到 Arduino 板上。此代码有效。我知道这一点,因为我得到了超级终端的预期响应。

但是,当我尝试使用 PySerial 连接时,连接不会出错,但我发送的命令没有得到响应。

为什么会这样?

Python代码

import serial

def main():
    sp = serial.Serial()
    sp.port = 'COM4'
    sp.baudrate = 19200
    sp.parity = serial.PARITY_NONE
    sp.bytesize = serial.EIGHTBITS
    sp.stopbits = serial.STOPBITS_ONE
    sp.timeout = 0.5
    sp.xonxoff = False
    sp.rtscts = False
    sp.dsrdtr = False

    sp.open()

    sp.write("GV\r\n".encode('ascii'))
    value = sp.readline()
    print value
    sp.write("GI\r\n".encode('ascii'))
    value = sp.readline()
    print value

    sp.close()
 
if __name__ == "__main__":
    main()

注意:Arduino 上的代码在对\r\n命令的响应结束时发回。

超级终端配置:

超级终端中的 COM4 配置

编辑

我发现如果我将超时时间增加到 10 秒并sp.readline()在发送任何内容之前添加一个,那么我会得到对这两个命令的响应。

PySerial 和 Arduino 或 USB RS-232 端口之间的硬件握手通常需要多长时间?

4

5 回答 5

5

无法验证这一点,但可能是您在那里有任何数据之前尝试阅读,因此您没有得到回复。

要对此进行测试,您可以尝试进行轮询,直到有数据

value = None
while not value:
   value = sp.readline()
print value

编辑

当您打开串行连接时,Arduino 将重置,在启动期间写入的任何数据都可能会进入比特天堂。在进行任何读/写之前,您可以使用睡眠 2 秒(找不到确切的时间,无论如何可能会有所不同)。

或者,您可以写信给它,直到您收到回复,在您收到回复后,您开始做“真正的工作”。

于 2011-11-16T10:40:55.047 回答
3

目前我正在使用一种解决方法。我已将时间设置timeout为 1.5 秒,并readline在第一次写入之前拨打电话。

所以现在 Python 代码看起来像:

import serial

def main():
    sp = serial.Serial()
    sp.port = 'COM4'
    sp.baudrate = 19200
    sp.parity = serial.PARITY_NONE
    sp.bytesize = serial.EIGHTBITS
    sp.stopbits = serial.STOPBITS_ONE
    sp.timeout = 1.5 #1.5 to give the hardware handshake time to happen
    sp.xonxoff = False
    sp.rtscts = False
    sp.dsrdtr = False

    sp.open()

    sp.readline() #to give the hardware handshake time to happen

    sp.write("GV\r\n".encode('ascii'))
    value = sp.readline()
    print value
    sp.write("GI\r\n".encode('ascii'))
    value = sp.readline()
    print value

    sp.close()

if __name__ == "__main__":
    main()
于 2011-11-16T16:52:24.907 回答
2

我最近也遇到了这个问题,这是我的解决方案:

import serial

ser = serial.Serial(4, timeout=2)
ser.setRTS(True)
ser.setRTS(False)
while 1:
    line = ser.readline()
    print(line)
ser.close

事实证明,这将成功重置 Arduino 板。

于 2012-07-04T02:37:27.360 回答
1

在您打开端口后添加延迟,因为 Arduino 已重置并且引导加载程序开始侦听新固件。如果此时发送了某些内容,则 MCU 仍停留在引导加载程序中。延迟会导致引导加载程序超时。

sp.open()
time.sleep(2) # 2 seconds or possibly a bit less
sp.write("blahblah")
于 2016-08-16T13:24:23.737 回答
0

您可以使用兼容的库SerialTransfer.hpySerialTransfer在 Python 和 Arduino 板之间轻松、可靠地连接和通信。这些库使用开始/结束标记、循环冗余检查、一致的开销字节填充和动态有效负载长度自动打包和解析串行数据包。

SerialTransfer.h 可通过 Arduino IDE 的库管理器安装,pySerialTrasnfer 可通过 pip 安装。

示例 Python:

from pySerialTransfer import pySerialTransfer as txfer

if __name__ == '__main__':
    try:
        link = txfer.SerialTransfer('COM13')

        link.txBuff[0] = 'h'
        link.txBuff[1] = 'i'
        link.txBuff[2] = '\n'

        link.send(3)

        while not link.available():
            if link.status < 0:
                print('ERROR: {}'.format(link.status))

        print('Response received:')

        response = ''
        for index in range(link.bytesRead):
            response += chr(link.rxBuff[index])

        print(response)
        link.close()

    except KeyboardInterrupt:
        link.close()

示例 Arduino:

#include "SerialTransfer.h"
#include <SoftwareSerial.h>


SoftwareSerial mySerial(2, 3); // RX, TX
SerialTransfer myTransfer;


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

void loop()
{
  myTransfer.txBuff[0] = 'h';
  myTransfer.txBuff[1] = 'i';
  myTransfer.txBuff[2] = '\n';

  myTransfer.sendData(3);
  delay(100);

  if(myTransfer.available())
  {
    Serial.println("New Data");
    for(byte i = 0; i < myTransfer.bytesRead; i++)
      Serial.write(myTransfer.rxBuff[i]);
    Serial.println();
  }
  else if(myTransfer.status < 0)
  {
    Serial.print("ERROR: ");
    Serial.println(myTransfer.status);
  }
}
于 2020-02-10T00:07:48.463 回答