Foto del tastierino

Ciao a tutti,
è da molto tempo che non parlo di progetti strambi, come termometri o formattazioni. E' ora di ricominciare. In attesa di un qualcosa di un po' più corposo (ho appena aggiornato il termometro a termometro 3.1) ho deciso di scrivere del tastierino che gestisce l'alimentazione della strumentazione del mio laboratorio. Questo progetto è nato da una serie di idee tanto semplici quanto cretine.
 

Anzitutto, sono sempre stato affascinato da tutte quelle cose che c'entrano col entrare in posti segreti o riservati: inserire codici, strisciare tesserini, meno gli esami di impronte digitali e della retina, quelli sono troppo futuristici e perdono di fascino. Anche se l'apice sarebbe un sistema come l'LCARS di Star Trek, in cui TUTTO avviene con l'interazione vocale, dall'accensione della luce alla FFT (o chissà quale altra diavoleria che i matematici inventeranno in futuro).
Nel mio caso, non potendo stuprare una porta solo per aggiungere una chiusura a pistone o magnetica, ho dovuto accontentarmi, e per accontentarmi intendo poter accendere e spegnere pc e strumentazione con un codice (appunto).

Specifiche ed idee fondanti

Passiamo alle specifiche. Come detto sopra, il sistema deve:

  1. Commutare una linea elettrica (accenderla e spegnerla in base alla correttezza del codice)
  2. Possibilmente non deve fornire alcun indizio sul codice (correttezza, lunghezza...)
  3. Deve indicare lo stato della linea (abilitata oppure no)

Per realizzare la specifica 1 mi sono servito di un relè bistabile (o passo passo) inserito nella placchetta degli interruttori. Esso viene pilotato con la 220 da un altro relè più piccolo inserito nel circuito del modulo. Fanno parte del circuito anche un connettore per il tastierino, un PIC18F2520 ed un cicalino, che fa *bip* quando si preme un tasto. E' infine presente il connettore per la programmazione ed il debug rapido del circuito.
La seconda specifica, invece, prende spunto dagli antifurti: il primo approccio che viene naturale nel progettare un sistema di questo tipo è di inserire un codice e premere il tasto invio per verificare la correttezza del codice. In questo modo, però, si finisce per fornire un'informazione sulla lunghezza massima del codice impiegato. Le casseforti digitali, ad esempio, adottano questo stratagemma: se scrivi troppe cifre danno errore. Il mio progetto, invece, accetta numeri all'infinito e non "reagisce" fino a quando non riceve il numero giusto. In sostanza è una specie di parser.
Per indicare lo stato utilizza un semplice led bicolore, che è verde quando la linea è attiva, rosso quand'è disattivata ed arancione in fase di transizione.

Realizzazione hardware

Il circuito è semplice, talmente semplice e ovvio che cercando la documentazione che produco solitamente quando mi metto a fare un progetto (lo schema elettrico) non l'ho nemmeno trovato. Non credo che sia colpa di Dropbox stavolta...
In pratica è composto da un PIC18F2520 (immancabile), un Relè con relativo diodo di ricircolo ed il led bicolore. Il PIC18F2520 è un oggettino molto versatile: è un microcontrollore ad 8bit, incorpora le funzioni base del pic quali tre porte ad 8 bit di I/O digitali (su una ci sono dei pull-up attivabili per non doverli aggiungere sul circuito), convertitori A/D, timers, watchdog timer... per passare a funzioni più complesse, quali generatori di segnale PWM (usando un timer), porta seriale, bus SPI-I2C (il suo collega 2550 si può collegare all'usb). Costano 5€ a dire tanto (il programmatore PicKit2 costa 25-30€) e si programmano con 4 segnali direttamente sul circuito, quindi particolarmente indicati per essere inclusi in progetti casalinghi. Quando poi ho scoperto che si può debuggare anche con il PicKit2 ho dato di matto...
A tutto questo si aggiunge (ovviamente) un tastierino numerico. Tali oggetti sono costruiti a matrice ed il tasto premuto pone in cortocircuito una riga con una colonna. Tale approccio vieta la pressione di più tasti contemporaneamente (pena lettura sbagliata). Le righe sono collegate alle uscite del pic, mentre le colonne sono collegate agli ingressi tramite resistenze di pull-down.

Il software: leggere un tastierino alfanumerico

Leggere un tastierino è un'operazione molto semplice. Si sceglie quale "lato" della matrice attivare (in questo caso le righe) e su quale lato andare a verificare la pressione del tasto (le colonne). Deciso per le righe, si alimenta con un segnale alto (o basso, è uguale) una riga alla volta (mantenendo le altre basse) e si controllano le colonne: se non è presente nessun segnale alto nessun tasto (su quella riga) è stato premuto, altrimenti controllando quale colonna è attiva è possibile rilevare quale tasto è stato premuto. Ad esempio, premendo il 2, si attiva la seconda colonna. Si può facilmente intuire che la funzione usata per leggere è una fila di switch case che controllano le colonne dopo aver abilitato le righe ma non solo, in quanto sorgono alcuni problemi:

  • Nessun tasto potrebbe essere stato premuto. In tal caso ho copiato la convenzione della funzione leggi tastiera che usavo al Fermi: il valore di ritorno è il tasto premuto + 1. Se nessun tasto è stato premuto, ritorno 0. In questo modo, con un semplice if logico, è possibile determinare se un tasto è stato premuto oppure no.
  • Due o più tasti potrebbero essere stati premuti contemporaneamente. Sebbene questa configurazione non sia lecita (un po' come per i latch S-R) e non metta in crisi la funzione (vince semplicemente il primo case che incontra), potrebbe essere dannosa nel caso i due tasti premuti siano sulla stessa colonna, in quanto porrebbe in cortocircuito due uscite del pic, una alta ed una bassa. Per evitare questo malfunzionamento si possono intraprendere due strade: inserire tra righe ed uscite delle resistenze serie che limitino la corrente (che vanno però rapportate alle resistenze di pull-up sulle colonne pena un valore di tensione logica sballato), oppure durante la scansione abilitare in uscita solo il pin attivo, lasciando tutti gli altri impostati come ingressi (e quindi in alta impedenza). La seconda soluzione è preferibile per non degradare il segnale logico (grazie a Fantini che mi ci ha fatto pensare col suo corso).

Notare che si tratta di una funzione da utilizzare in polling, dato che il pic deve solo ascoltare il tastierino numerico in attesa del codice ho preferito questa soluzione. Un'altra soluzione ad interrupt è teoricamente possibile, attivando tutte le righe e gli interrupt sulle colonne. In caso di pressione, si può effettuare la scansione normale per rilevare il tasto premuto. Questo sistema, impostando un interrupt su transizione di stato (da basso ad alto, ad esempio), risolverebbe anche un altro problema, quello di distinguere lo stato del tasto (premuto/non premuto) dall'effettiva azione di pressione e rilascio (che noi intendiamo come digitazione).

Lettura e convalida del codice

Come ho scritto sopra la lettura del tastierino avviene in polling. In pratica vi è un ciclo che attende che la funzione di lettura restituisca un valore diverso da zero. Per evitare di riempire il buffer con una cifra (la funzione è più veloce dell'utente e legge molti numeri) viene tenuta traccia dell'ultima cifra premuta ed il ciclo di attesa verifica che la nuova cifra sia diversa da 0 (nessun tasto premuto) e dalla cifra precedente (tasto premuto in precedenza che non è stato ancora rilasciato).
Per convalidare il codice ho scelto di appoggiare i numeri man mano che vengono digitati in un buffer e confrontarli ogni volta con un codice hard-coded (questo significa che per cambiare codice occorre cambiare il sorgente, ricompilare e riprogrammare). Per realizzare il buffer ho usato una variabile intera, ed il sistema utilizzato è il seguente:

buffer = (buffer * 10 + cifra) % MASCHERA;

Dove maschera è una potenza del 10, dove l'esponente è pari al numero di cifre nel codice. Il modulo tra la maschera ed il buffer taglia via la cifra troppo significativa. Il prodotto esegue uno shift in base 10 (sposta tutte le cifre a sinistra) e la somma inserisce la nuova cifra nel buffer. Se buffer diventa uguale a codice, il sistema cambia di stato. In realtà, usando un relè passo passo, basterebbe inviare un impulso ed il sistema potrebbe benissimo essere all'oscuro dello stato in cui si trova. Tale distinzione si rende necessaria per dare la giusta colorazione al led di stato. Inoltre, per evitare che un blackout resetti il led ma non il relè, lo stato viene salvato sulla EEPROM del pic e viene riletto in fase di accensione.

Conclusioni

Era da tempo che volevo togliermi uno sfizio del genere, e finalmente ci sono riuscito. La realizzazione, come avrete riscontrato, è particolarmente semplice, alla portata di tutti. Non ho inserito nessun tipo di sicurezza anti hacking (tanto basta aprire la scatola e fare un ponticello), ma avrei potuto inserire ritardi, ad esempio se il codice viene sbagliato 5 volte di fila oppure di 2 secondi ogni volta che viene sbagliato, tipo ssh. E voi, cosa proteggereste con un codice?

beh proteggerei gli oggetti che per me hanno più valore e a cui sono molto affezionato, ovviamente la mia bambola gonfiabile, e il mio tesserino del LPC!!