Aspettare un evento e ripartire con il ciclo

Salve a tutti, è da un paio di giorni che mi sono imbattuto nella scrittura di uno sketch che non riesco a risolvere.
Precisamente quello che vorrei fare è la seguente cosa:

dentro il loop() inizio con una parte di codice, poi vorrei aspettare che si verifichi una condizione (chiusura di un pulsante) e quando questo è avvenuto continuare con un altro pezzo di codice.

Detto a parole sembra una banalità, ma sinceramente non riesco ad uscirne fuori con un semplice if, in quanto se la condizione non è verificata quando interrogo l'if si esce dal ciclo e arduino ricomincia a leggere la prima parte del codice!!!

Non sò se mi sono spiegato bene, praticamente vorrei che arduino esegue la prima parte, aspetta il verificarsi della condizione (che può avvenire anche dopo parecchi secondi) e quando questa è verificata, continua con l'altro pezzo di codice.

Riuscite ad aiutarmi? Se non mi sono spiegato bene, ditelo pure!!!

Grazie a chiunque voglia rispondermi!!!

Invece dell'IF ... prova a guardare la sintassi del while() :wink:

Guglielmo

gpb01:
Invece dell'IF ... prova a guardare la sintassi del while() :wink:

Guglielmo

Non sarebbe meglio usare due if al posto del while? Capisco che la soluzione è corretta ma con il while si può gettare le basi per i successivi delay :slight_smile: mentre con i due if (il secondo testa se la condizione della prima parte del codice è stata soddisfatta nel caso semplice descritto) non si approccia meglio all'idea che il loop viene sempre eseguito di continuo nelle mcu e quindi occorre pensare il codice in tal senso?

fabpolli:
Non sarebbe meglio usare due if al posto del while? Capisco che la soluzione è corretta ma con il while si può gettare le basi per i successivi delay ...

Non capisco ... quali basi per quale delay() ? ? ? :o

Fai semplicemente una while() come condizione controlli il bottone e lasci il corpo vuoto. Appena la condizione diveta "FALSE" esci dal while() e prosegui ...
... dove è il delay() ?

Guglielmo

Quindi il While dovrebbe essere usato solo per aspettare che si verifichi la condizione di pulsante chiuso.

E' corretto scrivere:

  • primo blocco di istruzioni

  • while(stato pulsante=chiuso)

-secondo blocco istruzioni

  • terzo blocco istruzione

è corretto cosi?

Grazie sempre!

La while() è un ciclo … tale ciclo viene ripetuto fino a quando la condizione impostata è TRUE. Quando la condizione impostata diventa FALSE, si esce dal ciclo. Nessuno ti obbliga a mettere qualche cosa nel ciclo che, quindi, può anche essere vuoto : while(condizione) {}

A questo punto … prova a buttare giù il codice e vediamo :wink:

Guglielmo

P.S.: Ovviamnete, questo è valido se e solo se, nel frattempo NON devi fare altro (un ciclo come quello è bloccante), altrimenti, se contemporaneamente occorre fare altre cose, bisogna scegliere un’altra strada.

gpb01:
… dove è il delay() ?

Guglielmo

Mi sono espresso male, non intendo dire che c’è il delay ma che il modo di pensare il software in quel modo potrebbe essere forviante e portare a scappatoie come il dalay al posto di millis che richiede un modo di pensare il programma adatto alle mcu.
Ovvero la domanda riformulata è “Non è meglio evitare di introdurre zone bloccanti (come il while) all’interno del loop ma pensare il programma in modo che esegua sempre tutto il loop e vincolare alcune “funzioni” in base alle condizioni di esecuzione in un programma per mcu?”
Da quello che ho capito qui sul forum è sempre bene non interrompere il normale flusso del programma (se non in rari casi) e eseguire il solo codice necessario demandando al loop per l’appunto di girare di continuo, ma magari ho capito male, da questa considerazioen la mia domanda.

avevo risposto a Ghibli ma mi hai anticipato :wink:

fabpolli:
Ovvero la domanda riformulata è "Non è meglio evitare di introdurre zone bloccanti (come il while) all'interno del loop ma pensare il programma in modo che esegua sempre tutto il loop e vincolare alcune "funzioni" in base alle condizioni di esecuzione in un programma per mcu?"

Non sono affatto d'accordo e ho espresso questa cosa più e più volte.

Il delay() è utilissimo in centinaia di casi ove NON c'è altro da fare che attendere. Idem per cicli di attesa di una condizione.

NON "demoniziamo" il concetto di "bloccante" ...

... ci sono infiniti casi dove il codice PUÒ/DEVE essere bloccante e altrettanti infiniti in cui il codice NON PUÒ/NON DEVE deve assolutamnete esserlo.

Quindi .. TUTTO DIPENDE DA QUELLO CHE DEVI FARE.

Guglielmo

P.S.: Nota bene che questo NON significa che uno NON deve sapere scrivere codice non bloccante, anzi, tutt'altro, uno deve essere in grado di affrontare qualsiasi situazione, sia quella in cui occorre bloccare il codice, sia quella in cui assolutamnete non lo si può bloccare.

Un ultimo dubbio: quindi se io arrivo al While() e la condizione è falsa lui continua ad aspettare che la condizione sia vera? in questo modo è come se sto "di guardia" aspettando che si verifichi la condizione.... ed una volta verificata continua con il codice sotto... corretto??

Ghibli:
Un ultimo dubbio: quindi se io arrivo al While() e la condizione è falsa lui continua ad aspettare che la condizione sia vera? in questo modo è come se sto “di guardia” aspettando che si verifichi la condizione… ed una volta verificata continua con il codice sotto… corretto??

Si, corretto. — avevo letto male la domanda — NO, se arrivi al while() e la condizione è falsa, lui esce subito. la condizione deve essere vera (in pratica rimane nel ciclo fino a quando la condizione è VERA).
Però, ad esempio per il tuo caso, la condizione può essere la stessa funzione che legge il bottone

while (digitalRead(bottone)) {}

rimane nel while() fino a quando la digitalRead() gli da HIGH ed esce quando è LOW. Se usi l’operatore negazione (’!’) inverti la condizione.

Una piccola raccomandazione … per evitare brutte sorprese, NON considerare i pulsati come “ideali”, ovvero che se non premuto è, ad esempio, aperto e quando premuto è subito chiuso … in realtà il comportamneto di un bottone “reale” è questo :

… ovvero quando chiudi il contatto (così come quando lo riapri) hai una serie di “rimbalzi” che vengono tutti letti come pressione/rilascio da parte di Arduno.

Quindi, quando si leggono dei bottoni, si debbono applicare tecniche di “debouncing” (cerca con Google).

Esistono tecniche SW ed esistono tecniche HW. Per quest’ultime ti allego un utile pdf.

Guglielmo

debouncing_hw.pdf (22.8 KB)

gpb01:
Non sono affatto d'accordo e ho espresso questa cosa più e più volte.

Il delay() è utilissimo in centinaia di casi ove NON c'è altro da fare che attendere. Idem per cicli di attesa di una condizione.

NON "demoniziamo" il concetto di "bloccante" ...

... ci sono infiniti casi dove il codice PUÒ/DEVE essere bloccante e altrettanti infiniti in cui il codice NON PUÒ/NON DEVE deve assolutamnete esserlo.

Quindi .. TUTTO DIPENDE DA QUELLO CHE DEVI FARE.

Guglielmo

P.S.: Nota bene che questo NON significa che uno NON deve sapere scrivere codice non bloccante, anzi, tutt'altro, uno deve essere in grado di affrontare qualsiasi situazione, sia quella in cui occorre bloccare il codice, sia quella in cui assolutamnete non lo si può bloccare.

Ok, grazie, pienamente d'accordo con te per il P.S., per tutto quanto espresso prima è chiarissimo e seguirò questi consigli per le future necessità/risposte ad altri

Grazie tante… Farò tutto quello che mi hai detto e speriamo funzioni tutto!!!

Ghibli:
Grazie tante..... Farò tutto quello che mi hai detto e speriamo funzioni tutto!!!

Attento alla mia correzione nel post #9 ...

Guglielmo

Ok Guglielmo ho letto la tua correzione. :wink: :wink: :wink:

Ho letto un po’ sul fenomeno del “debouncing” ed ho deciso di adottare il metodo HW. Riguardo a questo volevo fare un ulteriore domanda: nel debouncing con pull-down la resistenza indicata con 100 è di 100 Ohm o 100 kOhm? Vanno benissimo quelle da 1/4 di watt… Corretto? Grazie sempre!!!

con 100 si intende 100 Ohm, altrimenti viene indicato come 100K per i kiloOhm, 100M per i 100 MegaOhom, ecc.
1/4w vanno bene

Grazie.... un ultima cosa il condensatore è in poliestere, non elettrolitico.... corretto?

Ghibli:
Grazie.... un ultima cosa il condensatore è in poliestere, non elettrolitico.... corretto?

... guarda la capacità ... elettrolitico ti sembrerebbe normale ? ? ? :o ... o magari è più facile che sia ceramico ?

Guglielmo

Attenzione
se adoperi questo metodo del while in questa maniera, il ciclo si bloccherà OGNI VOLTA che riaprirai l'interruttore.
Se vuoi attendere solo una volta, solo la prima volta, e poi non deve fermarsi più anche se modifichi lo stato dell'interruttore o del pulsante, non è sufficiente usare questo codice ma dovrai apportare una piccola correzione.

Un altro dubbio: se volessi mettere 2 pulsanti in "and" dentro il while è corretto scrivere ad esempio:

while((P1==LOW) && (P2==LOW)){ leggi P1 e P2}
continua il loop......

Praticamente fino a quando P1 e P2 non sono chiusi, il micro controllore dovrebbe leggere sempre il loro stato, fin quanto tutti e 2 sono chiusi; considerando che P1 e P2 sono i pin di una "rete" pull-down, quando sia P1 che P2 sono aperti ho LOW in entrambi.

Ho scritto questo codice, e se metto un solo pulsante funziona perfettamente, se ne metto 2 in and, basta che si chiuda uno dei 2, e si esce dal while... cosa sbaglio??

Grazie in anticipo!!!