domenica 2 agosto 2015

Apriporta RFID parte 2 - il software

In questa seconda parte completo il primo post sull'apriporta rfid descrivendone brevemente il codice.

Chiamata al server esterno

Al momento della "strisciata" con il badge rfid viene chiamato un servizio web esterno che effettua la validazione del codice rfid letto.
La chiamata è una semplice http get a un pagina web alla quale vengono passati il codice rfid letto e il gate, ovvero il codice della postazione.
Questo perchè il sistema è stato pensato per gestire un set di porte, gestite centralmente con un unico database.
La chiamata è del tipo GET /presenze.aspx?code=XXX&gate=YYY, dove XXX è il codice rfid e YYY è il codice della postazione.
Il servizio chiamato restituisce un "OK" se il codice rfid è valido, in tutti gli altri casi è sufficiente che la pagina web restituisca una stringa diversa.
Per questioni di sicurezza, al fine di avere sempre garantita l'apertura della porta  anche in caso di assenza di connettività verso il server, ho previsto fino a 10 card "master" il cui identificati rfid è cablato nel codice: in questo caso se viene rilevata uno di questi codici, la porta viene aperta istantaneamente senza alcun tipo di verifica sul server remoto. Queste card andranno utilizzate solo dai proprietari del sistema, mentre l'abilitazione di tutte le altre card potrà essere fatta dinamicamente attraverso il database.

Configurazione

per la configurazione sono necessarie alcune costanti:
  • const IPAddress server(82,63,171,50) : indirizzo del nostro server
  • const int       serverPort = 80 : porta del server
  • const String    gate = "SEDE1" : identificativo della postazione (gate)
  • byte            mac[] = { 0x90, 0xA2, 0xDA, 0x0F, 0xE5, 0x0F } : mac address della ethernet shield (attenzione: deve coincidere con quello riportato sull'etichetta sul dietro della scheda)
  • const String master0 = "2590ab25" : identificativo della card master (fino a 10)
  • const int       activateTime = 1000 : tempo di attivazione del relè (consigliato >500ms)

Attenzione: se lavorate con ip address statico, settate la variabile myip[] e scommentate la riga successiva, altrimenti verrà acquisito un indirizzo dinamico via dhcp

  byte myip[] = { 10, 10, 30, 89 };   
 // Ethernet.begin(mac, myip);

Funzionamento

Il main è un ciclo infinito:
viene fatto lampeggiare il led, viene letto l'rfid, vengono aspettati 200ms e poi si ripete nuovamente il ciclo.
In caso di lettura di un rfid, viene verificato se il codice coincide con una delle card master, in tal caso viene attivato immediatamente il relè. Se il codice non è relativo a una card master, allora viene invocato il servizio esterno chiedendo la verifica sul codice rfid letto. Se la risposta è affermativa allora viene eccitato il relè.

Lo sketch

Scarica qui lo sketch completo

Non posto la parte serve in quanto davvero semplice. Nel mio caso si trattava di una pagina aspx che andava a effettuare una query su una tabella contenente le card abilitate. Al momento della chiamata veniva inoltre scritta una tabella di log riportante codice, ora, gate ed esito.






sabato 1 agosto 2015

Apriporta RFID parte 1 - il progetto

Ho avuto qualche richiesta di pubblicazione del progetto apriporta rfid, che avevo brevemente postato tempo fa su youtube.


Il progetto è un derivato diretto dal progetto di rilevazione presenze, dal quale eredita la gestione dell'Rfid e della chiamata http per validare il dato.
Ovviamente trattandosi di un apri porta è presente in più un relè che serve ad eccitare l'apriporta.

Come funziona un apriporta

Per aprire una porta con arduino è necessario che questa sia dotata di una serratura elettrica. Nella maggiorparte dei casi le porte di ingresso degli uffici sono dotati di un incontro elettrico. L'incontro non è la serratura, bensì il "fermo" che sta sulla parte opposta, sulla quale il catenaccio aperto dalla maniglia va ad incastrarsi. Nelle porte normali non elettrificate questa componente è fissa ed è semplicemente un foro, mentre nelle porte elettrificate diventa una parte mobile che può essere sbloccata elettricamente permettendo alla porta di essere aperta.
Per chi interessa c'è un bel video della Viro che spiega come montarne uno. Tra l'altro il costo è veramente ridottissimo, circa 30 euro uno di buona marca.


Di fatto per arduino l'incontro elettrico viene "nascosto" dietro un relè da eccitare per qualche decina di millisecondi, al quale sarà collegato appunto l'incontro elettrico.

Per questo progetto non ho utilizzato il classico arduino uno, bensì un arduino mega, in quanto avevo la necessità di tenermi la porta aperta (scusate il gioco di parole visto che si tratta di un apriporta...) in caso di future espansioni di questo progetto.

Ecco la lista della spesa:

  • 1 Arduino Mega 2560 R2
  • 1 proto shield
  • 1 ethernet shield (without poe)
  • 1 scheda relè 5v
  • 1 alimentatore 12v
  • 1 display 16x2
  • 1 modulo rfid 522
  • 1 level converter
  • 1 buzzer
  • 1 led
  • cavo di rete cat 5


Il cavo di rete ci servirà in quanto il modulo rfid, il led di controllo e il buzzer saranno montati lontani dalla centralina arduino. Questo perchè nella mia installazione il modulo rfid/led/buzzer sono all'esterno della porta di casa, sotto il citofono, mentre la centralina arduino + relè sono all'interno. Un po' per questioni di sicurezza (ci vuole un secondo a cortocircuitare un relè e aprire la porta), un po' perchè la parte elettronica principale preferivo non esporla alle intemperie e agli sbalzi termici (vivo in Trentino, qui d'inverno fa anche -10°C).
Non sottovalutate i cavi troppo lunghi, ho scritto un interessante post in passato, ci sono disturbi di tutti i tipi in agguato, nell'insieme questo è un progetto davvero molto sensibile ai disturbi.
Per questo ho usato twistare i segnali sulla massa in modo indipendente, nell'utilizzare il cavo di rete.

Sull'utilizzo del level converter ho scritto un precedente post, se non fosse chiaro l'utilizzo prego darvi una rapida letta.

Wiring

Per l'assemblaggio ho usato una scatola di derivazione dove ospitare l'arduino, la scheda di rete, il relè, mentre all'esterno ho utilizzato una scatola stagna per campanelli, dove viene ospitato il lettore rfid, il led e il buzzer.
Per la connessione tra le 2 scatole ho usato 2 cavi di rete cat 6, per un totale di 16 poli disponibili, di cui però ne ho usato solo una parte

Cavo 1 (cavo di rete cat 6): si usano tutte le coppie

ARDUINO          LEVEL CONVERTER                                                            RFID
50 (miso)   --->  B4 level converter     A4 ---> Marrone (twistato con B/marrone + 3.3V) --> miso 
51 (mosi)   --->  B3 level converter     A3 ---> Verde (twistato con B/verde +3.3v)      --> mosi 
8  (sda)    --->  B2 level converter     A2 ---> Arancio                                 --> sda  
9  (rst)    --->  B/Arancio                                                              --> rst  
52 (sck)    --->  Blu  (twistato con B/blu gnd)                                          --> sck  
+3.3V       --->  B/verde + B/marrone + pin LV scheda level converter                    --> +3.3V 
gnd         --->  B/blu + pin GND scheda level converter                                 --> gnd  
+5V         --->  pin HV scheda level converter

Cavo 2 (cavo di rete cat 6): si usano solo 3 cavi

ARDUINO

2  (+buzzer) --->  B/Verde   cavo 2   ----> +buzzer
53 (+led)    --->  Verde     cavo 2   ----> +led
Gnd          --->  B/Marrone cavo 2   ----> resistenze 100 ohm verso polo (-) buzzer e led
           

Connessione alla scheda Rfid (cavo 1)

arancio   ---| SDA
blu       ---| SCK
verde     ---| MOSI
marrone   ---| MISO
non coll. ---| IRQ
b/blu     ---| GND
b/arancio ---| RST
b/verde   ---| +3.3V

Buzzer e led (Cavo 2)


      LED               BUZZER
     +   -             -      +
     |   |             |      |
  verde  |             |   B/verde
         |             |
         +-100R-+-100R-+
                |
                |
               gnd
            B/Marrone
           
Connessione al relè

Arduino                 Relè
7 Polo controllo Blu -> In1 
Gnd Bianco           -> Gnd 
+5V Rosso            -> Vcc

Display

Ho utilizzato un display 16x2 montato su un connettore che ne permettesse facilmente la rimozione.
Questa componente è opzionale, ma direi indispensabile in una prima fase di test, in quanto permette agevolmente di capire se arduino è collegato in rete, se ha preso l'indirizzo dal dhcp, se l'rfid legge, ecc.

47 -> RS
43 -> enable
41 -> D4
35 -> D5
33 -> D6
31 -> D7
oltre a gnd e +5V 

Ecco alcune foto della realizzazione:














Nel prossimo post: il software dell'apriporta

giovedì 26 febbraio 2015

Arduino a 5V e corretto interfacciamento tra periferiche 3.3V

Ho notato che spesso si trovano esempi di progetti su internet del tutto inaffidabili.
Un esempio classico è il collegamento di periferiche a 3.3V basate su bus SPI a normali arduini a 5V.
Un errore è quello di pensare che sia sufficiente alimentare la periferica a 3.3V, collegando il bus SPI normalmente senza alcun riduttore di tensione.
Sono incappato anch'io in questo errore, e ho scoperto a mie spese che il bus SPI deve lavorare alla stessa tensione dell'alimentazione della periferica, pena il cattivo funzionamento o addirittura il danneggiamento della scheda.

Vi faccio un esempio. Il classico lettore Rfid RC522 disponibile in molte varianti e marche va alimentato a 3.3V.

L'errore è quello di collegare Vdd a 3.3V di arduino, Gnd a gnd, e poi miso/mosi/sck/rst/sda ai rispettivi pin di arduino.

Devo essere sincero che ho fatto anch'io così e a prima vista sembrava funzionare tutto bene.
Poi quando ho smesso di alimentare il tutto via usb e sono passato all'alimentazione esterna, tutto ha smesso di funzionare.

Qualche giornata a dare la caccia ai fantasmi e poi il dubbio e l'intuizione: non è che alimentando il tutto con un alimentatore esterno si generano dei livelli di tensione più alti che alterano il funzionamento?

Se andiamo a leggere le specifiche NXP che trovate qui http://www.nxp.com/documents/data_sheet/MFRC522.pdf noterete che la tolleranza dell'RC522 è di circa mezzo volt rispetto alla tensione nominale di 3.3V.

Io ho provato in condizioni di alimentazione usb a misurare il livello di un'uscita ttl di arduino: a un valore HIGH non corrispondono 5V ma qualcosina di meno, nell'ordine dei 4V.
Ebbene, se alimentiamo l'arduino con un alimentatore esterno tale livello si alza di un qualcosina, diciamo che si porta attorno a 4.1/4.2V, a seconda delle schede e delle tolleranze dei componenti.
Tale differenza è quella che fa si che l'RC522 smetta di funzionare, perchè l'RC522 tollera (forse) un 4V al posto di un 3.3V, ma non riconosce un segnale più alto, anzi questa tolleranza cambia da scheda a scheda.

Ho avuto la fortuna di disporre di 3 schede RC522 identiche e di poterle intercambiare.
Ebbene, tutte e 3 funzionavano se alimentate da usb. Una sola su 3 funzionava se alimentato il tutto dall'esterno.

La soluzione corretta è l'applicazione di un level converter che converta il segnale dei pin miso/mosi/ecc da 5V a 3.3V.
Essendo il bus SPI bidirezionale ho adottato con successo questo level converter della adafruit.
http://www.adafruit.com/product/757 che costa circa €1.50 e svolge egregiamente il suo lavoro: converte da 5V a 3.3V i segnali SPI da arduino all'rfid e viceversa.

E mi viene da dire: culo che andasse senza level converter e che niente si sia guastato nelle prove.





Bus SPI e cavi lunghi

Ho recentemente montato una versione del mio progetto di rilevazione presenze con rfid, adattandolo ad apri porta con validazione lato server.
Non ripropongo qui il progetto perchè è una leggerissima variante di quello già postato in precedenza per il rilevatore presenze.
La cosa interessante su cui volevo soffermarmi è la difficoltà di portare lontano le periferiche dalla board arduino, in particolare quelle basate sul bus SPI.
Nel progetto incriminato utilizzavo una mega 2560 con a cavallo una ethernet shield e un relè, che doveva costituire la centralina base del mio apriporta e posizionata all'interno dell'abitazione.
All'esterno dell'abitazione veniva posizionato il lettore rfid rc522, un led e un buzzer di segnalazione.
In mezzo, circa 3m di cavo, su cui girava il bus spi e i pin di controllo per led+buzzer.
Sia la ethernet shield che l'rfid utilizzano il bus SPI, alternandosi tramite attivazione via software (pin SDA).
Ho perso circa 2gg a cercare di capire il perchè il tutto funzionasse perfettamente sul tavolo di casa ma appena montato nella sua sede definitiva smettesse di funzionare, in particolare la schede ethernet che pensavo, essendo montata direttamente sopra la board arduino, dovesse essere l'ultima ad avere problemi.
Il problema è che il bus SPI non è fatto per le grandi distanze, anzi è fatto per gestire collegamenti diretti molto molto brevi tra shield.

Dalle specifiche dello standard SPI:

The serial peripheral interface (SPI) bus is an unbalanced or single-ended serial interface designed for short-distance communication between integrated circuits

Appena si introduce un cavo lungo, anche nell'ordine di 1 o pochi metri, si vanno a introdurre disturbi sul bus SPI che alterano in modo sistematico e a volte randomico il funzionamento.
Il bus SPI infatti "gira" a una frequenza tipicamente 1/4 della frequenza del nostro arduino. Su un arduino Uno o Mega 2560, il clock 16MHz va a formare il clock al SPI  con una frequenze pari a 1/4, ovvero 4MHz. Un segnale digitale a 4MHz su un cavo inadatto o in ambiente rumoroso (cavi 220V nelle vicinanze, citofoni, campanelli, ecc) può essere davvero un gran problema.
Uno dei problemi che riscontravo era che nonostante l'rfid fosse scollegato, il solo cavo volante connesso lato arduino al bus SPI portasse gravi disagi all'ethernet shield posta a 1cm dall'arduino board.

Ci sono vari trick&tips per la soluzione del problema.

Consiglio #1

Attenzione al cavo: evitiamo cavi elettrici sfusi o da antifurto. Un cavo di rete cat5/6 può andare benissimo, meglio se schermato (stp). La particolare conformazione del cavo di rete, a coppie twistate, permette scegliendo bene la combinazione di segnali di proteggersi meglio dal rumore.
Ad esempio accoppiando SCK con GND, MISO con Vdd, MOSI con Vdd ho ottenuto ottimi risultati. Tra tutti quandi direi che il segnale di clock SCK è quello più sensibile al rumore.

Consiglio #2

Un'altro fattore importantissimo da non sottovalutare è la frequenza del clock. Più il cavo è lungo, più effetto capacitivo ed induttivo viene introdotto, alterando la forma del segnale digitale. Quello maggiormente sensibile è proprio il segnale di clock (SCK, a volte indicato come CLK).
La frequenza può però essere ridotta via software, impostando un divisore maggiore della frequenza base.

Questa semplice istruzione ad esempio imposta il clock a 16MHz / 128 = 125KHz

SPI.setClockDivider(SPI_CLOCK_DIV128); 

Altri consigli

Ho trovato vari articoli, ma questo mi è stato particolarmente utile:
http://neophob.com/2012/03/lpd6803-spi-and-long-distance
In particolare qui si cita la necessità di introdurre sui pin dati del spi (miso , mosi e anche sul clock sck) una resistenza di basso valore (33-51-100Ohm) al fine di implementare un terminatore per ridurre le reflextion del segnale.
Nel mio caso non ho provato perchè la semplice adozione del cavo twistato e l'abbassamento del clock ha permesso di far funzionare tutto egregiamente, però immagino che nel caso avessi adottato un cavo più lungo tale consiglio sarebbe stato essenziale.
Altri consigliano di mettere una resistenza tra il SCK e la GND, pari a 1K o più.

Parola d'ordine: SPERIMENTARE!





lunedì 8 dicembre 2014

netToken - parte 2 - il codice

Veniamo all'implementazione software di netToken.


Il codice è composto da un loop principale dove viene verificata la chiamata da un client esterno, cioè dal browser. Il microservo agisce semplicemente quando la pagina web generata da Arduino viene chiamata in HTTP GET, senza alcuna necessità di passare parametri nell'url.
Ovviamente questa tecnica è molto primitiva, ma non avendo altra necessità oltre a quella di far muovere il braccetto fino a premere il pulsante del token per poi farlo ritornare in posizione iniziale, non ho previsto la possibilità di interpretare comandi inviati dal client.

netToken - parte 1: il progetto

Questo strano progetto nasce dall'esigenza di condividere tra più persone un token crittografico. Cos'è un token crittografico si fa presto a dirlo: è un piccolo dispositivo dotato di un display numerico che in modo temporizzato offre all'utente un numero valido per pochi secondi, che deve essere utilizzato per le operazioni di internet banking (cioè una one-time-password).
E' tipicamente usati sia dai siti di onbanking che dalle molte app mobile che ormai tutte le banche mettono a disposizione ai clienti in un'ottica di multicanalità.



Tale numero è univoco e viene generato in un certo istante da quel particolare token con una validità di pochissimi secondi, il che permette alla banca di garantire che chi usa quel numero per accedere sia per forza fisicamente in possesso di quel token, che tradotto in criteri di sicurezza significa avere una certezza in più che la persona che accede è probabilmente il cliente che possiede il token crittografico.
Per chi ne volesse sapere di più, passo la palla a wikipedia, non era questo l'argomento che volevo approfondire. Sappiate solo che il token non comunica con alcunchè ed è semplicemente sincronizzato alla nascita con un server.
Completo il quadro dicendo che la mia azienda si occupa tra l'altro proprio di sviluppo di app mobile per il settore internet banking.
Ebbene, proprio per questo nel mio ufficio ci sono più programmatori che lavorano sulla stessa app contemporaneamente (su due piattaforme: iOS ed Android) e per testare quello che scrivono utilizzano un ambiente di test che la banca ha messo a disposizione con delle credenziali di prova che simulano in tutto e per tutto l'ambiente reale. E come non poteva mancare il token crittografico dato che il tutto deve essere il più realistico possibile?
Immaginate ora queste persone che devono continuamente passarsi l'un l'altro il token per fare test diversi sulla stessa utenza! Semplicemente scomodo ed inefficiente.
Come risolvere il problema? Con questo semplice "coso", che ho chiamato semplicemente netToken.


netToken serve per controllare remotamente via web il token, in modo da permettere la pressione del tastino che lo fa accendere e mostrare per qualche secondo un nuovo numero, catturandone l'immagine remota via webcam, il tutto utilizzabile sia dal un browser desktop che dal un dispositivo mobile.

mercoledì 2 aprile 2014

Banana touch: un light controller per le Philips Hue - parte 2: comandare la lampada

Per controllare la lampada ho utilizzato la porta Ethernet del mio Arduino Ethernet, per collegarlo al Bridge delle Philips Hue. Il tutto attraverso un piccolo router che mi fungeva in questo caso da switch e da server dhcp.
Per maggiori dettagli di come vengono inviati i comandi alle Philips Hue tornate ai miei post precedenti sull'argomento.

Per inviare il codice colore e la luminosità ho predisposto una funzione chiamata setHue(X,Y,B) dove X e Y rappresentano i codice colore 0-255 e B la luminosità sempre in range 0-255.