Contatore e reset di millis()

Ci sono ho visto alcuni topic che trattano la questione del millis(), io per un progetto che sto portando avanti devo effettuare queste operazioni:

1 - il sensore ad infrarossi rileva uno ostacolo
2 - se l'ostacolo è prossimo al valore 400 (dal Serial.begin) fai partire un contatore che conti 10 secondi
3 - allo scadere dei 10 secondi uno speaker suona

Ora fino qui ci sono riuscito più o meno, il mio problema è:

come posso fare in modo che mettendoci la mano davanti ad ogni esecuzione il processo si resetti e riprenda a contare i 10 secondi canonici?

Da come l'ho scritto in pratica i 10 secondi li conta solo la prima volta, poi se tolgo la mano, il suono smette, ma se la rimetto subito dopo suona immediatamente e non fa passare altri 10 secondi.

Sicuramente ho sbagliato qualcosa. Devo resettare il millis()? Se si come funziona, non l'ho capito molto.

Grazie a chi mi aiuterà.

void parkingDouble() {
DVal = analogRead(DRed);
Serial.println(DVal);

if (DVal > 300) {
if (millis() > 10000) {
for (int i = 0; i < length; i++) {
if (notes == ' ') {
delay(beats * tempo); // rest
* } else {*
playNote(notes, beats * tempo);
* }*
* }*

* // pause between notes*
* delay(tempo / 2);*
* }*
* }*
}[/quote]

cosi dovrebbe andare

void parkingDouble() {  
 unsigned long time=0;
 DVal = analogRead(DRed);
 Serial.println(DVal);
 
 if (DVal > 300) {
  time=millis();
    if (millis() - time > 10000) {
 for (int i = 0; i < length; i++) {
   if (notes[i] == ' ') {
     delay(beats[i] * tempo); // rest
   } else {
     playNote(notes[i], beats[i] * tempo);
   }
 }
   
   // pause between notes
   delay(tempo / 2);
 }
 }
}

Provo subito, e se funziona grazie mille. =)

Niente da fare, adesso non suona nemmeno più. te lo posto tutto.

int PRed=1;
int PVal=0;
int PLed=13;

int DRed=2;
int DVal=0;
int DSound=12;

int length = 3;
char notes[] = "c d c f b ";
int beats[] = { 1, 1, 1};
int tempo = 100;

void setup () {
pinMode(DSound,OUTPUT);
pinMode(PLed,OUTPUT);
Serial.begin(9600);
}

void loop () {
//parkingFree();
parkingDouble();
}

void parkingFree() {
PVal = analogRead(PRed);
Serial.println(PVal);

digitalWrite(PLed,HIGH);

if (PVal > 200)
digitalWrite(PLed,LOW);
}

void parkingDouble() {
DVal = analogRead(DRed);
Serial.println(DVal);

unsigned long time=0;

if (DVal > 300) {
time=millis();
if (millis() - time > 5000) {
for (int i = 0; i < length; i++) {
if (notes == ' ') {
delay(beats * tempo);
* } else {*
playNote(notes, beats * tempo);
* }*
* }*
* delay(tempo / 2);*
* }*
* }*
}
void playTone(int tone, int duration) {
_ for (long i = 0; i < duration * 1000L; i += tone * 2) {
* digitalWrite(DSound, HIGH);
delayMicroseconds(tone);
digitalWrite(DSound, LOW);
delayMicroseconds(tone);
}
}
void playNote(char note, int duration) {
char names[] = { 'c', 'd', 'e', 'f', 'g', 'a', 'b', 'C' };
int tones[] = { 1915, 1700, 1519, 1432, 1275, 1136, 1014, 956 };
for (int i = 0; i < 8; i++) {
if (names == note) {
playTone(tones, duration);
}
}
}
[/quote]*_

Non può funzionare.
Nel codice hai usato:

if (DVal > 300) {
   time=millis();
    if (millis() - time > 5000) {
 for (int i = 0; i < length; i++) {
   if (notes[i] == ' ') {
     delay(beats[i] * tempo);
   } else {
     playNote(notes[i], beats[i] * tempo);
   }

Gli stati dicendo:
Se Dval>300, prendi il valore del tempo e inseriscilo in time.
Successivamente fai time-il valore del tempo (APPENA PRESO PER CUI VERRA' SEMPRE ZERO!!!) e se viene >5000 etc ect.

Ti consiglio la lettura di un articolo scritto espressamente per l'uso di millis dove spiego con attenzione questi aspetti:

Beh ho semplicemente utilizzato il codice suggerito dalla persona sopra. :smiley:
Quindi semmai l'errore lo ha fatti lui, la mia versione non contemplava la presenza di millis()-time. E comunque non funzionava lo stesso.
Ho l'esame domani ho chiesto se si poteva risolvere questa cosa con un paio di consigli rapidi, ma mi rimandi a due pagine che dovrò studiarmi nella mezz'ora di tempo che avrò da qui alle 17. Speravo in un indirizzamento più pratico (ho capito dove è l'errore, ma vorrei anche capire la soluzione), ma vedrò di capirne di più leggendo (anche se la prima parte l'ho letta tempo fa cercando una guida e non ho capito comunque come risolvere il problema).
Grazie comunque.

Jofazer qui non siamo a scuola.
Il mio non voleva essere una "correzione di errore" ma un farti vedere dove probabilmente stesse il problema.
Poi che l'abbia scritto tu o qualcun altro poco importa.
Ti ho rimandato a due pagine perchè le ho scritte apposta: dato che molti utenti, prima o dopo, arrivano al millis e incontrano un sacco di problemi, mi son preso la briga di scrivere questi due articoli del quale non so davvero come tu abbia fatto a leggere la prima parte "tempo fa" dato che l'ho scritto 3gg fa.

Per ultimo se con "indirizzamento" più pratico intendi una riscittua del codice mi sa che è un po' tantino.
Non fraintendermi non voglio essere scortese ma solo dirti che come programmo io riscriverei tutto lo sketch...
A partire da un'unica funzione nel loop() che di fatto fa un loop nel loop per cui non serve praticamente a nulla.

La mia domanda era: come faccio a riazzerarlo ad ogni uso. :smiley:
Mi interessava questo perché guardando in giro è una cosa che non ho capito nella logica del sistema, tutto qua.

A partire da un'unica funzione nel loop() che di fatto fa un loop nel loop per cui non serve praticamente a nulla.

Questa cosa non l'ho capita, che intendi?
Sono due metodi staccati che non c'entrano nulla l'uno con l'altro mi è solo più comodo farlo così perché domani al prof glielo devo spiegare e mostrarli quale è la parte di codice che fa una determinata cosa isolandola dal resto semplifica la comprensione.

Ora vedo cosa riesco a fare leggendo quella guida, ma a prima occhiata non credo risolverò il problema in due minuti. Ripeto è una cosa che non capisco e non mi entra in testa, volevo solo resettarlo dopo un loop.

Grazie comunque.

Beh ho semplicemente utilizzato il codice suggerito dalla persona sopra. Cheesy
Quindi semmai l'errore lo ha fatti lui

è vero che il codice l'ho scritto io ma era da intendere come bozza e non come codice bello e pronto da usare.

Ti do un consiglio banale: fatti uno schema a blocchi di come dovrebbe funzionare il tuo programma e verifica che concettualmente funzioni.

Se vuoi che la sequenza sia:

lettura sensore e controllo valore -> tempo -> melodia

il consiglio che ti do è quello di vedere come funziona una macchina a stati finiti, è un concetto abbastanza facile e che non ti porterà via molto tempo, consiste nello spostarsi a passi lungo la sequenza ovvero:

in questo caso hai 3 passi: lettura, tempo e melodia e per passare da uno all'altro hai bisogno di qualcosa che faccia avvenire la transizione, che potrebbe essere: valore sensore corretto, il tempo scaduto, la melodia completata.
Per abilitare e disabilitare un passo puoi usare delle variabili booleane, la regola fondamentale è che ci sia un solo passo attivo alla volta, quindi appena si verifica una condizione resetti il passo precedente ed attivi il successivo (l'ultimo passo attiva il primo passo, così ricominci).

Probabilmente quello che ho scritto non è chiarissimo perchè ho riassunto troppo, ma anch'io ho poco tempo...se ti documenti su macchina a stati finiti o programmazione a passi poi potresti cogliere il senso pratico di quello che ho scritto.

Buon lavoro

uccio mi avevi scritto: così dovrebbe funzionare.
Ho colto quello che volevi dire nei passaggi del codice e l'ho provato e non funziona.
Ho provato anche con un codice analogo di un altro programma che avevo fatto e che funzionava in questa circostanza non funziona.
Ho provato anche a non usare millis() ma un contatore che assegni un valore unsigned long ad ogni millisecondo passato:

time = time + +1;

Ad ogni valore che legge e che rientra nel parametro di lettura del sensore ad infraroddi superiore a 300.

Quindi mi sono detto se è superiore a 300 e se time arriva a 1000 (esempio) con entrambi questi valori attivi inizia a suonare e così è.

Se tolgo la mano smette.

Se la rimetto, time non rinizia a contare da 1 e quindi suona subito.

Allora ho detto: magari basta riazzerare questo contatore time a zero alla fine del loop per poter ricominciare la lettura una volta che nuovamente l'ìnfrarosso rileva nuovamente il 300 canonico.

E niente, stavolta addirittura non succede nulla dopo che si raggiunge il valore 1000.

A questo punto mi sà che me lo tengo così, vorrà dire che reciterò la parte e lo farò girare una sola volta.

Tutto questo non mi torna proprio, ho anche fatto i diagrammi di flusso tanti simpatici e tutto torna, il principio è facile, ma sulla carta non riesce.

Grazie per gli interventi.

Continuo a provare cose che mi vengono in mente, ma a sto punto boh.

uccio mi avevi scritto: così dovrebbe funzionare.

appunto DOVREBBE

Benissimo, sono riuscito a risolvere con un trucchetto continuando a lavorare sulla variabile time e senza usare il millis(), peccato perché avrei voluto capirlo bene, ma deve funzionare quindi questo è l'importante.

Sono dovuto andar a rivedere dei codici scritti in java all'epoca di ingegneria informatica, ogni tanto torna utile.
Sono soddisfatto, grazie comunque per la pazienza.