Anemometro a coppe portatile sketch – quinta parte

Eccoci finalmente alla descrizione dello sketch dell’anemometro a coppe portatile di Federico.

Anemometro a coppe portatile progetto montato 4

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:

  1. Anemometro a coppe portatile – prima parte
  2. Anemometro a coppe portatile – seconda parte
  3. Anemometro a coppe portatile – terza parte
  4. 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 !!!

  • Questo sito ed i suoi contenuti è fornito "così com'è" e Mauro Alfieri non rilascia alcuna dichiarazione o garanzia di alcun tipo, esplicita o implicita, riguardo alla completezza, accuratezza, affidabilità, idoneità o disponibilità del sito o delle informazioni, prodotti, servizi o grafiche correlate contenute sul sito per qualsiasi scopo.
  • Ti chiedo di leggere e rispettare il regolamento del sito prima di utilizzarlo
  • Ti chiedo di leggere i Termini e Condizioni d'uso del sito prima di utilizzarlo
  • In qualità di Affiliato Amazon io ricevo un guadagno dagli acquisti idonei qualora siano presenti link al suddetto sito.

Permalink link a questo articolo: https://www.mauroalfieri.it/elettronica/anemometro-coppe-portatile-sketch-quinta-parte.html

Lascia un commento

Il tuo indirizzo email non sarà pubblicato.

Questo sito usa Akismet per ridurre lo spam. Scopri come i tuoi dati vengono elaborati.