Buongiorno .. è da un po' di tempo che sto lavorando ad un progetto ma sono fermo a causa di un problema nella programmazione.
L'obiettivo è quello di leggere la velocità di una ruota che gira attorno ad un piccolo albero (cioè in un delta t di 10 secondi rilevare il numero di giri) e "nello stesso istante" rilevare il continuo incremento di giri
Ho a disposizione un sensore a forcella(fototransistor, led ir) e arduino uno
Se potete darmi delle dritte su come impostare il programma
La parte di incremento è semplice e l,ho già fatta ma il resto mi da dei valori sbagliati
int po = 7; //porta di lettura
int i = 0;//blocco
int q = 0;//blocco
unsigned int gt; // numero di giri totali
unsigned int gp; // numero di giri ogni 10 secondi
unsigned int x; // variabile per il millis
void setup() {
Serial.begin(9600);
pinMode (po,INPUT);
}
void loop() {
if ( digitalRead(po) == HIGH and i == 0)
{
gt++;
i = 1;
}
if ( digitalRead(po) == LOW and i == 1)
{
i =0;
}
if ( (millis()-x) % 10000 > 0 and (millis()-x) % 10000 < 1000 and q == 0)
{
x = millis();
gp = gt - gp;
q = 1;
Serial.println ("numero giri ogni 10 sec :");
Serial.println (gp);
Serial.println ("numero giri totali :");
Serial.println (gt);
gt = gp;
}
if ( (millis()-x) % 10000 > 1000 and q == 1)
{
q = 0;
}
}
Ciao, innanzitutto la variabile x la devi definire unsigned long e non int per rispettare il tipo restituito da millis().
Potresti pensare di utilizzare l'interrupt per leggere gli impulsi, ti eviti l'if doppio all'interno del loop e forse è anche più affidabile visto che mentre notifichi il numero di giri vuoi continuare a rilevarli. Impostandolo a RAISING potrebbe fare al caso tuo, nell'isr delle interrupt incrementi sia il contatore parziale che totale dei giri, nel loop non ti resta che verificare se la differenza tra millis() e il valore che hai memorizzato precedentemente nella variabile x è maggiore o uguale al tempo limite (nel tuo caso 10 sec), se si stampi i valori delle variabili e salvi di nuovo in x l'attuale valore di millis()
Per verificare il tempo ti basta una cosa del tipo
Grazie dell'aiuto, ma dopo aver provato con una piccola prova per usare l'interrupt per creare un semplice contatore di giri non mi da un giusto valore ecco il codice
L'obbiettivo ad ogni volta che da LOW passa a HIGH incrementa (con gli if che avevo fatto funzionava con questo no da delle diverse rilevazioni)
Se puoi correggimi dove ho sbagliato Grazie
unsigned int gt; // numero di giri totali
int po = 2; //porta di lettura
void setup() {
Serial.begin(9600);
pinMode (po,INPUT);
attachInterrupt(0, incr, RISING);
}
void loop() {
Serial.println(gt);
}
void incr() {
gt++;
}
Il codice sembra corretto, in che senso ti da valori errati? Ti da più impulsi di quelli effettivi? Se si potresti provare a cambiare leggermente e incrementare sul fronte di discesa in questo modo:
e vedere se si risolve, altrimenti potrebbe servirti un debounce hardware (condensatore+resistenza).
In ogni caso non è che non puoi usare il tuo codice che funziona, dovresti cambiare la parte di verifica del tempo come ti ho indicato nel post #2, il dubbio è che la prate di codice che rileva gli impulsi stia simulando un debounce che potrebbe non funzionare correttamente in tutte le condizioni (velocità, frequenza, ecc.) però, ripeto, se funziona puoi usarlo senza problemi
molto probabilmente i valori errati sono dovuti ai "disturbi elettrici" che un pin impostato come INPUT senza resistenze esterne può ricevere...se si imposta come INPUT_PULLUP si dovrebbe risolvere questo problema (adeguare cablaggi!)...altra cosa è il possibile effetto bouncing .
Ho provato la modifica dello sketch come mi avete consigliato ma la lettura nonostante questo le lettura non corrispondono hai valori reali (cioè interrompo il fascio una volta e nella siriale è present un'altro valore al posto di uno)
Per il debounce hardware non penso ce ne sia bisogno già nel modulo del sensore a farcella l' FC-33 avrà al suo interno delle resistenze di pull down, il condenstore non è presente dici sia questo visto che nonostante abbia cambiao software non cambia
const int po = 2; //porta di lettura
volatile unsigned int gt; // numero di giri totali
void setup() {
Serial.begin(9600);
pinMode (po,INPUT_PULLUP);
attachInterrupt(0, incr, FALLING);
}
void loop() {
}
void incr() {
gt++;
Serial.println(gt);
}
Nonostante abbia messo un condensatore da 82 nF (anche se era indicato 100nF ma con questi condensatori hanno tolleranze di +- 20%) perciò ho pensato vada bene ho provato per l'ennesima volta e non rileva i valori misurati
Non so che fare. Aumento la capacità a 100nF giusti ?
Non so se sia una cosa simile, comunque io ho avuto in passato un problema analogo con un sensore IR a forcella, esattamente un FC-03 (qual è il tuo?).
In pratica ho risolto ma con un escamotage, ossia prendo il segnala output analogico (AO) invece di quello digitale (DO) e con quello sembra funzionare.
Capire no, credo/temo che fosse il modulo difettoso, ma come puoi leggere nel thread che ti ho linkato, ho risolto usando l'uscita analogica al posto di quella digitale.
Nel tuo caso se hai solo quella digitale non credo che, se il problema è come il mio, si possa fare molto se non acquistare un altro encoder dotato di entrambe le uscite...