Wyłącz DTR na ttyUSB0

11

Łączę się z Pi do płytki klonowej Arduino. Problem polega na tym, że muszę wyłączyć linię DTR, aby zapobiec resetowaniu Arduino podczas łączenia.

Czytałem, że na RPi nie można kontrolować DTR, DCD i innych linii. Czy dotyczy to globalnie RPi, czy tylko pinów GPIO używanych do komunikacji szeregowej?

Jeśli to możliwe, aby wyłączyć DTR na porcie USB, jak to zrobić?

jnovacho
źródło

Odpowiedzi:

6

Właściwości konwertera szeregowego USB nie mają nic wspólnego ze sprzętem systemu hosta, ale tylko z samym układem szeregowym USB i stosem oprogramowania systemu hosta.

Pi powinien używać standardowych sterowników szeregowych Linux USB.

Dlatego możesz włączyć / wyłączyć powiązanie DTR z portem otwierającym / zamykającym za pomocą zwykłej metody czyszczenia systemu Linux hupclzgodnie z dokumentacją na stronie Arduino i gdzie indziej:

stty -F /dev/ttyUSB0 -hupcl

Lub zastąpienie / dev / ttyUSB0 plikiem, który faktycznie odpowiada portowi szeregowemu USB (na przykład pierwsze podłączone Uno to prawdopodobnie / dev / ttyACM0)

Nawet w przypadku własnego natywnego portu szeregowego PI, to zachowanie DTR jest ostatecznie kontrolowane przez oprogramowanie - każdy, kto twierdzi inaczej, ignoruje fakt, że jest to tylko sterownik Linux, a nie sprzęt, który ma jakąkolwiek wiedzę na temat tego portu otwarte lub zamknięte. Rzeczywisty sprzęt portu może jedynie stwierdzić, że jest odczytywany, zapisywany lub ponownie konfigurowany, z których żaden nie jest właściwie równoznaczny z otwarciem urządzenia szeregowego.

Chris Stratton
źródło
Czy to będzie działać tylko tak długo, jak hosting pi nie zostanie ponownie uruchomiony?
user2395126
6

@ChrisStrattons post opisuje, jak używać, stty -F /dev/ttyUSB0aby uniknąć zawieszenia, które powoduje reset. Oto fragment do zrobienia tego w Pythonie:

import termios

path = '/dev/ttyACM0'

# Disable reset after hangup
with open(path) as f:
    attrs = termios.tcgetattr(f)
    attrs[2] = attrs[2] & ~termios.HUPCL
    termios.tcsetattr(f, termios.TCSAFLUSH, attrs)

ser = serial.Serial(path, 9600)
# etc.

Zauważ, że dokładna liczba może przy ponownym podłączeniu kabla USB, więc ścieżkę wykrywam przez globbing:

try:
    path = glob.glob('/dev/ttyACM*')[0]
except IndexError:
    # retry, error out, etc.
    pass
Lekensteyn
źródło
Potwierdziłem, że działa to w Ubuntu na zwykłym laptopie x86_64 i Raspberry Pi 2.
Cerin
Czy istnieje jakiś powód do użycia termios, powiedzmy os.system("stty -F /dev/ttyUSB0 -hupcl"),? Poza tym zauważyłem, że nie zapobiega to resetowaniu Arduino przy pierwszym połączeniu z nim po włączeniu systemu hosta; zapobiega resetowaniu przy kolejnych połączeniach. Co jest lepsze niż nic. Ale chciałbym wymyślić, jak powstrzymać to przed przełączaniem DTR.
Jason C
2
@JasonC Korzystanie termioszapisuje widelec / exec (wywołanie) do zewnętrznego programu ( stty). Nie jestem pewien, co zrobić z DTR, myślę, że właśnie zaakceptowałem tę „funkcję” i dodałem trochę logiki (niestandardowy uścisk dłoni przez pisanie / czytanie), aby wykryć, czy Arduino i aplikacja na Pi zsynchronizowały się.
Lekensteyn,
Moim ostatecznym rozwiązaniem było dodanie polecenia stty podczas uruchamiania pi, a następnie echa portu, aby wymusić to pierwsze resetowanie, oraz 3 sekundowe opóźnienie oczekiwania na reset arduino. Potem nie muszę już o tym myśleć ani martwić się tym w skryptach Pythona. Zrobiłem to w rc.local, ale gdziekolwiek. Koszt to +3 sekundy czasu rozruchu pi.
Jason C
3

Możesz dodać rezystor 120Ohm (lub kombinację, aby uzyskać 120Ohm) między RESETi5V To całkowicie uniemożliwi reset. Jest to najmniej inwazyjne, ponieważ inne rozwiązania wymagają usunięcia rezystora lub kondensatora z płyty, komplikuje przesyłanie. Nie trzymaj rezystora, jeśli programujesz. Usunąć to.

wprowadź opis zdjęcia tutaj

Tablice Leonardo nie resetują się, nawet jeśli DTRzostaną wyzwolone, ale problem zaczyna się, gdy trzeba je zresetować zdalnie, ponieważ czasami traci połączenie z Raspberry i trzeba go fizycznie zresetować.

Piotr Kula
źródło
3
Nie jestem pewien, czy to zasługuje na opinię. Jest do bani, ale nie jest oparty na oprogramowaniu, ale po kilku badaniach wydaje się, że jest to gotowe rozwiązanie sprzętowe.
Jason C
0

Jeśli korzystasz z biblioteki Seria i pySerial, możesz użyć:

ser = serial.Serial ('/ dev / ttyACM0', 9600, dsrdtr = True)

polo04
źródło
-1

Możesz użyć PySerial. Oto przykład kodu w języku Python:

port =serial.Serial(
    "/dev/ttyUSB0",
    baudrate=57600,
    parity=serial.PARITY_NONE,
    stopbits=serial.STOPBITS_ONE,
    bytesize=serial.EIGHTBITS,
    dsrdtr = False
    )

aby uzyskać więcej opcji, sprawdź Pyserial.

hsantana8
źródło
1
To nie jest problem z biblioteką. Próbowałem już 4 różnych bibliotek, zawsze ten sam wynik - polecenia DTR są ignorowane.
jnovacho
Jeśli jest to dokładne stwierdzenie czegoś, co działa na innym Linuksie, powinno również działać na pi, ponieważ sprzęt pi obsługuje tylko ogólne oprogramowanie linux, a nie jest w to wyjątkowo zaangażowany.
Chris Stratton
1
To nie działa W systemie Linux nadal powoduje to zresetowanie Arduino.
Cerin,
1
Potwierdzam, że to nie działa na jakiejkolwiek wersji Pi i Arduino, którą mam (nie wiem, przepraszam, nic nie wiem o tych rzeczach, nie chcę wiedzieć, właśnie dostałem system do debugowania jakiegoś kodu on, heh.) Również nie jestem pewien, czy jest to powiązane, ale stty -F /dev/ttyUSB0 -cdtrdsrzgłasza invalid argument: -cdtrdsr.
Jason C