Misuratore di periodi

Ciao a tutti, devo misurare il periodo di oscillazione di un oggetto. Siccome la cosa è urgente spererei di fare con quello che ho in casa. In pratica penserei di utilizzare un light sensor: l'oggetto oscilla e passando davanti al sensore dovrebbe diminuire il valore in uscita. Può funzionare? Chiaramente deve avere un'affidabilità decente, mi servirebbe una misura in centesimi di secondi. Avete dei consigli? Qualche idea per quanto riguarda la parte sw? Grazie mille

dipende dalla lettura del sensore. se normalmente legge > di 3v e la lettura nel passaggio dell’oggetto è < di 2.5v, allora puoi usare una lettura digitale con pulseIn(), in pratica con una sola istruzione hai risolto il tuo problema.

per vedere i valori, usa analogread che spara i valori via seriale, e testi il comportamento del sensore!

grazie dell'aiuto, il sensore è questo http://www.ladyada.net/learn/sensors/cds.html . Il dubbio è: si tratta dell'oscillazione, rapida, di un peso: arduino ce la fa ad elaborare in tempo il cambiamento di stato?

arduino ragiona in microsecondi(circa 4 per ogni istruzione basica), quindi i millesecondi gli fanno un baffo, i centesimi neanche a parlarne!

per intenderci tu devi avere precisione 100Hz, arduino ha precisione ~250.000Hz :)

Perfetto! Thanks ;)

Una cosa: io ho solo resistenze da 15k al momento, nel tutorial di ladyada parlano di resistenze da 10k, può andare la mia?

credo di sì, al massimo leggi uno 0 fisso ma non credo. Il problema ci sarebbe se volessi trasformare la lettura in valore lumen, problema che non hai

Giusto: come potrei fare per misurare il tempo tra un "contatto" e l'altro? Non sai quanto è utile il tuo aiuto :)

prima di tutto leggi il variare del sensore usando un'analog read e vediamo se la soluzione pulseIn() è fattibile (che è la più semplice)

Ehm, cambio di programma: ho scoperto di aver comprato il sensore di hall invece di quello per la luce. Ho dei magneti di cui so il peso, quindi dovrebbe funzionare anche così... il sensore è questo https://www.adafruit.com/products/158#productDescription quindi dovrebbe funzionare con la logica dell'on/off quindi con pulseIn, giusto? Grazie ancora :grin:

In quella pagina c'è scritto che lavora con magneti bipolari perché "sente" solo il polo sud.

Questo non è un problema.. il sensore e il magnete sono venduti nello stesso kit SpokePOV, anche se io li ho comprati separatamente. Il punto è: come faccio a misurare la durata dell'oscillazione del magnete? Pensavo ad un Interrupt, ma sinceramente non ho idea di come proseguire, sono ancora all'inizio ... :P

sempre con la pulseIn, gli interrupt per ora lascali stare, puoi benissimo usare una lettura in loop per cavare i risultati con una precisione più che ottima per te.

ok, ma il loop come lo imposto?

forse è meglio se prima fai un pò di pratica osservando gli esempi contenuti nell'IDE arduino, per capire la struttura del linguaggio, se no è tutto inutile :-)

ho seguito il tuo consiglio e ho buttato giù questo: so che è contrario a qualsiasi logica di buona programmazione, ma dovrebbe funzionare. Con un loop faccio tutto: il primo periodo me lo brucio, visto che sarebbe soltanto mezzo periodo, prendo un riferimento temporale per ogni "contatto" e faccio le sottrazioni. Domani faccio un test effettivo. Potresti consigliarmi un modo più intelligente e funzionale di scrivere il codice? Grazie!!!

int pin = 7; unsigned long time; unsigned long time2; unsigned long time3; unsigned long time4; unsigned long time5; unsigned long time6; unsigned long time7; unsigned long time8; unsigned long time9; unsigned long time10; unsigned long time11; unsigned long time12;

unsigned long t_uno; unsigned long t_due; unsigned long t_tre; unsigned long t_quattro; unsigned long t_cinque; unsigned long t_sei; unsigned long t_sette; unsigned long t_otto; unsigned long t_nove; unsigned long t_dieci; unsigned long t_undici; unsigned long t_dodici; unsigned long periodo;

void setup() { pinMode(pin, INPUT); Serial.begin(9600); }

void loop() { Serial.println('Starting...'); t_uno = pulseIn(pin, HIGH, 5000000); time = millis(); t_due = pulseIn(pin, HIGH, 5000000); time2=millis(); periodo=time2-time; Serial.println('Periodo 1: '); Serial.println(periodo/1000); Serial.println('secondi');

t_tre = pulseIn(pin, HIGH, 5000000); time3=millis(); periodo=time3-time2; Serial.println('Periodo 2: '); Serial.println(periodo/1000); Serial.println('secondi');

t_quattro = pulseIn(pin, HIGH, 5000000); time4=millis(); periodo=time4-time3; Serial.println('Periodo 3: '); Serial.println(periodo/1000); Serial.println('secondi');

t_cinque = pulseIn(pin, HIGH, 5000000); time5=millis(); periodo=time5-time4; Serial.println('Periodo 4: '); Serial.println(periodo/1000); Serial.println('secondi');

t_sei = pulseIn(pin, HIGH, 5000000); time6=millis(); periodo=time6-time5; Serial.println('Periodo 5: '); Serial.println(periodo/1000); Serial.println('secondi');

t_sette = pulseIn(pin, HIGH, 5000000); time7=millis(); periodo=time7-time6; Serial.println('Periodo 6: '); Serial.println(periodo/1000); Serial.println('secondi');

t_otto = pulseIn(pin, HIGH, 5000000); time8=millis(); periodo=time8-time7; Serial.println('Periodo 7: '); Serial.println(periodo/1000); Serial.println('secondi');

t_nove = pulseIn(pin, HIGH, 5000000); time9=millis(); periodo=time9-time8; Serial.println('Periodo 8: '); Serial.println(periodo/1000); Serial.println('secondi');

t_dieci = pulseIn(pin, HIGH, 5000000); time10=millis(); periodo=time10-time9; Serial.println('Periodo 9: '); Serial.println(periodo/1000); Serial.println('secondi');

t_undici = pulseIn(pin, HIGH, 5000000); time11=millis(); periodo=time11-time10; Serial.println('Periodo 10: '); Serial.println(periodo/1000); Serial.println('secondi');

t_dodici = pulseIn(pin, HIGH, 5000000); time12=millis(); periodo=time12-time11; Serial.println('Periodo 11: '); Serial.println(periodo/1000); Serial.println('secondi'); }

ok più o meno ci siamo.... ottimo tentativo ma vediamo come sistemarlo:

1: è inutile ripetere il codice così tante volte: dato che la funzione loop(), come suggerito dal nome, viene eseguita all'infinito (in pratica quando finisce ricomincia), allora basta che scrivi la lettura solo una volta:

void loop()
{
Serial.println('Starting...');
t_uno = pulseIn(pin, HIGH, 5000000);
time = millis();
t_due = pulseIn(pin, HIGH, 5000000);
time2=millis();
periodo=time2-time;
Serial.println('Periodo 1: ');
Serial.println(periodo/1000);
Serial.println('secondi');
}

1: bella l'idea della millis, e poi fare la sottrazione, ma è esattamente quello che fa già la pulseIn()!!! infatti noterai che il valore letto è lo stesso (o al massimo è diverso di 1ms, ma il valore letto da millis è più vicino alla realtà, visto che tu stai leggendo impulso+durata delle istruzioni di pulseIn() )

quindi diventa:

void loop()
{
Serial.println('Starting...');
periodo = pulseIn(pin, HIGH, 5000000);
Serial.println('Periodo 1: ');
Serial.println(periodo/1000);
Serial.println('secondi');
}

(se ottieni letture "nulle" allora devi sostituire HIGH con LOW, dipende dallo stato "a riposo" del tuo sensore, dal tuo codice mi pare che vada sostituito ma per sicurezza lascio tutto così com'è, poi in caso sistemi tu)

3: ovviamente ora scriverà sempre: "Periodo 1:", quindi sistemiamo:

void loop()
{
Serial.println('Starting...');
periodo = pulseIn(pin, HIGH, 5000000);
Serial.print('Periodo ');
Serial.print(numeroLoop);
Serial.print(': ');
Serial.print(periodo/1000);
Serial.println(' secondi');
numeroLoop=numeroLoop+1; //si può anche scrivere "numeroLoop++"
}

4: vogliamo anche evitare di stampare tutte le volte starting, ma stamparlo solo alla prima, quindi spostiamo la println nel setup. quindi codice completo:

int pin = 7;

unsigned long periodo; unsigned long numeroLoop;

void setup() { pinMode(pin, INPUT); Serial.begin(9600); Serial.println('Starting...'); }

void loop() { periodo = pulseIn(pin, HIGH, 5000000); //da cambiare in LOW se non hai delle letture valide Serial.print('Periodo '); Serial.print(numeroLoop); Serial.print(': '); Serial.print(periodo/1000); Serial.println(' secondi'); numeroLoop=numeroLoop+1; //si può anche scrivere "numeroLoop++" }

Grazie infinite per l'aiuto... c'è una cosa che non capisco... pulseIn ritorna la durata dell'impulso, quindi la durata del "contatto" tra magnete e sensore, giusto? A me non serve la durata del contatto, ma l'intervallo tra un contatto e l'altro. Proprio per questo motivo ho deciso di fare un solo loop e non infiniti loop... Nel modo, molto più elegante e pulito :D che hai fatto tu, perdo il riferimento temporale del contatto precedente e non posso capire quanto tempo è passato... Non so se mi sono spiegato bene, ma il problema è questo ;)

no, pulseIn misura la durata di un impulso LOW o un impulso HIGH.

Se quando passa il magnete davanti al sensore l'impulso diventa HIGH, allora se fai una pulseIn settando HIGH leggerai il tempo tra un passaggio e l'altro del magnese, se LOW, il tempo impiegato dal magnete a passare davanti al sensore.

e viceversa, ovviamente. Per questo ti ho scritto che non ero sicuro se devi usare LOW o HIGH: tutto dipende da cosa fa il sensore quando passa davanti il magnete.

Ok, farò come dici tu.... se qualcosa andrà storto ti romperò le scatole di nuovo! Grazie ancora ;)