Отключить DTR в pyserial из кода

Я пытаюсь использовать 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.

Во многих публикациях говорится, что вы можете отключить сброс DTR, поместив резистор ~100 Ом между 5 В и сбросом. Но я не хотел, чтобы это было постоянным. Итак, вместо этого я поместил резистор между 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), который выдает 5 В на резисторе 100 Ом и выводе сброса, не позволяя DTR понижать его и сбрасывать микросхему:) Затем я просто вызываю setResetDisable(false)) когда я выхожу из последовательного режима, так что чип можно запрограммировать как обычно.

5 ответов

Решение

Вы должны иметь возможность отключить DTR перед открытием порта, например так:

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

Однако в текущей версии pyserial (2.6) для Windows возникает следующее исключение:

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

Похоже, что это ошибка, исправленная в последней версии исходного кода, редакция SVN 445, 29 декабря 2011 г. (см. http://pyserial.svn.sourceforge.net/viewvc/pyserial/trunk/pyserial/serial/serialwin32.py?view=log) с комментарием:

разрешить setRTS, setDTR перед открытием на Win32 (для установки начального состояния), обновление документа

Похоже, что он только что пропустил релиз 2.6 (загружен 2 ноября 2011 года, см.: https://pypi.python.org/pypi/pyserial).

Кроме того, глядя на текущую реализацию setDTR() для POSIX (в serialposix.py) похоже, что эта ошибка не исправлена и возникает исключение, если порт не открыт, поэтому кроссплатформенное решение выглядит маловероятным.

Отключение 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()

Я нашел это здесь.

Метод, который вы описываете, кажется наиболее распространенным решением этой проблемы, которое я видел, поэтому я подозреваю, что не существует более простого программного решения. Конечно, вы можете вручную изменить состояние линии DTR, используя ser.setDTR(level) - однако я не пробовал это конкретно в случае автосброса Arduino, и я подозреваю, что даже переключение линии сразу после открытия последовательного порта может быть недостаточно быстрым, чтобы предотвратить сброс.

Другие доступные вам варианты: предотвратить автоматический сброс Arduino на аппаратном уровне ( см. Здесь) или слегка изменить ваш код, чтобы позволить Arduino перезагрузиться после первоначального установления последовательного соединения, а затем, когда Вы вручную запускаете режим последовательного приема, отправляя начальный сигнал от Arduino, чтобы показать, что теперь он готов к приему данных. Или же вы можете включить в свой скрипт измененную версию библиотеки pySerial.

Это старая тема, но я сейчас работаю над программой, отправляющей последовательные данные в Arduino. Это линия, которая надежно работает для меня:

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

Примечание: аргумент — «dsrdtr», а параметр — «None», а не «False».

проверено на: Python 3.8.8, Anaconda 3 (2021.05), pyserial 3.5 Arduino Mega2560, MKR WiFi 1010, Wemos Mega2560 + ESP8266

Вот программное решение, я сам некоторое время пользуюсь им, и оно работает как шарм:

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

Обратите внимание, что сон - сложная часть, без этого он не будет работать.

Другие вопросы по тегам