Отключить 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)
Обратите внимание, что сон - сложная часть, без этого он не будет работать.