anemometro molto semplice con reed

ciao a tutti

ho realizzato un anemometro in inox, al cui albero centrale è attaccata una calamita che apre e chiude un ampolla reed.

avrei la necessità di calcolare la velocità di rotazione (se no che anemometro è!) però riscontro alcune piccole difficoltà.
ho riadattato uno dei codici base alle mie necessità:

const int LED = 13;
const int BUTTON = 7;

int val = 0;
int state = 0;
int conta =0;
int aperto=0;
float tempo = 0;
float delta;


void setup() {
  
  Serial.begin(9600);
  
  pinMode(LED,OUTPUT);
  pinMode(BUTTON,INPUT);
  tempo = 0;
  conta = 0;
}

void loop() {
  

  tempo = tempo+1;
  delta = millis() - tempo;
  
  val = digitalRead(BUTTON);
  
  if (val == HIGH) {
    state = 1 ;
    
    if (aperto == 1) {
      
      conta = conta + 1;
      
      aperto = 0;
      
    }
   
    
  } else {
    
    state = 0;
    
        if (aperto == 0) {
      
      aperto = 1;
      
    }
  }
  
  if (state == 1) {
    
    digitalWrite(LED,HIGH);
    
  } else {
    
    digitalWrite(LED,LOW);
    
  }


if (delta>=1000){

  Serial.println(1000*conta/delta);
  conta = 0;
  tempo = millis();

}

}

come si vede, la variabile delta regola il tempo di campionatura (cioè conto il numero di giri per ogni secondo, e passato tale lasso di tempo la variabile "delta" viene azzerata)

il fatto è che così come è scritto il codice non mi stampa su monitor seriale un bel niente.
io vorrei fargli stampare un valore al secondo, ma non posso usare delay, dato che durante il tempo di delay appunto non misurerebbe la variabile "conta" (che è quella che appunto mi conta quante volta è stato chiuso il reed)

come posso fare?

grazie a tutti!

tommaso

Poiché è evidente che mentre il micro è impegnato ad inviare dati sulla seriale potrebbe perdere dei conteggi, ti consiglio di usare un piedino di external interrupt (il 2 od il 3) per conteggiare gli impulsi.
Guarda la documentazione a riguardo.

non capisco il senso di questo codice:

tempo = tempo+1;
  delta = millis() - tempo;

Ciao Uwe

Se per questo, non capisco neppure perchè tempo di tipo float (ovvero con virgole)

float tempo = 0;

Lo aumenti di 1, come la millis() ti basta un unsigned long che arriva 4 miliardi, circa 49 giorni

E poi tempo come dice @uwe, a che serve? Messo come l'hai scritto aumenta di uno a ogni loop() ma non ha una tempistica certa, dipenda da quanto tempo impiega l'Arduino ad eseguire tutto il codice contenuto nella loop()

cyberhs:
Poiché è evidente che mentre il micro è impegnato ad inviare dati sulla seriale potrebbe perdere dei conteggi, ti consiglio di usare un piedino di external interrupt (il 2 od il 3) per conteggiare gli impulsi.
Guarda la documentazione a riguardo.

Vorrei fare una precisazione. Anche la seriale è gestita da interrupt per cui il codice non si blocca.
Casomai si potrebbe fare un discorso più completo. Leggendo il pin con un digitalWrite potresti perderti il segnale se questo arriva nel momento in cui non stai leggendo il pin, perché la digitalWrite legge lo stato del pin in un dato istante. Diversamente, un interrupt agganciato ad un pin è un evento che viene registrato dal microcontrollore in un registro interno e quindi richiamato comunque.

ciao
dal mio punto di vista, lasciando perdere interrupt o altro, tu chiedi:

…io vorrei fargli stampare un valore al secondo,…

la logica potrebbe essere questa:
-tempo = millis
-azzeri conta
-incrementi conta quando arriva impulso se millis - tempo < 1000
-quando millis - tempo >= 1000 ti fai i tuio calcoli della velocità e la spari alla seriale

  • ricomincia.
    Così arduino sta li ad aspettare il segnale in ingresso e non deve fare niente altro.
    Non ho mai lavorato con un sensore reed quindi non so se potrai avere problemi di debounce, inoltre non credo che questo anemometro avrà una frequenza di campionatura altissima in quanto, se ho capito bene al cui albero centrale è attaccata una calamita mi darà un impulso al giro.

ciao
pippo72

Grazie a tutti per le risposte

il concetto da cui partivo è :

ogni inizio loop la variabile tempo viene incrementata di uno, e contemporaneamente la variabile conta viene incrementata ogni volta che il reed viene attivato
quando la variabile delta (cioè la differenza tra millis e tempo) arriva a 1000 (cioè, nelle mie intenzioni, dopo un secondo), viene visualizzatya la variabile "conta", cioè il numero di giri che sono stati gfatti un un secondo, e contemporaneamente la variabile tempo viene "aggiornata" a millis() (in modo che la variabile "delta" risulti uguale a zero, così da poter ri iniziare il ciclo.

di fatto questo metodo ha diversi punti deboli, come mi fate giustamente notare "tempo" viene incrementata di uno ogni loop, ma non significa che ogni loop impieghi un ms, quindi quando delta arriva a 1000 potrebbe essere passato meno di un secondo.

sono (come avrete capito) neofita, percui chiedo: c'è un comando per "temporizzare" millis? nel senso, come faccio a chiedergli "visualizza conta (poi azzeralo) ogni volta che millis() raggiunge un valore multiplo di 1000"?

Usi una variabile di appoggio, tipo lastMillis in cui memorizzi il momento in cui inizi a contare 1000 millisecondi e poi con un semplice IF sai se ne sono passati 1000 ...

Prova a studiarti come si usa la millis() prima QUI, poi QUI ed infine leggi anche QUI ... vedrai che ti sarà tutto più chiaro :wink:

Guglielmo

grazie mille, in effetti era quello che stavo cercando di fare, anche se in maniera un po maldestra.

ora funziona!

tuttavia mi sto picchiando con un lcd 20x4, tra poco scriverò un post di aiuto!