2013-03-17 6 views
8

Sto provando a utilizzare pyserial per inviare dati a un arduino. Ma quando apro la porta COM, imposta DTR basso e ripristina la scheda. Tuttavia, ho la mia configurazione del codice Arduino tale che devo metterlo in modalità di ricezione seriale tenendo premuto due pulsanti per 1 secondo. Preferirei non dover fare l'input seriale all'avvio dell'arduino, se possibile.Disabilita DTR in pyserial dal codice

A quanto pare è possibile modificare il file serialWin32.py, cambiando la riga che legge:

self._dtrState = win32.DTR_CONTROL_ENABLE 

a:

self._dtrState = win32.DTR_CONTROL_DISABLE 

Ma, c'è un modo per disabilitare proprio questo direttamente nel mio script python ? Devo anche farlo per tutti i sistemi. Preferirei non forzare le persone a cambiare la loro configurazione seriale di base solo per usare questo script.

La porta seriale è aperta come segue:

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

Aggiornamento: Alla fine ho trovato una soluzione che funziona bene per la mia messa a punto. Dal momento che non ho avuto bisogno di fare i dati seriali tutto il tempo, solo quando ho messo il dispositivo in modalità di ricezione seriale ho trovato un modo per disabilitare il reset sulla connessione seriale dallo stesso arduino.

Molti post hanno dichiarato che è possibile disattivare il ripristino DTR posizionando un resistore ~ ​​100 Ohm tra 5 V e ripristinato. Ma non volevo che fosse una cosa permanente. Così, invece, ho inserito una resistenza tra PD5 e reset. Poi, nel 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 
} 

Così ora, quando voglio essere in modalità seriale, io chiamo setResetDisable (vero) che getta 5V su quel 100 Ohm e il perno di riarmo, impedendo DTR da tirandolo basso e reimpostare il chip :) Ho quindi chiamato setResetDisable (false) quando esco dalla modalità seriale in modo che il chip possa essere programmato normalmente.

risposta

11

È dovrebbe essere in grado di disabilitare DTR prima di aprire la porta, in questo modo:

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

Tuttavia, così facendo sulla versione corrente di pySerial (2.6) su Windows getta la seguente eccezione:

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

Questo sembra essere un bug che è stato risolto nel più recente versione della fonte, SVN revisione 445 del 29 dicembre 2011 (vedi http://pyserial.svn.sourceforge.net/viewvc/pyserial/trunk/pyserial/serial/serialwin32.py?view=log) con un commento:

permettono setRTS, setDTR prima di aprire su Win32 (per impostare stato iniziale), l'aggiornamento doc

che sembra che potrebbe avere appena perso il 2,6 rilascio (caricato il 2 novembre 2011 vedi: https://pypi.python.org/pypi/pyserial).

Inoltre, guardando l'attuale implementazione di setDTR() per POSIX (in serialposix.py) sembra questo bug non è fisso e viene generata un'eccezione se la porta non è aperta, quindi una soluzione cross-platform sembra improbabile.

+1

Questo non funziona per me. Anche con DTR = False, l'Arduino si reimposta ancora durante la riconnessione seriale. Sto usando la versione più recente di Pyserial 3.0.1 su Ubuntu. – Cerin

+2

@Cerin Aveva lo stesso problema, ma l'impostazione di DTR prima di aprire la porta ora funziona per me (Python 3.5.1 su Windows 8.1 a 64 bit e l'attuale pySerial 3.1). Vedi anche il problema nel repository "nuovo" su GitHub: https://github.com/pyserial/pyserial/issues/124 – handle

+0

Ho anche notato che facendo 'stty -hup' sulla porta si arresta anche il problema. Perchè è questo? Com'è collegato a DTR? –

1

Il metodo che descrivi sembra essere la soluzione più comune per questo problema che ho visto - quindi sospetto che non ci sia una soluzione basata su software più semplice. Ovviamente è possibile modificare manualmente lo stato della linea DTR usando ser.setDTR(level) - tuttavia non l'ho provato in particolare nel caso dell'autoreteet Arduino, e sospetto che persino la commutazione della linea immediatamente dopo l'apertura della porta seriale potrebbe non essere abbastanza veloce per impedire il reset.

Le altre opzioni posso vedere che avete a disposizione sarebbe quello di impedire l'autoreset del Arduino in hardware (see here), o per modificare il codice leggermente in modo che si consenta l'Arduino per riavviare dopo aver inizialmente rendendo la connessione seriale, e quindi quando si attiva manualmente la modalità di ricezione seriale, inviare un segnale iniziale da Arduino per mostrare che è ora pronto per ricevere i dati. In alternativa, potresti includere una versione modificata della libreria pySerial con il tuo script.

-1

Ecco una soluzione software, ho usato io stesso per un po 'e funziona come un fascino:

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

Nota che il sonno è la parte difficile, senza di essa non funzionerà

+3

Questo perché il sonno attende abbastanza da reimpostare l'arduino. Il dtr qui non sta facendo nulla. – Mark

+0

Mark, lo so, ma questo è l'unico modo per farlo funzionare. Le altre soluzioni prevedono la correzione di un bug in pyserial. Si tratta di una soluzione abbastanza buona se si vuole ottenere le cose, ed è multipiattaforma. – aguaviva

0

disattivazione DTR non funziona per me:
ser.dtr = None
(Linux 4.4.0 x86_64/Python 2.7.12/PySerial 3.4)

Ma questo funziona:

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

L'ho trovato here.

Problemi correlati