2013-03-17 13 views
8

Próbuję użyć pyserial do wysłania danych do Arduino. Ale kiedy otwieram port COM, ustawia on poziom DTR na niskim poziomie i resetuje kartę. Jednak mam ustawiony mój kod arduino tak, że muszę włożyć go do trybu odbioru szeregowego, przytrzymując dwa przyciski przez 1 sekundę. Wolałbym nie robić seryjnego wejścia przy starcie arduino, jeśli to możliwe.Wyłączyć DTR w pyserial z kodu

Podobno można zmodyfikować plik serialWin32.py, zmieniając linię, która brzmi:

self._dtrState = win32.DTR_CONTROL_ENABLE 

do:

self._dtrState = win32.DTR_CONTROL_DISABLE 

Ale, czy jest jakiś sposób, aby po prostu wyłączyć ten bezpośrednio w mój skrypt Pythona ? Też muszę to zrobić dla wszystkich systemów. Wolałbym raczej nie zmuszać ludzi do zmiany ich podstawowej konfiguracji szeregowej tylko po to, aby używać tego skryptu.

port szeregowy jest otwarty, co następuje:

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

Aktualizacja: W końcu znalazłem rozwiązanie, które działa dobrze dla mojej konfiguracji. Ponieważ nie musiałem wykonywać seryjnych danych przez cały czas, tylko gdy ustawiłem urządzenie w trybie odbioru szeregowego, znalazłem sposób na wyłączenie resetowania na połączeniu szeregowym z samego urządzenia arduino.

Wiele postów powiedziało, że można wyłączyć reset DTR, umieszczając rezystor ~ 100 Ohm pomiędzy 5 V i reset. Ale nie chciałem, żeby to była stała sprawa. Zamiast tego umieściłem rezystor pomiędzy PD5 i zresetowałem. Następnie w programie:

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 
} 

Więc teraz, gdy chcę być w trybie seryjnym, wzywam setResetDisable (true), który rzuca 5V na tym 100 rezystor ohm i pin resetu, zapobiegając DTR ciągnie to niski i resetowanie układu :) Po prostu wywołuję setResetDisable (false), kiedy opuszczam tryb szeregowy, aby chip mógł zostać zaprogramowany jako normalny.

Odpowiedz

11

Ty powinien aby móc wyłączyć DTR przed otwarciem portu, podobnie jak to:

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

Jednak robi to w bieżącym wydaniu pyserial (2.6) w systemie Windows rzuca następujący wyjątek:

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

Wydaje się to być błąd, który został rozwiązany w najnowszej wersji źródła, SVN wersji 445 w dniu 29 grudnia 2011 roku (patrz http://pyserial.svn.sourceforge.net/viewvc/pyserial/trunk/pyserial/serial/serialwin32.py?view=log) z komentarzem:

pozwalają setRTS, setDTR przed otwarciem na Win32 (ustawić stan początkowy), aktualizacja doc

który wygląda jak może mieć po prostu brakowało 2,6 uwalnianiu (przesłanego w dniu 2 listopada 2011 r patrz: https://pypi.python.org/pypi/pyserial).

Ponadto, patrząc na bieżącej realizacji setDTR() dla POSIX (w serialposix.py) wygląda ten błąd nie jest ustalona i jest wyjątek, jeśli port nie jest otwarty, więc rozwiązanie wieloplatformowe wygląda mało prawdopodobne.

+1

To nie działa dla mnie. Nawet przy DTR = False, Arduino wciąż resetuje się podczas ponownego łączenia szeregowego. Używam najnowszego wydania pyserial 3.0.1 na Ubuntu. – Cerin

+2

@Cerin Miał ten sam problem, ale ustawienie DTR przed otwarciem portu działa teraz dla mnie (Python 3.5.1 na Windows 8.1 64 bit i aktualny pySerial 3.1). Zobacz także problem w "nowym" repozytorium na GitHub: https://github.com/pyserial/pyserial/issues/124 – handle

+0

Zauważyłem również, że robienie 'stty -hup' na porcie również zatrzymuje problem. Dlaczego to? Jak to jest połączone z DTR? –

1

Opisana metoda wydaje się najczęstszą poprawką dla tego problemu, który widziałem - więc podejrzewam, że nie ma prostszego rozwiązania opartego na oprogramowaniu. Oczywiście możesz ręcznie zmienić stan linii DTR używając ser.setDTR(level) - jednak nie wypróbowałem tego specjalnie w przypadku autoretyka Arduino i podejrzewam, że nawet przełączenie linii natychmiast po otwarciu portu szeregowego może nie być wystarczająco szybkie aby zapobiec resetowaniu.

innych opcji widzę, że masz dostępne byłoby zapobiec AUTORESET z Arduino w sprzęcie (see here), lub zmienić swój kod nieznacznie, dzięki czemu pozwalają na Arduino, aby ponownie uruchomić po początkowym wykonaniu połączenia szeregowego, a następnie, po ręcznym uruchomieniu trybu odbioru szeregowego, wyślij początkowy sygnał z Arduino, aby pokazać, że jest on gotowy do odbioru danych. Ewentualnie możesz dołączyć zmodyfikowaną wersję biblioteki pySerial do swojego skryptu.

-1

Tutaj jest oprogramowaniem, używam go samodzielnie na chwilę i działa jak czar:

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

Note, że sen jest skomplikowana część, bez niego to nie będzie działać

+3

To dlatego, że sen czeka wystarczająco długo, aby arduino mogło się zresetować. Dtr tutaj nic nie robi. – Mark

+0

Mark, wiem, ale to jedyny sposób, żeby to zadziałało. Inne rozwiązania obejmują naprawę błędu w pyserial. Jest to całkiem dobre rozwiązanie, jeśli chcesz, aby wszystko działało, i jest to platforma wieloplatformowa. – aguaviva

0

Wyłączenie DTR nie działa dla mnie:
ser.dtr = None
(Linux 4.4.0 x86_64/Python 2.7.12/PySerial 3.4)

Ale to działa:

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

Znalazłem go here.

Powiązane problemy