Eccoci finalmente alla descrizione dello sketch dell’anemometro a coppe portatile di Federico.
Tutta la teoria sul sensore a coppe per l’anemometro e sull’analisi dei dati rilevati è descritta nei precedenti articoli insieme al circuito elettronico ed alle fasi di realizzazione del box:
- Anemometro a coppe portatile – prima parte
- Anemometro a coppe portatile – seconda parte
- Anemometro a coppe portatile – terza parte
- Anemometro a coppe portatile – quarta parte
Dopo aver letto tutti gli articoli precedenti è giunto il momento di dedicarti alla realizzazione dello sketch ed al test sul campo.
Sketch dell’anemometro a coppe portatile
// ============================================================== // PROJECT: ANEMOMETRO // DESCRIPTION: Realizzazione di un anemometro gestito da Arduino // AUTHOR: FEDERICO DAVANTERI // DATE: 29/10/2014 // REV: 1.0 // ============================================================== // Pin dedicato alla lettura del sensore di vento const int getpulsepin = 2; // Associazione dei pin ai segmenti delle cifre (anodi) const int a = 10; const int b = 8; const int c = 7; const int d = 5; const int e = 4; const int f = 9; const int g = 3; const int p = 6; // punto decimale const int toggle = 13; // pin del pulsante di modo calcolo // Associazione dei pin alle cifre (catodi) // cc1 e cc4 sono collegati ai pin A4 e A5 utilizzati come digitali const int cc1 = A4; const int cc4 = A5; const int cc2 = 11; const int cc3 = 12; // Variabili relative alla gestione del display unsigned long counter = 0; // Contatore per azzeramento cifre // dopo 2 sec inattività unsigned long disp_start = 0; // Contatore per visualizzazione // asincrona sul display unsigned long disp_time = 1000; // Durata (ms) visualizzazione // asincrona display // Ritardo spegnimento cifre per multiplexing display // 1 microsecondo = 1/1.000.000 sec // 20.000 microsecondi = 1/50 sec int ritardo = 20000; // Variabili per rappresentazione delle cifre sul display int n1 = 0; // valore calcolato in tempo reale int n2 = 0; // valore calcolato in tempo reale int dec = 0; // valore calcolato in tempo reale int digit1 = 0; // valore n1 assegnato in visualizzazione ritardata int digit2 = 0; // valore n2 assegnato in visualizzazione ritardata int digit3 = 0; // valore dec assegnato in visualizzazione ritardata // variabili per calcoli anemometro float windspeed = 0.0; float m_s_conv = 1000.0/3600.0; // Fattore conversione Km/h --> m/s float nodi_conv = m_s_conv * 1.944; unsigned long startime = 0; unsigned long durata = 0; int stato = 0; int pinval = 0; // variabili per cambio modalità calcolo int mode; // variabile di lettura del pulsante int toggle_status = 0; // toggle_status 0 -> m/s 1 -> Km/h 2 -> Nodi // antirimbalzo per il pulsante unsigned long lastDebounceTime = 0; // istante della precedente // pressione del pulsante unsigned long debounceDelay = 50; // tempo di debounce int buttonState = 0; // stato corrente del pulsante int lastButtonState = LOW; // ultimo stato del pulsante // Funzioni di gestione per il display void WriteDig(int n, int dig) { /* Funzione che gestisce il display 4 digits a CATODO COMUNE n = valore da rappresentare dig = posizione cifra spegnere un digit = HIGH (perchè ha catodo comune) accendere un digit = LOW (perchè ha catodo comune) spegnere un segmento = LOW accendere un segmento = HIGH */ switch(dig) // gestione cifre { case 1: // la prima cifra è sempre spenta (non utilizzata) digitalWrite(A4, HIGH); digitalWrite(cc2, HIGH); digitalWrite(cc3, HIGH); digitalWrite(A5, HIGH); digitalWrite(p, LOW); break; case 2: digitalWrite(A4, HIGH); digitalWrite(cc2, LOW); digitalWrite(cc3, HIGH); digitalWrite(A5, HIGH); digitalWrite(p, LOW); break; case 3: digitalWrite(A4, HIGH); digitalWrite(cc2, HIGH); digitalWrite(cc3, LOW); digitalWrite(A5, HIGH); // accende il punto decimale solo tra la terza e quarta cifra digitalWrite(p, HIGH); break; case 4: digitalWrite(A4, HIGH); digitalWrite(cc2, HIGH); digitalWrite(cc3, HIGH); digitalWrite(A5, LOW); digitalWrite(p, LOW); break; } switch(n) // gestione segmenti { case 0: digitalWrite(a, HIGH); digitalWrite(b, HIGH); digitalWrite(c, HIGH); digitalWrite(d, HIGH); digitalWrite(e, HIGH); digitalWrite(f, HIGH); digitalWrite(g, LOW); break; case 1: digitalWrite(a, LOW); digitalWrite(b, HIGH); digitalWrite(c, HIGH); digitalWrite(d, LOW); digitalWrite(e, LOW); digitalWrite(f, LOW); digitalWrite(g, LOW); break; case 2: digitalWrite(a, HIGH); digitalWrite(b, HIGH); digitalWrite(c, LOW); digitalWrite(d, HIGH); digitalWrite(e, HIGH); digitalWrite(f, LOW); digitalWrite(g, HIGH); break; case 3: digitalWrite(a, HIGH); digitalWrite(b, HIGH); digitalWrite(c, HIGH); digitalWrite(d, HIGH); digitalWrite(e, LOW); digitalWrite(f, LOW); digitalWrite(g, HIGH); break; case 4: digitalWrite(a, LOW); digitalWrite(b, HIGH); digitalWrite(c, HIGH); digitalWrite(d, LOW); digitalWrite(e, LOW); digitalWrite(f, HIGH); digitalWrite(g, HIGH); break; case 5: digitalWrite(a, HIGH); digitalWrite(b, LOW); digitalWrite(c, HIGH); digitalWrite(d, HIGH); digitalWrite(e, LOW); digitalWrite(f, HIGH); digitalWrite(g, HIGH); break; case 6: digitalWrite(a, HIGH); digitalWrite(b, LOW); digitalWrite(c, HIGH); digitalWrite(d, HIGH); digitalWrite(e, HIGH); digitalWrite(f, HIGH); digitalWrite(g, HIGH); break; case 7: digitalWrite(a, HIGH); digitalWrite(b, HIGH); digitalWrite(c, HIGH); digitalWrite(d, LOW); digitalWrite(e, LOW); digitalWrite(f, LOW); digitalWrite(g, LOW); break; case 8: digitalWrite(a, HIGH); digitalWrite(b, HIGH); digitalWrite(c, HIGH); digitalWrite(d, HIGH); digitalWrite(e, HIGH); digitalWrite(f, HIGH); digitalWrite(g, HIGH); break; case 9: digitalWrite(a, HIGH); digitalWrite(b, HIGH); digitalWrite(c, HIGH); digitalWrite(d, HIGH); digitalWrite(e, LOW); digitalWrite(f, HIGH); digitalWrite(g, HIGH); break; } // ritardo tra un refresh e il successivo // attende il ritardo e spegne tutte le cifre delayMicroseconds(ritardo); digitalWrite(A4, HIGH); digitalWrite(cc2, HIGH); digitalWrite(cc3, HIGH); digitalWrite(A5, HIGH); } void setup() { // pin digitali segmenti display pinMode(a, OUTPUT); pinMode(b, OUTPUT); pinMode(c, OUTPUT); pinMode(d, OUTPUT); pinMode(e, OUTPUT); pinMode(f, OUTPUT); pinMode(g, OUTPUT); pinMode(p, OUTPUT); // pin digitali cifre display pinMode(A4, OUTPUT); pinMode(cc2, OUTPUT); pinMode(cc3, OUTPUT); pinMode(A5, OUTPUT); // pin digitali pulsante e led di modalità calcolo pinMode(toggle, INPUT); pinMode(A0, OUTPUT); pinMode(A1, OUTPUT); pinMode(A2, OUTPUT); digitalWrite(A0, HIGH); digitalWrite(A1, LOW); digitalWrite(A2, LOW); // pin dell'anemometro pinMode(getpulsepin, INPUT); } void loop () { pinval = digitalRead(getpulsepin); // quando rileva una pulsazione avvia il calcolo della velocità if ((stato == 0) & (pinval == 1)) { counter = millis(); // contatore per azzeramento display dopo timeout durata = millis() - startime; // intervallo tra due pulsazioni startime = millis(); // setta nuovo startime per pulsazione successiva switch(toggle_status) { case 0: windspeed = (2500.0/durata)*m_s_conv; // calcola velocità in m/s break; case 1: windspeed = 2500.0/durata; // calcola velocità in Km/h break; case 2: windspeed = (2500.0/durata)*nodi_conv; // calcola velocità in Nodi break; } // decodifica le cifre per la visualizzazione n1 = int(windspeed/10); n2 = int(windspeed-(n1*10)); dec = int((windspeed-int(windspeed))*10); } // visualizzazione asincrona sul display // visualizza le stesse cifre per la durata definita da // disp_time (1000 ms) // poi aggiorna le cifre con il nuovo valore di velocità // e resetta il contatore if ((millis() - disp_start) < disp_time) { WriteDig(0,1); if (digit1 != 0) { WriteDig(digit1,2); }; // se le decine sono a zero non accende la cifra WriteDig(digit2,3); WriteDig(digit3,4); } else { disp_start = millis(); digit1 = n1; digit2 = n2; digit3 = dec; } // azzera le cifre "0.0" dopo 2 sec di inattività del sensore if ((millis() - counter) > 2000.0) { n1 = 0; n2 = 0; dec = 0; } // gestione del pulsante di modalità calcolo (antirimbalzo) mode = digitalRead(toggle); // legge lo stato del pulsante if (mode != lastButtonState) { // se lo stato è cambiato resetta // il contatore del tempo lastDebounceTime = millis(); } // se è trascorso l'intervallo di controllo setta il valore //definitivo di toggle_status if ((millis() - lastDebounceTime) > debounceDelay) { if (mode != buttonState) { buttonState = mode; if(buttonState == 1) { if(toggle_status == 0) { digitalWrite(A0, LOW); digitalWrite(A1, HIGH); digitalWrite(A2, LOW); toggle_status = 1; } else if (toggle_status == 1){ digitalWrite(A0, LOW); digitalWrite(A1, LOW); digitalWrite(A2, HIGH); toggle_status = 2; } else { // toggle_status == 2 digitalWrite(A0, HIGH); digitalWrite(A1, LOW); digitalWrite(A2, LOW); toggle_status = 0; } } } } stato = pinval; lastButtonState = mode; }
inizia dalla linea 009 saltando le prime linee di commento: definisci una variabile getpulsepin a cui assegni il valore del pin a cui ha collegato il sensore, considerando che su un Arduino Uno i due pin che puoi utilizzare sono il e o il 3 in grado di leggere un segnale di interrupt;
linee 011-018: definisci le variabili a cui sono connessi i pin relativi ai segmenti del display;
linea 019: definisci il pin a cui è collegato il pulsante;
linee 022-025: imposta i pin a cui sono colegati i 4 pin catodo del display;
linee 027-032: imposta 3 contatori che utilizzerai in seguito per la visualizzazione delle cifre sul display e del tempo di refresh dei led display;
linea 036: imposta una variabile relativa a 20000 microsecondi che equivale a 1/50 di secondo;
linee 038-043: imposta 6 variabili di tipo integer con cui visualizzare le cifre sul display;
linee 046-052: definisci delle variabili di conversione e traccia dei valori rilevati dall’anemometro a coppe, in particolare le prime 3 variabili indicano valori di conversione della velocità del vento;
linee 055-056: imposta le variabili in cui memorizzi la modalità in cui visualizzare il valore di velocità del vento;
linee 059-063: imposta delle variabili di controllo del pulsante e della modalità di debounce ( antirimbalzo );
linea 066: inizia la funzione WriteDig che si preoccupa della visualizzazione del valore sul display;
linee 075-106: in funzione del valore dig che indica la posizione in cui visualizzare la cifra n porti HIGH o LOW il catodo corrispondente al digit. Ad esempio se volessi visualizzare una cifra sul 4* digit devi portare a LOW il pin corrispondente al cc4 e HIGH tutti gli altri catodi;
linee 107-199: definisci i pin da portare HIGH o LOW in funzione della cifra che desideri rappresentare;
linea 202: attendi il tempo di ritardo impostato;
linee 203-206: porta alto i valori relativi ai 4 catodi, in questo modo spegni tutte le cifre;
linee 208-233: la funzione setup() è molto semplice si limita a definire quali pin saranno utilizzati come INPUT e quali come OUTPUT;
linea 236: leggi il valore del pulsante per rilevare il momento in cui la pressione determina l’avvio della rilevazione dell’anemometro a coppe;
linea 238: alla rilevazione del movimento del sensore in funzione del vento ( pinval == 1 ) inizia a rilevare la velocità;
linee 239-241: imposta i contatori per la rilevazione delle pulsazioni e la visualizzazione sul display;
linee 242-253: in funzione del valore impostato per la variabile toggle_status determini la scala di conversione in cui mostrare il valore della velocità del vento rilevata;
linee 255-257: dividi il valore letto in 3 cifre per visualizzarle sul display;
linee 264-271: in funzione del tempo impostato per la visualizzazione delle cifre richiama la funzione WriteDig passandole la cifra e la posizione in cui visualizzarla. Un commento di Federico ti dice che il valore “0” per i decimali non è mostrato;
linee 272-277: se il valore di tempo trascorso è superiore a quello impostato per la visualizzazione resetti il valore di disp_start e assegni a digit1,2 e 3 i valori in cifre da visualizzare successivamente;
linee 279-283: se passano più di 2 secondi senza che il sensore rilevi alcun movimento azzeri tutte le cifre del contatore;
linea 285: leggi il valore digitale relativo alla pressione del pulsante connesso al pin 13;
linee 287-289: se il valore rilevato è differente dal precedente il pulsante ha cambiato stato è quindi stato premuto e puoi reimpostare il contatore lastDebounceTime uguale al valore restituito dalla funzione millis();
linea 292: quando la differenza tra millis() e il valore di lastDebounceTime è maggiore del valore impostato per debounceDelay esegue il codice successivo;
linee 293-315: alla pressione del pulsante varia la modalità di funzionamento da 1 a 2 a 3 ed è indicata dall’accensione dei 3 led;
linea 317: reimposta il valore di stato come pinval ossia il valore letto sul pin 2 dal sensore;
linea 318: reimposta il valore di lastButtonState identico al valore mode;
Buona rilevazione e Grazie Federico per il tuo splendido anemometro a coppe !!!