Ciao a tutti ragazzi. Mi trovo in difficoltà nel fermare il loop tramite pulsante.
Praticamente ho fatto delle prove questo è il codice:
void loop()
{
readButtons(); //I splitted button reading and navigation in two procedures because
navigateMenus();
switch(ModCorrente){
case StatoStart:
navigateMenus(); //in some situations I want to use the button for other purpose (eg. to change some settings)
lcd.clear();
i++;
lcd.print(i);
digitalWrite(wakepin, HIGH); //turn wakeup/focus on
delay(wakeup); //keep focus
digitalWrite(wakepin, LOW); //turn wakeup off
delay(wakewait); //wait
digitalWrite(outpin, HIGH); //press the shutter
delay(shutter_on); //wait the shutter release time
digitalWrite(outpin, LOW); //release shutter
delay(shutter_off); //Intervallo tra uno scatto e l'altro
rotateDeg(360, 1); //Movimento motore
delay(500); //delay motore per evitare vibrazioni prima dello scatto
break;
}//switch
} //loop()...
Vorrei poter fermare tramite pulsante il ciclo.
Se metto un if con una costante ad esempio
if(i<4){
lcd.clear();
i++;
lcd.print(i);
digitalWrite(wakepin, HIGH); //turn wakeup/focus on
delay(wakeup); //keep focus
digitalWrite(wakepin, LOW); //turn wakeup off
delay(wakewait); //wait
digitalWrite(outpin, HIGH); //press the shutter
delay(shutter_on); //wait the shutter release time
digitalWrite(outpin, LOW); //release shutter
delay(shutter_off); //Intervallo tra uno scatto e l'altro
rotateDeg(360, 1); //Movimento motore
delay(500); //delay motore per evitare vibrazioni prima dello scatto
} break;
Il tutto funziona alla perfezione. una volta arrivato a 4 si ferma.
Mentre se faccio una cosa di questo genere:
if(digitalRead(Bottone) == LOW){
lcd.clear();
i++;
lcd.print(i);
digitalWrite(wakepin, HIGH); //turn wakeup/focus on
delay(wakeup); //keep focus
digitalWrite(wakepin, LOW); //turn wakeup off
delay(wakewait); //wait
digitalWrite(outpin, HIGH); //press the shutter
delay(shutter_on); //wait the shutter release time
digitalWrite(outpin, LOW); //release shutter
delay(shutter_off); //Intervallo tra uno scatto e l'altro
rotateDeg(360, 1); //Movimento motore
delay(500); //delay motore per evitare vibrazioni prima dello scatto
} break;
Funziona soltanto se tengo il pulsante pigiato. Come dovrei fare per farlo funzionare al click del pulsante?
Devi usare la funzione millis, guarda l'esempio BlinkWithoutDelay presente nell'IDE, e fare un check sul trascorrere del tempo. I delay bloccano il codice.
PS:
cmq questa è una cosa stradetta sul forum, bisognerebbe usare un po' la funzione "Cerca".
leo72:
Devi usare la funzione millis, guarda l'esempio BlinkWithoutDelay presente nell'IDE, e fare un check sul trascorrere del tempo. I delay bloccano il codice.
PS:
cmq questa è una cosa stradetta sul forum, bisognerebbe usare un po' la funzione "Cerca".
ti ringrazio, anche se non riesco a trovare il nesso. In questo caso non è una questione di delay, in quanto se nel codice metto:
La funzione loop() é quella che si ripete di continuo. Se intendi quella come "loop" Ti ripondo che non si deve fare (si puó, ma blocchi l'esecuzione del Tuo programma).
Per fare che il codice viene eseguito solo 1 volta memorizzi che é stato premuto un pulsante e fai quello che vuoi fare. Poi cancelli la variaabile quando il pulsante viene rilasciato.
if (digitalRead(pulsante) ==1 && premuto ==0) // viene eseguito la prima volta che vede il pulsante premuto
{
premuto =1
fai quello che devi fare)
}
if (digitalRead(pulsante) ==0 && premuto ==1) premuto =0
Non ho detto che non puoi uscire dalla funzione loop() per esempio con un break(). Puoi fermarla con un delay() oppure eseguire in modo condizionato quello che vuoi fare:
void loop()
{
if (pulsante premuto ) accendi LED
}
Perfetto. Sono riuscito a bloccare come voglio il loop. Adesso però, mi si presenta un altro problema ovvero, una volta uscito non mi permette di ripartire.
readButtons(); //I splitted button reading and navigation in two procedures because
navigateMenus();
switch(ModCorrente){
case StatoStart:
if(i<4){
lcd.clear();
i++;
lcd.print(i);
}
break;
}//switch
Allora arrivati a 4 giustamente il conteggio s'interrompe. A questo punto io clicco il tasto esc e ritorno al menù sul lcd. quando vado per rientrare per riavviare il timer, questo non parte più una seconda volta. Ho provato a mettere anche un else con i=0; ma naturalmente il conteggio ricomincia ciclicamente. Mentre se metto nell'else break; i=0; resto bloccato.
Scusate l'intromissione, ma vedo errori di logica nel codice. Lo switch..case mi sembra usato un po' male. Inoltre senza il resto del programma, è difficile capire cosa possa non andare..
Ah.. un'altra cosa:
Mentre se metto nell'else break; i=0; resto bloccato.
un'assegnazione dopo un break non è corretto. Non fa più parte del blocco di codice dell'if..else e non puoi sapere dove e quando verrà eseguita
un'assegnazione dopo un break non è corretto. Non fa più parte del blocco di codice dell'if..else e non puoi sapere dove e quando verrà eseguita
infatti facendo un controllo ho visto che la i mi resta sempre di valore 4 e non riesco a portarla a 0. Per questo poi, successivamente, non riesco più a rientrare nell'if... come posso fare a resettare la variabile i?
Ho messo la parte del menù togliendo le cose tipo gestione motore che in questo caso non serviva.
Praticamente vorrei riuscire a bloccare il loop(oppure un ciclo for usando la classe menuUsed). Come da codice (in questo caso nel loop) riesco a bloccare il ciclo, ma poi una volta uscito dalla voce menù, non riesco a fare ripartire il timer.
Molto di quel codice io non ho idea di come funzioni. Mi sembra di capire che vuoi eseguire il codice sono una volta. Poi vuoi anche decidere quando è il caso di rieseguire il codice nuovamente come se fosse la prima volta.
una variabile globale oneShot = 0;
loop()
{
if (!oneShot) // se è falsa incrementa solo una volta in quanto qui non ci entrerà più
oneShot++;
if (oneShot == 1) { // oneShot non può che essere uno e quindi esegue il tuo codice
chiama "miafunzione"
terminata la funzione divi fare in modo che in questa if non ci entri nuovamente quindi
oneShot = 2;
}
}
E solo psedo code. Quando vuoi eseguire nuovamente "miafunzione", azzeri la variabile oneShot. Dai anche una guardata alla macchina a stati finiti, per capire cosa sono gli stati sequenziali, di transizione ecc. Nel playground c'è anche una lib FSM, ma non mi chiedere come funziona perchè non ho approfondito.
La cosa che rompe parecchio con Arduino è che non puoi usare la programmazione modulare dichiarando una variabile che mantiene lo stato ed è visibile solo all'interno del modulo. Quindi sei costretto a fare uso di variabili globali che consumano ram. L'altra fregatura che Arduino permette di fare cose visimamente importanti, anche a chi non si è mai scontrato con i problemi di logica di base. In pratica sei fermo per una cosa banale.
MauroTec:
Molto di quel codice io non ho idea di come funzioni. Mi sembra di capire che vuoi eseguire il codice sono una volta. Poi vuoi anche decidere quando è il caso di rieseguire il codice nuovamente come se fosse la prima volta.
una variabile globale oneShot = 0;
loop()
{
if (!oneShot) // se è falsa incrementa solo una volta in quanto qui non ci entrerà più
oneShot++;
if (oneShot == 1) { // oneShot non può che essere uno e quindi esegue il tuo codice
chiama "miafunzione"
terminata la funzione divi fare in modo che in questa if non ci entri nuovamente quindi
oneShot = 2;
}
}
E solo psedo code. Quando vuoi eseguire nuovamente "miafunzione", azzeri la variabile oneShot. Dai anche una guardata alla macchina a stati finiti, per capire cosa sono gli stati sequenziali, di transizione ecc. Nel playground c'è anche una lib FSM, ma non mi chiedere come funziona perchè non ho approfondito.
La cosa che rompe parecchio con Arduino è che non puoi usare la programmazione modulare dichiarando una variabile che mantiene lo stato ed è visibile solo all'interno del modulo. Quindi sei costretto a fare uso di variabili globali che consumano ram. L'altra fregatura che Arduino permette di fare cose visimamente importanti, anche a chi non si è mai scontrato con i problemi di logica di base. In pratica sei fermo per una cosa banale.
Spero ti aiuti.
Ciao.
Grazie Mauro molto interessante. Intanto sono riuscito a fare quello che volevo. E' vero ero fermo per una banalità. Comunque approfondirò quegli aspetti che mi hai detto che mi torneranno sicuramente utili!
A me pare che non resetti mai "i" per cui è normale che nel ciclo non ti ci rientra più. Ho visto solo un incremento di "i" ma non un suo riazzeramento.