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 !!!



Il blog mauroalfieri.it ed i suoi contenuti sono distribuiti con Licenza