Continuo la descrizione del progetto di Federico Davanteri: Anemometro a coppe portatile basato su arduino
in questo articolo leggerai:
- Gestione del display
- Gestione del pulsante per cambio modalità di calcolo
- Sperimentazione dell’anemometro a coppe portatile
Come già fatto nel precedente articolo lascio la pagina a Federico che ha scritto un documento dettagliatissimo.
Gestione del display
Premetto che esistono vari modi di gestire un display di questo tipo. In commercio si trovamo moduli a 7 segmenti già dotati dell’elettronica necessaria per gestirli in modo semplice e veloce. Inoltre si possono utilizzare circuti intergati denominati “shift register” che permettono di utilizzare un numero contenuto di ping digitali di Arduino.
Io ho preso un display senza elettronica di gestione ed ho implementato tutta la circuiteria e il software necessari per farlo funzionare.
E’ stato molto istruttivo, ma ho dovuto utilizzare praticamente tutti i ping digitali e analogici della scheda e scrivere il software di “multiplexing” per la visualizzazione delle cifre.
Il display utilizzato è del tipo detto a “sette segmenti”, dove ogni cifra è composta da una combinazione diversa di segmenti accesi o spenti. Ciascun segmento é un LED, quindi l’intero display è formato da 4×7 = 28 LED + 4 punti decimali e un doppio punto centrale. In totale 34 LED.
I LED (segmenti) che costituiscono la cifra “DIG.x” sono identificati da una lettera da “A” a ”G”, come mostrato qui sotto a sinistra. IL punto è “DP”, mentre i due punti centrali sono “D5” e “D6”.
Nel caso specifico del display utilizzato da me, gli anodi dei LED (poli positivi) sono separati e raggruppati per segmento (es: tutti i segmenti “F” condividono lo stesso anodo), mentre i catodi (poli negativi) sono raggruppati per cifra. Da qui la definizione di display a catodo comune.
Per poter accendere e spegnere i led abbiamo quindi bisogno di 14 pin, ma io ne ho utilizzati 12 in quanto il doppio punto non mi serviva.
Nota: i pin digitali 0 e 1 sono utilizzati per la comunicazione seriale, pertanto se vengono impegnati per la gestione di altri dispositivi o sensori, essi vengono inibiti dall’attivazione della comunicazione seriale con il computer (Serial.begin…). Nel mio caso li ho utilizzati per il display.
Nella figura seguente si vede lo schema completo preso da datasheet del display.
Anodi e catodi corrispondono ai piedini del display (immagine sotto), e sono numerati da 1 a 14 (da 1 a 7 sul lato anteriore e da 8 a 14 su quello posteriore). Quindi vediamo (immagine sopra) che gli anodi corrispondono ai piedini 13, 9, 4, 2, 1, 12, 5, 3 e 8 (la posizione disordinata deriva dalla geometria interna dei collegamenti), mentre i catodi sono i piedini 6, 10, 7, 11, e 14.
Il piedino 13 collega quindi tutti i segmenti “A” delle quattro cifre, il 9 i segmenti “B” e così via.
Dallo schema appare chiaro che collegando il display e inviando gli opportuni segnali a ciascun pin, tutte le cifre mostreranno lo stesso numero, dato che ogni pin alimenta lo stesso segmento di ogni cifra. Come fare quindi per mostrare cifre diverse ?
Qui entra in gioco il software. Con il meccanismo di multiplexing, cui ho già accennato, si riesce a mostrare cifre diverse pur inviando lo stesso segnale a tutte le cifre.
Vediamo come funziona.
La funzione Loop() del programma richiama continuativamente una funzione, che ho chiamato WriteDig() la quale riceve come parametri la cifra da rappresentare, e su quale delle quattro indirizzarla. Facciamo un esempio pratico. Supponiamo di voler rappresentare le cifre 5, 6, 7 e 8.
void loop () { WriteDig(5,1); // cifra 5 sulla prima posizione WriteDig(6,2); // cifra 6 sulla seconda posizione WriteDig(7,3); // cifra 7 sulla terza posizione WriteDig(8,4); // cifra 8 sulla quarta posizione }
La chiamata della funzione avviene quattro volte per ogni loop, passando di volta in volta le quattro cifre indirizzate nelle quattro posizioni diverse del display.
La funzione WriteDig() quindi, con quattro chiamate successive esegue quanto segue:
- accende la prima cifra (le altre spente) e scrive 5. Attende 1/50 sec e spegne tutto.
- accende la seconda cifra (le altre spente) e scrive 6. Attende 1/50 sec e spegne tutto.
- accende la terza cifra (le altre spente) e scrive 7. Attende 1/50 sec e spegne tutto.
- accende la quarta cifra (le altre spente) e scrive 8. Attende 1/50 sec e spegne tutto.
Dato che l’occhio umano non è in grado di percepire cambiamenti così repentini dell’immagine (fenomeno detto della “persistenza della visione”), esso crede di vedere quattro cifre diverse, mentre in realtà ogni cifra viene inviata sempre in tutte le quattro posizioni, ma solo quella corrispondente alla posizione corretta viene di volta in volta accesa. La velocità di ripetizione dell’intero processo dà l’impressione che le diverse cifre siano tutte accese allo stesso istante mentre in realtà sono accese nelle rispettive posizioni ma in istanti diversi. E’ un inganno per l’occhio, ma un inganno fatto bene!
Abbiamo detto che ogni segmento del display è un LED, quindi deve essere protetto da un resistore che ne regoli la corrente, come espressamente specificato nel datasheet del display.
Sempre dal Datasheet si legge che la tensione di “forward” dei LED è pari a 2V. Quindi, alimentando il tutto con 5V calcoliamo facilmente il valore della resistenza che ci serve per avere una corrente di 10 mA, più che sufficiente per alimentare i LED e ampiamente al di sotto dei 40 mA di corrente massimi raccomandati per i pin della scheda Arduino UNO.
Ho preso quindi il valore standard più vicino per eccesso, che è 330 Ohm, ed ho collegato i resistori agli 8 pin (anodi) che mi serviva alimentare.
Da un punto di vista circuitale, ogni resistenza serve i quattro led corrispondenti ad un determinato segmento. Non si tratta però di LED in parallelo, avendo tutti catodi distinti.
Gestione del pulsante per cambio modalità di calcolo
All’accensione lo strumento visualizza la velocità del vento in m/s, che è l’unità di misura comunemente utilizzata. Ho voluto però aggiungere un pulsante NA (Normalmente Aperto) che permetta di cambiare la modalità ed esprimere la velocità anche in Km/h e in nodi.
Per far ciò ho utilizzato alcuni pin analogici, che all’occorrenza possono essere utilizzati come digitali (come da documentazione ufficiale di Arduino).
Lo schema elettrico è il seguente. Il pulsante è collegato al pin digitale 13 e al ground tramite un resistore da 10 Kohm (resistore di pull-down, come per la lettura del sensore di vento). Il programma legge lo stato del pulsante ed in base ad esso setta una variabile che condiziona la modalità di calcolo della velocità.
Ho aggiunto tre LED verdi collegati ai pin analogici (in modalità digitale) A0, A1 e A2, per indicare quale delle tre modalità di calcolo è attiva. I LED vengono accesi alternativamente ad ogni pressione del pulsante.
Va detto che per una buona gestione del pulsante è necessario aggiungere, alla semplice lettura dello stato del pulsante, anche alcune istruzioni di “debouncing” ossia antirimbalzo.
In pratica, il programma controlla lo stato del pulsante all’interno di un periodo di 50 millisecondi, per evitare che la pressione accidentale prolungata o altri tipi di interferenze nel segnale possano dare una falsa lettura. Se, trascorsi questi 50 ms, lo stato del pulsante non è più cambiato, allora la variabile di stato viene impostata al suo valore definitivo.
Senza questo accorgimento, infatti, risulta difficile premere il pulsante e variare lo stato dei led in modo preciso e netto. Con l’introduzione dell’antirimbalzo il sistema diviene invece affidabile e ogni pressione del pulsante causa lo switch tra un led e l’altro senza alcun problema.
Sperimentazione dell’anemometro a coppe portatile
Il grafico sotto rappresenta una semplice prova effettuata soffiando ripetutamente sull’anemometro. I valori sono stati inviati al monitor seriale di Arduino e poi copiati in Execl per generare il grafico.
Si osserva la linea regolare di smorzamento dello strumento, quando non più soggetto al flusso d’aria, rallenta fino a fermarsi.
Per verificare la correttezza della velocità rilevata ho fatto poi una prova pratica in automobile, Aiutato dal mio valido assistente e consulente scientifico, mio figlio Leonardo, ho montato il sensore su un’asta che ho poi esposto dal finestrino ad una velocità di 36 Km/h (10 m/s), verificata dal navigatore satellitare (non dal tachimetro dell’auto !). L’indicazione dell’anemometro ha confermato i dati di calibrazione con una buone precisione, tuttavia la prova così effettuata è facilmente soggetta ad errori. Mi riprometto, in futuro, di eseguire ulteriori test per convalidare la precisione dello strumento.
Sarebbe molto utile il confronto diretto con uno strumento professionale.
Durante la prova ho riscontrato un problema nella visualizzazione dei dati sul display. La valocità, nella prima versione del software, veniva visualizzata ad ogni ciclo del programma, ma già a 36 Km/h l’eccessiva cadenza degli impulsi disturbava la visualizzazione rendendola poco stabile (sfarfallio accentuato).
Ho quindi introdotto una modifica al software, limitando la visualizzazione della velocità ad una volta al secondo. In questo modo la rappresentazione risulta stabile senza influire sull’algoritmo di lettura che procede alla velocità normale di esecuzione.
Per far ciò ho fatto ricorso di nuovo alla funzione millis(), che restituisce il numero di millisecondi trascorsi dall’accensione di Arduino.
Tale funzione è utilissima nella programmazione di Arduino, infatti permette di controllare gli intervalli di tempo senza utilizzare l’istruzione “delay()”, la quale ferma l’esecuzione del programma per il tempo specificato, andando ad inibire anche la lettura dei sensori.
Sfruttando la funzione millis() Ho realizzato un timer dinamico ( nel senso che misura intervalli di tempo parziali sequenziali ), utilissimo in molte occasioni ed estremamente facile da implementare.
Si setta una variabile t_start = millis() ad un certo punto del programma. Dopodichè si va a verificare il tempo trascorso semplicemente testando il valore mills() – t_start
Se questo soddisfa determinati requisiti si azzera il timer imponendo t_start = 0 il che permette di iniziare la misurazione di un nuovo intervallo di tempo.
t_start deve essere una variabile di tipo usigned long ( valore restituito dalla funzione millis() ), che può memorizzare valori da 0 + 4,294,967,295.
Ciò significa che va in overflow (assume un valore troppo grande e quindi non rappresentabile) dopo circa 50 giorni di funzionamento continuativo di Arduino, dopodichè si riazzera automaticamente.
Una variabile di tipo int andrebbe invece in overflow (con Arduino UNO) dopo 32 secondi, causando con molta probabilità errori nell’esecuzione del programma.
2 commenti
Ciao, volevo farti una domanda visto che mi sono appena avvicinato ad Arduino, i dati sul vento invece che sul display possono essere mandati al PC per poter avere dei grafici e fare delle statistiche sul vento?
Grazie e ottimo lavoro
Fabio Giavara
Autore
Ciao Fabio,
di solito i dati puoi collezionarli in vari modi, certo devi modificare sia la parte elettronica sia lo sketch per cambiare lo scopo del tuo progetto.