Pilotare due motori DC
con un mouse ps/2
Semplice tutorial su come utilizzare il protocollo ps/2 di un mouse per manovrare un pan & tilt con 2
motoriduttori in continua.
Descrizione
Questo progetto si basa su un microcontrollore PIC 16F870 come interfaccia tra il mouse e i motori.
Certi componenti sono sicuramente sovradimensionati, altri sono ottimizzabili, ma il tutto e' stato fatto
con materiale di recupero o gia' in mio possesso.
A scopo di debug (e anche di coreografia) il circuito comprende anche un display lcd alfanumerico 16x2.
Per poter realizzare tutto questo, come sempre, dobbiamo partire dalla teoria, indispensabile per la
comprensione del firmware.
interfaccia ps/2
I mouse ps/2 sono dotati di connettore mini-DIN 6 poli. Molti mouse attualmente in commercio hanno una
connessione usb, ma vengono forniti con un adattatore usb-ps/2; questo significa che internamente il
mouse e' in grado di rilevare automaticamente il tipo di interfaccia al quale e' collegato senza bisogno di
settaggi esterni.
Riporto qui sotto la piedinatura del connettore femmina mini-DIN 6 poli che e' il connettore standard di un
dispositivo ps/2
1 = Data
2 = Non connesso
3 = GND
4 = Vcc +5V
5 = Clock
6 = Non connesso
Osservando la figura si nota che solo 4 dei 6 pin vengono utilizzati, dei quali due per l'alimentazione
(Vcc e Gnd).
Un dispositivo ps/2 non deve assorbire piu' di 275 mA, dettaglio importante per scegliere il sistema di
alimentazione.
Gli altri due servono per il clock di sincronizzazione e per il transito dei dati da/per il mouse.
Queste due linee sono entrambe open-collector e necessitano quindi di una resistenza di pull up esterna.
Il valore di tale resistenza puo' variare da 1kohm a 10kohm; piu' e' basso il valore piu' aumenta il consumo
di energia, mentre aumentandolo crescono i tempi di salita e discesa dei segnali (slew rate). Io sono stato
sulla solita via di mezzo 4,7kohm.
Se qualcuno si stesse chiedendo che cosa vuol dire open-collector e' presto detto:
in una linea di questo tipo si possono avere soltanto 2 stati, il livello basso e l'alta impedenza.
Quando un pin e' a livello basso, viene internamente cortocircuitato verso massa, provocando cosi uno
zero logico sulla linea.
Quando invecie il pin e' in alta impedenza, esso viene risulta isolato dal resto della circuiteria interna;
viene quindi portato a 1 logico dalla resistenza di pull up che e' collegata tra la linea e l'alimentazione.
Comunicazione ps/2
D'ora in poi indichero' con il termine 'host' il computer, microprocessore, microcontrollore o qualsiasi
altra cosa alla quale il mouse e' collegato.
Il protocollo ps/2 sfrutta una comunicazione seriale, sincrona e bidirezionale. Il bus e' in stato di riposo
(idle) quando entrambe le linee Data e Clock sono alte (alta impedenza).
Questo e' l'unico caso in cui il mouse e' autorizzato a trasmettere.
Infatti il controllo del bus e' delegato all'host che puo' interdire la comunicazione in qualsiasi momento
'abbassando' la linea del clock.
Abbassando invecie la linea Data e rilasciando la linea Clock si crea lo stato di Request To Send.
Vuol dire che l'host e' pronto a trasmettere dati e chiede al mouse di generare il clock.
Il segnale di sincronismo (clock) viene sempre generato dal mouse ad una frequenza compresa tra i 10
e i 16,7 kHz.
La comunicazione avviene sempre un byte alla volta, ognuno incapsulato in pacchetti da 11-12 bit:
- 1 bit di start (sempre 0)
- 8 bit di dati (trasmessi partendo dal bit meno significativo)
- 1 bit di parita' dispari
- 1 bit di stop (sempre 1)
- 1 bit di acknowledge (solo nella comunicazione host -> mouse)
Il bit di parita' sara' a livello alto se il numero di 1 nel byte da trasmettere e' pari, in modo che il totale
di bit a 1 sia dispari.
COMUNICAZIONE MOUSE -> HOST
In questa direzione i dati vengono letti dall'host sul fronte di discesa del clock, o meglio, il byte e' stabile
durante il livello basso del clock.
I pacchetti dati sono composti da 11 bit (vedi sopra) senza comprendere il bit di acknowledge.
Illustro qui sotto il diagramma temporale:
L'host puo' interrompere in qualsiasi momento la comunicazione abbassando la linea Clock per almeno
100ms.
COMUNICAZIONE HOST -> MOUSE
Per trasmettere un comando, l'host deve prima di tutto inibire la comunicazione mettendo il clock a
livello basso per almeno 100ms.
Poi applica lo stato di 'Request to Send' abbassando la linea Data e riportando a livello alto la linea Clock.
Da qui il mouse comicia a generare il clock.
Al contrario di quanto succede nella comunicazione mouse -> host, il mouse legge il dato durante il livello
alto del clock.
Dopo aver ricevuto il bit di stop, il mouse rispondera' con un acknowledge portando a livello basso la linea
Data. A questo punto se l'host non rilascia la linea Data, il mouse continuera' a generare il clock finche'
Data non torna a livello alto; allora il mouse generera' un codice di errore.
Anche in questo caso la trasmissione puo' essere annullata in qualsiasi momento dall'host portando a livello
basso il clock per almeno 100ms.
RISOLUZIONE e SCALING
Lo standard ps/2 prevede l'impiego di due contatori che tengono traccia dei movimenti X e Y. Questi
registri contengono un numero a 9 bit in complemento a 2 per rappresentare quantita' e direzione dello
spostamento, oltre ad un altro bit per ogni asse, detto di overflow.
Essi vengono resettati ad ogni invio, a meno che non venga interrotta prematuramente la comunicazione.
Questi contatori vengono incrementati dal mouse ogni volta che rileva un movimento. Il parametro che
determina di quanto debbano essere aumentati i contatori si chiama risoluzione.
La risoluzione di default e' di 4 conteggi ogni mm, ma puo' essere variata dall'host attraverso l'apposito
comando (vedi oltre).
C'e' un altro parametro, che si chiama scaling, che permette di stabilire quanti conteggi devono essere
effettuati prima di passare i dati in uscita. Lo scaling di default e' 1:1, modificabile anche lui tramite
apposito comando.
Il valore dei due contatori X e Y viene trasmesso, assieme allo stato dei pulsanti e ai flag di overflow, in
un pacchetto a 3 byte come raffigurato nella seguente tabella:
Il secondo e terzo byte contengono il valore dei 2 contatori di movimento, che rappresentano quanto si
e' spostato il mouse dall'ultimo invio di dati. Infatti questi contatori vengono aggiornati ogni volta che il
mouse, leggendo i suoi sensori, rileva un movimento e vengono resettati ogni volta che il mouse invia con
successo un pacchetto di dati.
Il valore contenuto in questi 2 byte deve essere considerato come un valore a 9 bit in complemento a 2,
dove il bit piu' significativo e' il relativo bit di segno nel byte 1 del pacchetto di risposta (bit 4 e 5).
Quindi ogni contatore puo' contare da -255 a +255, settando a 1 il relativo bit di overflow nel caso si
dovesse superare questo valore.
Il modo in cui un mouse invia le sue risposte dipende strettamente alla modalita' operativa in cui si trova.
Nello standard ps/2 queste modalita' sono quattro:
- Modo Reset: il mouse entra in questa modalita' all'accensione o dopo avere ricevuto un comando di
di reset dall'host (0xFF) e imposta tutti i parametri di default (sample rate = 100 campionamenti/secondo,
risoluzione = 4 conteggi/mm, scaling 1:1, disabilita il data reporting). A questo punto il mouse invia un
byte per confermare il successo dell'operazione o un eventuale errore (0xAA, 0xFC rispettivamente).
Infine viene inviato il codice 0x00 corrispondente al ID di un mouse ps/2 standard. Dopo avere inviato
l'ID di dispositivo, il mouse entra in modo Stream e disabilita il data reporting, vale a dire che il mouse
non inviera' nessun pacchetto di movimento finche' non ricevera' il comando di enable.
- Modo Stream: questa e' la modalita' di default impostata dopo un reset. In questa modalita' il mouse
inviera' un pacchetto di dati ogni volta che rilevera' un movimento sui sensori o sui pulsanti. Puo' essere
modificata anche la frequenza con la quale avvengono questi reporting (sample rate) da un minimo di
10 ad un massimo di 200 campionamenti/secondo.
- Modo Remote: in questa modalita' invecie il mouse inviera' un pacchetto di dati solo dopo che gli viene
richiesto dall'host tramite specifico comando. Flag e contatori vengono aggiornati ogni volta che viene
rilevato un movimento o un cambiamento di stato e vengono azzerati solo dopo essere stati trasmessi
all'host.
- Modo Wrap: questa modalita' viene utilizzata generalmente solo in fase di debug e di test. Qui il mouse
rispedisce indietro all'host ogni byte che riceve (echo) senza processarli, cosi' da poter capire se il
dispositivo e il bus funzionano.
Di seguito elenco i comandi riconosciuti da un mouse ps/2 standard.
Set di comandi
0xFF: Reset - il mouse risponde con un acknowledge (0xFA) e entra in modalita' Reset
0xFE: Resend - il mouse risponde con l'ultimo pacchetto inviato all'host
0xF5: Disable Data Reporting - il mouse risponde con un acknowledge (0xFA), disabilita il reporting e
azzera i contatori di movimento. Questo comando ha effetto solo in modo Stream.
0xF4: Enable Data Reporting - il mouse risponde con 0xFA e riabilita il reporting. Anche questo comando
ha effetto solo in modalita' Stream.
0xF3: Set Sample Rate - il mouse risponde con 0xFA e si mette in attesa di un altro byte che verra' salvato
come nuovo sample rate. Questo valore puo' essere 10, 20, 40, 60, 80, 100 o 200 campionamenti al
secondo. Infine un altro 0xFA.
0xF2: Get Device ID - il mouse risponde con 0xFA seguito dal device ID (0x00 nel caso del mouse ps/2).
0xF0: Set Remote Mode - il mouse risponde con 0xFA ed entra in modo Remote.
0xEE: Set Wrap Mode - il mouse risponde con 0xFA ed entra in modo Wrap.
0xEC: Reset Wrap Mode - il mouse risponde con 0xFA ed entra nella modalita' in cui era prima di entrare
in Wrap mode.
0xEB: Read Data - il mouse risponde con 0xFA ed invia il pacchetto dati a 3 byte con i movimenti X/Y e lo
stato dei pulsanti. Questo e' l'unico modo per leggere informazioni dal mouse in modo Remote.
0xEA: Set Stream Mode - il mouse risponde con 0xFA ed entra in modo Stream.
0xE8: Set Resolution - il mouse risponde con 0xFA e attende un ulteriore byte per impostare la risoluzione
secondo il seguente schema:
Byte Risoluzione
0x00 1 conteggio/mm
0x01 2 conteggi/mm
0x02 4 conteggi/mm
0x03 8 conteggi/mm
Infine il mouse invia un altro 0xFA.
0xE7: Set Scaling 2:1 - il mouse risponde con 0xFA e imposta lo scaling a 2:1.
0xE6: Set Scaling 1:1 - il mouse risponde con 0xFA e imposta lo scaling a 1:1.
Mi rimangono solo un paio di cosette ancora da dire. I mouse ps/2 hanno bisogno per funzionare di una
procedura di inizializzazione tramite i comandi visti sopra. Questo fa si che questo genere di dispositivi non
sia collegabile a sistema gia' avviato (hot plug). Inoltre abbiamo visto fino a qui le caratteristiche di un
mouse ps/2 standard. Come ben sapete alcuni mouse hanno anche una o piu' rotelline, nonche' diversi
pulsanti aggiuntivi. Queste features non fanno parte del protocollo ps/2 standard, ma rientrano in
alcune estensioni, la piu' famosa delle quali e' senza dubbio l'estensione Intellimouse della Microsoft che
esula pero' dallo scopo di questo tutorial.
Finalmente dopo tanta teoria e' giunto il momento di passare a un po' di pratica.
Interfaccia hardware
Diamo un'occhiata allo schema elettrico:
|
clicca per ingrandire |
Lo schema e' stato disegnato con Kicad per GNU/Linux. Nonostante possa sembrare piuttosto ingarbugliato
in realta' e' piuttosto semplice. Il cuore di tutto e' un microcontrollore PIC 16F870 clockato con un quarzo
a 4 MHz. I due pin RA0 e RA1 vengono utilizzati come linea Data e Clock rispettivamente. Si vedono le 2
resistenze di pull up (R1 e R2) che sono peraltro gli unici 2 componenti essenziali alla comunicazione col
mouse.
Quasi tutta la porta B viene impiegata per l'interfacciamento col display lcd alfanumerico 16x2 compatibile
HD44780. Ho inserito il display per controllare anche senza motori che il circuito funzionasse e in piu' un
po' di coreografia non fa male a nessuno. Non descriveremo in questo articolo il funzionamento del display
in quanto gia' ampiamente documentato in rete (un link fra tanti che consiglio:
www.giobe2000.it/HW/HD44780/Pag/Home.asp).
La porta C invecie e' usata per comandare un L293B, un doppio ponte H per il pilotaggio dei motori in
continua (in realta' sono motoriduttori da 20 rpm, con forza 10 kg/cm).
Ho utilizzato l'L293B perche' e' un componente che avevo gia' in casa, comunque per motori di
piccola potenza consiglio l'L293D che contiene gia' al suo interno i diodi in parallelo al motore. Tali diodi
hanno la stessa funzione di quelli posti in parallelo alla bobina dei rele', cioe' servono a cortocircuitare le
sovratensioni scaricate dalle bobine durante le commutazioni del segnale di pilotaggio che potrebbero
danneggiare il circuito ad esse collegato. I diodi devono essere molto veloci in modo che riescano a
passare dalla conduzione alla interdizione prima della scarica delle bobine.
La figura sopra serve a spiegare il principio di funzionamento di un ponte H. I due triangoli A e B possono
essere considerati come dei deviatori che portano l'uscita a livello dell'alimentazione o cortocircuitata
verso massa a seconda del livello logico sull'ingresso. In pratica per far girare il motore (M) in un verso
dobbiamo portare l'uscita di A al valore Vcc mentre l'uscita di B verra' portata a livello logico basso, cioe'
cortocircuitata verso massa. Si crea cosi' una corrente che va da A a B. Per far girare il motore nel senso
opposto bastera' invertire gli stati logici e il gioco e' fatto.
Nello schema e' da notare l'utilizzo di due tensioni di alimentazione, una da 5V per l'elettronica e l'altra da
12V per i motoriduttori. L'utilizzo di due alimentazioni separate e' altamente consigliato per evitare che i
forti disturbi introdotti dai motori possano resettare il micro o danneggiare il display.
Seguono alcune foto della realizzazione su breadboard (si, lo so, e' un gomitolo di fili).
|
clicca per ingrandire |
Il mio pan & tilt casalingo (molto casalingo :-) con applicata sopra una telecamerina
|
clicca per ingrandire |
Il circuito anch'esso molto casalingo.
Nella foto si nota soprattutto il display, poi partendo da sinistra vediamo il PIC 16F870 con il quarzo, il
trimmer per la regolazione del contrasto dell'lcd, un 7805 che alimenta tutta la logica e infine l'L293B con
i suoi 8 diodi. In alto a sinistra c'e' un doppio connettore ps/2 da stampato ricavato da una vecchia scheda
madre ormai fritta.
Un breve filmato dimostrativo puo' essere scaricato da:
">it.youtube.com/watch
Il firmware
Il firmware da caricare nel PIC puo' essere scaricato da qui:
UserFiles/amberlight/File/mouse.asm
Per i piu' pigri c'e' anche il firmware gia' compilato con gpasm (per GNU/Linux) pronto per essere scritto
nel micro.
UserFiles/amberlight/File/mouse.hex
E' scritto in assebler e bene commentato, comunque cerchiamo di fare un breve riepilogo di cio' che fa.
Dopo le solite dichiarazioni di variabili e inizializzazioni dei registri e delle porte, viene impostato un
ritardo di circa un secondo con la linea Data a livello basso. E' un tempo un po' lungo, ma questo permette
ai mouse con doppia interfaccia usb-ps/2 (come il mio) di rilevare il protocollo corretto.
Inizia quindi la fase di inizializzazione del mouse inviando in sequenza i seguenti comandi:
- 0xFF - Reset
- 0xF5 - Disabilita Data Reporting
- 0xF3 - Modifica Sampling Rate
- 0x0A - 10 campionamenti/secondo
- 0xE8 - Imposta Risoluzione
- 0x03 - 8 conteggi/mm
- 0xF0 - Imposta modo Remote
- 0xF4 - Enable
Una inizializzazione del display lcd e si entra in un loop infinito che invia al mouse il comando 0xEB (Read
Data) memorizzando i 3 byte di risposta in altrettante variabili (byte1, byte2 e byte3). Il primo byte
conterra' i flag e lo stato dei pulsanti, mentre gli altri due conterranno i famosi contatori di movimento. Di
questi ultimi due valori controlliamo solo il bit meno significativo per vedere se c'e' stato un movimento,
nel qual caso un test sui bit di segno nel primo byte ci dira' come impostare le uscite della porta C per far
girare il relativo motore in un senso oppure in un altro.
Per complicare ulteriormente le cose ogni motore entra in funzione solo se e' premuto anche il relativo
pulsante, per evitare rotazioni accidentali prendendo contro al mouse.
Sul display vengono visualizzate le informazioni dei pulsanti e dei movimenti con vari simboli come le
freccie (simboli da verificare sul datasheet del display in quanto ogni costruttore potrebbe implementare
delle tabelle di caratteri diverse).
Il firmware e' infine completato con le due routine di invio e ricezione dati sul bus ps/2 che seguono alla
lettera i diagrammi e le temporizzazioni di cui abbiamo parlato prima.
Questa e' solo una spiegazione sommaria, per i dettagli vi rimando alla lettura del codice sorgente.
Nel caso vogliate divertirvi a modificare il listato ricordate di non impostare MAI la linea Data o la linea
Clock come uscita a livello alto; se dall'altra parte il mouse abbassa quella linea ci si ritrova con un pin del
micro cortocircuitato a massa. Meglio evitare.
Conclusioni
Abbiamo visto il protocollo ps/2 dei mouse e come sfruttarlo per pilotare due motori, ma naturalmente le
possibili applicazioni non sono tutte qui. Spero in un prossimo articolo di poter trattare qualche altro
utilizzo, magari sfruttando anche la rotella.
Se qualcuno avesse critiche da fare (possibilmente costruttive), consigli da dare per migliorare la pagina o
per qualunque chiarimento sono a disposizione di tutti.