windows PySerial 不与 Arduino 交谈

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/8149628/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-15 18:28:50  来源:igfitidea点击:

PySerial not talking to Arduino

pythonwindowsserial-portarduinopyserial

提问by Matt Ellen

I have written some code to simulate some hardware I'm working with and uploaded it to the Arduino board. This code works. I know this, because I get the expected response from HyperTerminal.

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

However, when I try to connect using PySerial the connection does not error, but I get no response to the commands I send.

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

Why might this be?

为什么会这样?

Python code

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()

NB: the code on the Arduino sends back \r\nat the end of a response to a command.

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

HyperTerminal configuration:

超级终端配置:

COM4 configuration in HyperTerminal

超级终端中的 COM4 配置

Edit

编辑

I have found that if I increase the timeout to 10 seconds and add a sp.readline()before I send anything, then I get responses to both commands.

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

How long is the hardware handshake usually between PySerial and an Arduino or USB RS-232 ports?

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

采纳答案by ib.lundgren

Can not verify this but it could be that you try and read before there is any data there, thus you get no reply back.

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

To test this you could try and poll until there is data

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

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

Edit

编辑

The Arduino will reset when you open a serial connection, any data written during bootup will likely go to bit heaven. You could use a sleep for 2 seconds (could not find the exact time it takes, will likely vary anyway) before you do any reads/writes.

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

Alternatively you could write to it until you get a response back, after you get a return you start doing "real work".

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

回答by Matt Ellen

For the time being I am using a workaround. I have set the timeoutto 1.5 seconds and put a readlinecall in before the first write.

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

So now the Python code looks like:

所以现在 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()

回答by Memphis

I've also encountered this problem recently and here's my solution:

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

import serial

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

Turns out this will successfully reset the Arduino board.

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

回答by nvd

Add a delay after you open the port as Arduino is reset and the bootloader starts listening for new firmware. If something is sent at that moment, the MCU remains stuck in bootloader. The delay causes the bootloader to timeout.

在您打开端口后添加延迟,因为 Arduino 被重置并且引导加载程序开始侦听新固件。如果在那一刻发送了一些东西,MCU 仍然停留在引导加载程序中。延迟会导致引导加载程序超时。

sp.open()
time.sleep(2) # 2 seconds or possibly a bit less
sp.write("blahblah")

回答by P_B

You can easily and robustly connect and communicate between Python and Arduino boards using the compatible libraries SerialTransfer.hand pySerialTransfer. These libraries automatically packetize and parse serial packets using start/end markers, cyclic redundancy checking, consistent overhead byte stuffing, and dynamic payload lengths.

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

SerialTransfer.h is installable through the Arduino IDE's Libraries Manager and pySerialTrasnfer is pip-installable.

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

Example Python:

示例 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()

Example Arduino:

示例 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);
  }
}