使用pySeri等待Arduino自动重置

2024-06-01 09:51:34 发布

您现在位置:Python中文网/ 问答频道 /正文

我试图在Linux上用一个非常简单的代码(为了展示问题)来读取Arduino板上的行。

Python代码:

# arduino.py
import serial
arduino = serial.Serial('/dev/ttyACM0')

with arduino:
    while True:
        print(arduino.readline())

Arduino代码:

// simpleWrite.ino
long ii = 0;

void setup() {
  // initialize serial communications at 9600 bps:
  Serial.begin(9600);
}

void loop() {
  Serial.println(ii);
  ii++;
}

当串行连接打开时,板自动复位,第一个字节可能是垃圾。一两秒钟后一切正常。

这是一个典型的输出:

$ python arduino.py 
b'09\r\n'
b'540\r\n'
b'541\r\n'
b'542\r\n'
b'543\r\n'
b'544\r\n'
b'545\r\n'
b'546\r\n'
b'547\r\n'
b'548\r\n'
b'549\r\n'
b'550\r\n'
b'551\r\n'
b'552\r\n'
b'553\r\n'
b'554\r\n'
b'555\r\n'
b'556\r\n'
b'557\r\n'
b'55\xfe0\r\n'  # <---- Here the board restarted
b'1\r\n'
b'2\r\n'
b'3\r\n'
b'4\r\n'
b'5\r\n'
b'6\r\n'
b'7\r\n'
b'8\r\n'
b'9\r\n'
b'10\r\n'

但是,我看到ArduinoIDE串行监视器没有这个问题,并且正确地显示了一个延迟(重新启动时),然后打印从第一个开始的所有行。

有没有办法用pySerial在Python中模拟这种行为?也就是说,在重新启动之前放弃所有输出,然后就不做其他操作了?也许是通过一些低级的功能?

我试着看看relevant Arduino source code,但我不懂Java,也没用。

注:当然,我可以睡三秒钟,扔掉所有东西,从那里开始,但我可能也会扔掉一些第一行。

编辑:显然,Windows上不存在此问题,也不需要接受的解决方案。


Tags: 代码pydevimporttruelinuxwithserial
4条回答

我知道这是一个老问题,但希望这能对其他有同样问题的人有用。

我遇到了一个问题,如果我使用9600以外的任何波特率,python中的串行连接将一直收到乱码,即使在arduino上正确设置了Serial.begin(...),并且与python代码中使用的值匹配。 我在网上看到,引导加载程序或看门狗可能需要一秒钟的时间来加载(当电路板通电时),它可能会以某种特定的波特率通过串行方式发送数据(可能用于芯片编程)。我猜这就是在python中扰乱串行通信的原因。

这段代码给了我可靠的结果:

import serial
from time import sleep
arduino = serial.Serial('/dev/ttyACM0') # dummy connection to receive all the watchdog gibberish (unplug + replug) and properly reset the arduino
with arduino: # the reset part is actually optional but the sleep is nice to have either way.
  arduino.setDTR(False)
  sleep(1)
  arduino.flushInput()
  arduino.setDTR(True)

# reopen the serial, but this time with proper baudrate. This is the correct and working connection.
arduino = serial.Serial('/dev/ttyACM0',baudrate=57600)

with arduino:
    while True:
        print(arduino.readline())

arduino端用于测试的代码非常简单:

void setup() {
  Serial.begin(57600);
  Serial.println("setup");
}

void loop() {
  Serial.println("hello");
  delay(200);
}

您需要设置var,请尝试:

unsigned long ii = 0;

但请注意,这是一个32位的var,当它满了时,会导致溢出并重新启动。 为我工作。 根据@Kobi K的建议,添加最小延迟时间,对于9600 boud的加载实际数据,每个字符的持续时间为2 ms

    void loop() {

      Serial.println(ii);
      delay(20);
      ii++;
    }

在python中,您需要声明这样的Pyserial:

arduino=serial.Serial('/dev/ttyACM0',9600,timeout=0.0001)

希望这对你有帮助

Arduino IDE的监视器开关是连接时端口的指定DTR管脚。这种切换会导致Arduino重置。注意,在监视器打开串行端口并准备好接收数据后,DTR将被切换。在您的情况下,下面的示例也应该这样做。

Import serial

arduino = serial.Serial('/dev/ttyS0',
                     baudrate=9600,
                     bytesize=serial.EIGHTBITS,
                     parity=serial.PARITY_NONE,
                     stopbits=serial.STOPBITS_ONE,
                     timeout=1,
                     xonxoff=0,
                     rtscts=0
                     )
# Toggle DTR to reset Arduino
arduino.setDTR(False)
sleep(1)
# toss any data already received, see
# http://pyserial.sourceforge.net/pyserial_api.html#serial.Serial.flushInput
arduino.flushInput()
arduino.setDTR(True)

with arduino:
    while True:
        print(arduino.readline())

我也要加上称赞的DTR的阿杜伊诺与AVR的使用内置USB,如莱昂诺阿多,埃斯波拉等。setup()应具有以下时间,以等待主机打开USB。

void setup() {
  //Initialize serial and wait for port to open:
  Serial.begin(9600);
  while (!Serial) {
    ; // wait for serial port to connect. Needed for Leonardo only
  }
}

这对FTDI的UNO等没有影响。

我知道这是一个老问题,但希望这能对其他有同样问题的人有用。

我遇到了一个问题,如果我使用9600以外的任何波特率,python中的串行连接就会一直收到乱码,即使Serial.begin(...)在arduino上正确设置并与python代码中使用的值匹配。 我在网上看到,引导加载程序或看门狗可能需要一秒钟的时间来加载(当电路板通电时),它可能会以某种特定的波特率通过串行方式发送数据(可能用于芯片编程)。我猜这就是在python中扰乱串行通信的原因。

这段代码给了我可靠的结果:

import serial
from time import sleep
arduino = serial.Serial('/dev/ttyACM0') # dummy connection to receive all the watchdog gibberish (unplug + replug) and properly reset the arduino
with arduino: # the reset part is actually optional but the sleep is nice to have either way.
  arduino.setDTR(False)
  sleep(1)
  arduino.flushInput()
  arduino.setDTR(True)

# reopen the serial, but this time with proper baudrate. This is the correct and working connection.
arduino = serial.Serial('/dev/ttyACM0',baudrate=57600)

with arduino:
    while True:
        print(arduino.readline())

arduino端用于测试的代码非常简单:

void setup() {
  Serial.begin(57600);
  Serial.println("setup");
}

void loop() {
  Serial.println("hello");
  delay(200);
}

相关问题 更多 >