2013-03-17 11 views
8

Ich versuche, Pyserial zu verwenden, um Daten an ein Arduino zu senden. Aber wenn ich den COM-Port öffne, setzt er DTR niedrig und setzt die Karte zurück. Allerdings habe ich meine Arduino-Code-Setup so, dass ich es in den seriellen Empfangsmodus durch Halten von zwei Tasten für 1 Sekunde setzen muss. Ich würde lieber nicht die serielle Eingabe beim Booten des Arduino machen, wenn möglich.Disable DTR in Pyserial von Code

self._dtrState = win32.DTR_CONTROL_ENABLE 

zu:

self._dtrState = win32.DTR_CONTROL_DISABLE 

Aber gibt es eine Möglichkeit, nur diese deaktivieren direkt in meinem Python-Skript

Anscheinend kann man serialWin32.py Datei, Ändern Sie die Zeile, liest ändern ? Ich muss das auch für alle Systeme tun. Ich möchte die Leute nicht dazu zwingen, ihre serielle Basiskonfiguration zu ändern, nur um dieses Skript zu verwenden.

Die serielle Schnittstelle wird wie folgt geöffnet:

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

Update: Am Ende fand ich eine Lösung, die für mein Setup funktioniert gut. Da ich die seriellen Daten nicht ständig machen musste, fand ich nur dann eine Möglichkeit, das Zurücksetzen der seriellen Verbindung vom Arduino selbst zu deaktivieren, wenn ich das Gerät in den seriellen Empfangsmodus setzte.

Viele Beiträge haben gesagt, dass Sie DTR Reset deaktivieren können, indem Sie einen ~ 100 Ohm Widerstand zwischen 5V und Reset setzen. Aber ich wollte nicht, dass dies eine dauerhafte Sache ist. Also habe ich stattdessen einen Widerstand zwischen PD5 und Reset gesetzt. Dann in der Software:

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 
} 

So, jetzt, wenn ich im seriellen Modus sein will, rufe ich setResetDisable (true), die 5 V führt auf, dass 100-Ohm-Widerstand und den Reset-Pin, verhindert DTR aus ziehen sie niedrig und Zurücksetzen des Chips :) Ich rufe dann nur setResetDisable (false), wenn ich den seriellen Modus verlassen, so kann der Chip als normal programmiert werden.

Antwort

11

Sie sollte der Lage sein, DTR zu deaktivieren, bevor Sie den Port, wie diese Öffnung:

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

jedoch dabei auf der aktuellen Version von pyserial (2.6) unter Windows wirft die folgende Ausnahme:

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

Dies scheint einen Fehler zu sein, die in der neuesten Version der Quelle, SVN-Revision 445 am 29. Dezember 2011 (siehe http://pyserial.svn.sourceforge.net/viewvc/pyserial/trunk/pyserial/serial/serialwin32.py?view=log) mit Kommentaren festgelegt ist:

erlauben setRTS, setDTR vor

auf Win32 (gesetzt Anfangszustand), doc Update Öffnung, die es sieht aus wie verpasst haben nur die Version 2.6 (hochgeladen am 2. November 2011, siehe: https://pypi.python.org/pypi/pyserial).

Der Weitere bei der aktuellen Implementierung von setDTR() für POSIX suchen (in serialposix.py) es sieht aus wie diese Fehler nicht befestigt sind und eine Ausnahme ausgelöst wird, wenn die Port nicht geöffnet ist, so dass eine plattformübergreifende Lösung unwahrscheinlich aussieht.

+1

Dies funktioniert nicht für mich. Selbst wenn DTR = False ist, wird das Arduino während der seriellen Wiederverbindung zurückgesetzt. Ich benutze die neueste Version von Pyserial 3.0.1 unter Ubuntu. – Cerin

+2

@Cerin Hatte das gleiche Problem, aber die Einstellung DTR vor dem Öffnen des Ports funktioniert jetzt für mich (Python 3.5.1 unter Windows 8.1 64 Bit und die aktuelle pySerial 3.1). Siehe auch das Problem im "neuen" Repository bei GitHub: https://github.com/pyserial/pyserial/issues/124 – handle

+0

Ich bemerkte auch, dass 'sty-hup' auf dem Port auch das Problem stoppt. Warum ist das? Wie ist das mit DTR verbunden? –

1

Die Methode, die Sie beschreiben, scheint die häufigste Lösung für dieses Problem zu sein, die ich gesehen habe - also vermute ich, dass es keine einfachere softwarebasierte Lösung gibt. Sie können natürlich den Zustand der DTR-Leitung manuell ändern, indem Sie verwenden - allerdings habe ich dies im Fall des Arduino-Autoresets nicht versucht, und ich vermute, dass sogar das Umschalten der Leitung unmittelbar nach dem Öffnen der seriellen Schnittstelle möglicherweise nicht schnell genug ist um das Zurücksetzen zu verhindern. Die anderen Optionen, die ich sehen kann, dass Sie zur Verfügung haben, wären, das Autoreset des Arduino in der Hardware zu verhindern (see here), oder Ihren Code leicht zu ändern, damit Sie den Arduino neu starten können, nachdem Sie die serielle Verbindung hergestellt haben, Wenn Sie Ihren seriellen Empfangsmodus manuell auslösen, senden Sie ein erstes Signal vom Arduino, um zu zeigen, dass es nun bereit ist, Daten zu empfangen. Alternativ können Sie auch eine modifizierte Version der pySerial-Bibliothek in Ihr Skript einfügen.

-1

Hier ist eine Software-Lösung ist, ich habe es selbst für eine Weile mit und es wirkt wie ein Zauber:

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

Beachten Sie, dass der Schlaf der schwierige Teil ist, ohne sie wird es nicht

arbeiten
+3

Das liegt daran, dass der Schlaf lange genug wartet, bis das Arduino zurückgesetzt wird. Das dtr hier macht nichts. – Mark

+0

Mark, ich weiß, aber das ist der einzige Weg, um das zum Laufen zu bringen. Die anderen Lösungen beinhalten die Behebung eines Fehlers in pyserial. Dies ist ein guter Workaround, wenn Sie die Dinge in Gang bringen wollen, und es ist plattformübergreifend. – aguaviva

0

Deaktivieren von DTR nicht für mich arbeiten:
ser.dtr = None
(Linux 4.4.0 x86_64/Python 2.7.12/PySerial 3.4)

Aber das funktioniert:

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

Ich fand es here.