14

我正在尝试使用 pyserial 将数据发送到 arduino。但是当我打开 COM 端口时,它会将 DTR 设置为低电平并重置电路板。但是,我有我的 arduino 代码设置,因此我必须通过按住两个按钮 1 秒钟将其置于串行接收模式。如果可能的话,我宁愿不必在 arduino 启动时进行串行输入。

显然,您可以修改 serialWin32.py 文件,更改内容为:

self._dtrState = win32.DTR_CONTROL_ENABLE

至:

self._dtrState = win32.DTR_CONTROL_DISABLE

但是,有没有办法直接在我的 python 脚本中禁用它?我还需要为所有系统执行此操作。我宁愿不强迫人们改变他们的基本串行配置只是为了使用这个脚本。

串口打开如下:

 com = serial.Serial(port, baud, timeout=1);

更新:最后我找到了一个适合我的设置的解决方案。由于我不需要一直做串行数据,只有当我将设备置于串行接收模式时,我才找到一种方法来禁用 arduino 本身的串行连接重置。

许多帖子都说您可以通过在 5V 和复位之间放置一个 ~100 欧姆的电阻来禁用 DTR 复位。但我不希望这成为永久性的事情。所以,我在 PD5 和复位之间放置了一个电阻。然后,在软件中:

void setup() {
    //.......
    DDRD &= ~(_BV(PD5)); //Set PD5 as input initially
    PORTD |= (_BV(PD5)); //Set high
    //.......
}

inline void setResetDisable(bool state)
{
  if(state)
    DDRD |= (_BV(PD5)); //Set PD5 as output to put 5V on reset line
  else
    DDRD &= ~(_BV(PD5)); //set back to input mode
}

所以现在,当我想处于串行模式时,我调用 setResetDisable(true),它会在 100 欧姆电阻和复位引脚上引发 5V,防止 DTR 将其拉低并重置芯片:) 然后我只需调用 setResetDisable(false ) 当我离开串行模式时,芯片可以正常编程。

4

5 回答 5

15

应该能够在打开端口之前禁用 DTR,如下所示:

com = serial.Serial()
com.port = port
com.baudrate = baud
com.timeout = 1
com.setDTR(False)
com.open()

但是,在 Windows 上当前版本的 pyserial (2.6) 上这样做会引发以下异常:

..., line 315, in setDTR
ValueError: Attempting to use a port that is already open

这似乎是一个错误,已在 2011 年 12 月 29 日的最新版本源 SVN 修订版 445 中修复(请参阅http://pyserial.svn.sourceforge.net/viewvc/pyserial/trunk/pyserial/serial/serialwin32。 py?view=log ) 注释:

在 Win32 上打开之前允许 setRTS、setDTR(设置初始状态)、文档更新

看起来它可能刚刚错过了 2.6 版本(2011 年 11 月 2 日上传,参见:https ://pypi.python.org/pypi/pyserial )。

此外,查看setDTR()POSIX 的当前实现(在serialposix.py中)看起来这个错误没有修复,如果端口未打开,则会引发异常,因此跨平台解决方案看起来不太可能。

于 2013-03-18T14:21:17.013 回答
6

禁用 DTR 对我不起作用:
ser.dtr = None
(Linux 4.4.0 x86_64 / Python 2.7.12 / PySerial 3.4)

但这有效:

import serial
import termios

port = '/dev/ttyACM0'
f = open(port)
attrs = termios.tcgetattr(f)
attrs[2] = attrs[2] & ~termios.HUPCL
termios.tcsetattr(f, termios.TCSAFLUSH, attrs)
f.close()
se = serial.Serial()
se.baudrate = 115200
se.port = port
print 'dtr =', se.dtr
se.open()

我在这里找到了。

于 2017-08-03T04:49:05.453 回答
2

您描述的方法似乎是我所见过的解决此问题的最常见方法-因此我怀疑没有更简单的基于软件的解决方案。您当然可以使用手动更改 DTR 线的状态ser.setDTR(level)- 但是我没有在 Arduino 自动重置的情况下专门尝试过这个,我怀疑即使在打开串行端口后立即切换线也可能不够快防止复位。

我可以看到您可以使用的其他选项是防止在硬件中自动重置 Arduino(请参见此处),或者稍微更改您的代码,以便您允许 Arduino 在最初建立串行连接后重新启动,然后当您手动触发串行接收模式从 Arduino 发送初始信号以表明它现在已准备好接收数据。或者,您可以在脚本中包含 pySerial 库的修改版本。

于 2013-03-18T13:37:26.477 回答
0

这是一个老话题,但我现在正在开发一个将串行数据发送到 arduino 的程序。这是对我来说可靠的线路:

ser = serial.Serial(port = 'COM4', baudrate = 115200, timeout = 0.1, dsrdtr=None)

注意:arg 是“dsrdtr”,参数是“None”,而不是“False”

测试:Python 3.8.8、anaconda 3 (2021.05)、pyserial 3.5 Arduino Mega2560、MKR WiFi 1010、Wemos Mega2560 + ESP8266

于 2021-12-01T17:52:48.863 回答
-2

这是一个软件解决方案,我自己使用了一段时间,它就像一个魅力:

ser = serial.Serial("/dev/ttyUSB0", 115200, timeout=1)
ser.setDTR(False)
time.sleep(0.5)

请注意,睡眠是棘手的部分,没有它就无法工作

于 2013-08-28T22:02:19.597 回答