Buonasra, il codice che segue mi legge la frequenza di un anemometro a coppette con magnete e sensore di hall il tutto ripulito da un circuito per sistemare il segnale quindi niente spurie o rimbalzi.
Purtroppo però, il valore in frequenza che poi andrò a convertire in metri al secondo del vento troppo spesso mi riporta valori esagerati che nulla hanno a che vedere con il reale.
Sono sicuro (quasi) che non è un problema di rimbalzi perchè con un altro sketch usando la funzione millis() non dava problemi.
Suggerimenti su dove mettere mano?
Non credo sia questo il caso, però io per non sbagliare in C quando uso float/double ed uso costanti nei calcoli, forzo la costante con i decimali, nel tuo caso 1000000.0
Provare non costa nulla
mi sembra di capire che tu voglia determinare il tempo totale di un singolo impulso, ossia da quando passa da LOW a HIGH, e fino all'inizio del successivo impulso (HIGH), corretto?
In tal caso io avrei usato un interrupt che viene invocato su RISING, ma nel caso gestirei il timeout di PulseIn (restituisce zero, quindi la divisione per il calcolo frequenza darebbe infinito). A parte questo dettaglio però mi sfugge il senso di questa divisione:
frequency = (1000000)/Ttime;
Qual è il sensore esattamente e quale rapporto esiste tra il numero di impulsi (ossia di giri delle coppette) e la relativa velocità del vento?
Tu qui dividi un milione per il tempo rilevato, che è in millisecondi, quindi, per dire, se il sensore ha un impulso per giro e le coppette fanno 1 giro al secondo, avresti calcolato una velocità del vento di 1000 metri al secondo, il che è ovviamente impossibile a meno di non avere coppette lunghe un chilometro...
Anche io ma in questo caso è ininfluente, il risultato non cambia anche mettendo 1000000.0.
Grazie per le risposte.
L'anemometro ha due magneti quindi doppia "pulsazione".
Ho cercato uno sketch in rete per "Arduino low frequency counter" e ho trovato tre esempi molto simili. Ho tolto le parti che non mi servono relative ai display e aggiunto un fattore di conversione che riportasse valori uguali all'anemometro di precisione che ho.
Poi ora ho aggiunto parti codice per memorizzare le raffiche e inoltre effettivamente mi esce un valore infinito a strumento fermo quindi un altro if{} per forzare a 0.
Accetto consigli per migliorare la situazione quindi mi guarderò gli interrupt come funzionano.
ok, quindi ogni impulso completo rappresenta mezzo giro, per calcolare i giri al secondo devi prendere il tempo in millisecondi di un impulso, raddoppiarlo e dividere 1000 per questo valore. Una volta che hai i giri al secondo, la velocità del vento la devi ottenere conoscendo le specifiche di quel sensore (io ho avuto a che fare professionalmente con anemometri che però non erano con le coppette o ventoline ma di tipo aeronautico a pressione) ossia cisarà pur scritto da qualche parte il calcolo per ottenere la velocità del vento in relazione alla velocità di rotazione no? (se tu avessi postato un link al tuo anemometro magari sarei stato più preciso...)
Su wokwi ho la possibilità di creare un chip custom, ok, fatto il chip.
Una volta in esecuzione pigi sul chip custom è compare il cursore da 0 a 100.
Ora il 0÷100 sarebbe il numero di giri per minuto, cioè rpm.
Oppure il cursore da 0 a n.n in m/s.
Nel file diagram.json scrivo questo:
In C ho il main timer autorepeat ogni 100ms per verificare la modifica del cursore da parte dell'utente.
Se il cursore è modificato devo modificare il timer (es.timer_gpio_clbk) che alza e abbassa il pin di out.
Ecco qual'è la formula inversa?
Ogni quanti millesimi di secondo devo chiamare la callback timer_gpio_clbk()?
Spero di aver linkato le immagini giuste.
L'anemometro è vuoto all'origine, solo meccanica.
Ha due sedi per incollare i magneti opposti a 180° uno dall'altro.
Io poi ho inserito e adattato il resto della basetta.
Qual'è il raggio tra centro asse e centro coppetta?
Secondo i miei calcoli:
raggio = 0.1metri
Vvento = 10km/h (~2.77 m/s)
rpm = ~265
Nel caso di 2 magneti 265 x 2 = 530 rpm.
giri/s = 8.8333 giri (530rpm)
periodo(s) = 1 / 8.8333 = 0,1132
Ma non sono per niente sicuro. Ad esempio 113.2ms per fare mezzo giro, sembra proprio così: 0.1132 x = 0,22641, 1 / 0,22641 = 4,4167 che è circa la metà di 8.83.
PS: scusa se non ti so dare risposta in merito, ma sto cercando di modellare il comportamento di un anemometro e ne so pari a zero.
Uso questa formula per calcolare la velocità del vento con questo anemometro..... (r) raggio, o braccio ( distanza asse coppette in metri), il numero dei giri al secondo (f), e quindi:
Velocità = r * 6.28 * f = Velocità in m/s. Per Velocità in Km/h = (Vm/s * 3,6).
Ok quindi nel tuo caso io farei così (nota anche qualche "ritocco", come il tipo delle variabili Ltime e Ttime, le #define iniziali con la configurazione, e l'uso del simbolo PI ossia il valore di pi greco...):
Per ogni giro ci sono 2 impulsi negativi ognuno largo 10us. La larghezza di 10us è fissa e non dipendente dalla velocità di rotazione, come se il circuito rilevatore introducesse un impulso basso di durata fissa.
Ok grazie per il tempo dedicatomi, ieri sera ho provato a leggere qualcosa sugli interrupt e fare prove.
Pin 2 e 3 per il nano.
Spero di rimettermi sopra al pc sabato per provare i vostri suggerimenti.
Grazie ancora.
Ho provato il codice e funziona, ho aggiunto le cose che mi servivano e cambiato qualche nome variabile.
nella riga:
Ttime = (Htime + Ltime) * 2;
Ho sostituito il 4 con un 2 perchè ho due magneti.
Il problema è unaltro ora, quando la frequenza va sotto il valore 1.0 smette di leggerla e passa tutto a 0.
Il valore della frequenza rimane memorizzato al valore ultimo più basso ecco perchè ho dovuto forzare un frequency = 0 prima del delay
//INIIO Definizione variabili anemometro coppette
#define braccio 0.1 //Diametro anemometro
#define Pin_Anem 3 //Pin ingresso (pin abilitato interrupt)
unsigned long Htime;
unsigned long Ltime;
unsigned long Ttime;
float frequency; //Frequenza impulsi
float Wind_velms; //Velocità vento m/s
float Wind_velmsGUST;//Velocità raffica vento m/s
const long interval = 60000; // Tempo in millisecondi dopo il quale azzerare la raffica
/*
60000ms = 1 minuto
300000ms = 5 minuti
600000ms = 10 minuti
*/
//FINE Definizione variabili anemometro coppette
void setup() {
Serial.begin(9600);
pinMode(Pin_Anem , INPUT);
delay(1000);
}
void loop() {
Wind_velms = 0;
Htime = pulseIn(Pin_Anem, HIGH);
Ltime = pulseIn(Pin_Anem, LOW);
if (Htime > 0 && Ltime > 0) {
// 4 low pulse per revolution
Ttime = (Htime + Ltime) * 2;
frequency = 1000000.0 / Ttime;
Wind_velms = (2.0 * PI) * braccio * frequency;
}
if (Wind_velms <= Wind_velmsGUST){ //Ciclo if else per memoriare la raffica di vento
}
else{
Wind_velmsGUST = Wind_velms;
}
unsigned long previousMillis = 0; //Inizio funzione reset raffica vento dopo intervallo
unsigned long currentMillis = millis();
if (currentMillis - previousMillis >= interval) {
previousMillis = currentMillis;
Wind_velmsGUST = Wind_velms;
}
Serial.print("Frequenza ");
Serial.println(frequency);
Serial.print("Vel. m/s ");
Serial.println(Wind_velms);
Serial.print("Vel. raffica m/s ");
Serial.println(Wind_velmsGUST);
Serial.println("---------------------");
frequency=0;
delay(1000);
}
Ogni tanto con il simulatore aumentando la velocità di rotazione durante la simulazione mi da un valore inferiore, non ho capito se dipende dal fatto che posso variare la velocità all'istante passando da 1 a 1000 in un instante cosa nella realtà non può accadere.
Rimuovendo il delay e stampando con millis ogni 1 secondi dovrebbe essere ancora meglio.
PS: puoi copiare e incollare una decina di valori che stampa l'algoritmo?
PS1: usa il tag code.