sto implementando in un mio sketch una sorta di controllo sicurezza.
In pratica è un pulsante collegato ad interrupt che quando è LOW fa delle azioni.
Funziona correttamente solo che quando viene premuto, oltre a cambiarmi una variabile, vorrei che "resettasse" il cliclo loop facendolo rincominciare e non riattivare da dov'è arrivato prima della pressine del pulsante.
Come potrei fare?
ho provato, dentro la funzione di interrupt come ultimo comando, ad inserire
Purtroppo tu non sai a che punto avviene un interrupt ... esso può avvenire anche nel mezzo di una singola istruzione che è composta da più istruzioni assembler, magari ripeturte più volte e quindi ... alterare dove tornare da una ISR potrebbe avere effetti disastrosi.
Se la cosa ti è indispensabile, c'è un solo modo, che però rallenta parecchio il tutto ... nella ISR settare una flag e nel loop(), per OGNI riga di codice, mettere una IF su quella flag e, se attiva, effettuare un "return;". Il loop() difatti è una normale funzione richiamata in continuazione ed i qualsiasi momento se ne può uscire con una "return;".
max95:
vorrei che "resettasse" il cliclo loop facendolo rincominciare e non riattivare da dov'è arrivato prima della pressine del pulsante.
Come ha detto Guglielmo, non puoi.
Ma aggiungo che sospetto che tu stia usando "male" la loop(). Mi spiego.
La funzione loop() deve contenere tutto ciò che Arduino deve fare ciclicamente (varia migliaia di volte), ed è anche per questo che dentro alla loop() non si mettono generalmente altri cicli come while() o, peggio, i delay().
Inoltre se anche fosse possibile, è comunque altamente sconsigliabile interrompere brutalmente qualche blocco di codice che generalmente è pensato per venir eseguito in sequenza!
Prova ad immaginare una cosa del tipo:
i += 1;
valore[i] = a;
se dopo la prima istruzione partisse l'interrupt e tu bloccassi il codice facendo ripartire la loop() ti ritroveresti con una variabile incrementata ma nel corrispondete array non avresti il valore atteso.
Quindi per fare quello che dici l'unica soluzione è settare un qualche flag dentro all'ISR, ma mettere il test in punti "chiave" ossia dove sicuramente non puoi avere problemi, ad esempio se avessi:
...
void loop ()
{
i += 1;
valore[i] = a;
if (a == 10)
{
b += 2;
elabora(b);
}
if (a == 11)
{
c += 2;
elabora(c);
}
lo modificheresti così:
...
volatile esci = false;
void miaISR()
{
...
if ( digitalRead(3) )
esci = true;
...
}
...
void loop ()
{
i += 1;
valore[i] = a;
if ( esci ) return;
if (a == 10)
{
b += 2;
elabora(b);
}
if ( esci ) return;
if (a == 11)
{
c += 2;
elabora();
}
Ovviamente il tutto va adattato al tuo codice (che non ci hai fatto vedere).
docdoc:
... Quindi per fare quello che dici l'unica soluzione è settare un qualche flag dentro all'ISR, ma mettere il test in punti "chiave" ossia dove sicuramente non puoi avere problemi ...
... che è l'alternativa che avevo suggerito nel mio post #1
scusate ma ho avuto modo di "studiare" e provare solo in questi giorni.
Innanzitutto grazie infinite dei preziosi consigli come sempre. Ho colto ciò che mi avete spiegato e sono sceso ad un compromesso: tre pulsanti pulsanti con funzioni differenti.
se premo pulsante EMERGENZA viene portata alla conclusione l'ultima operazione e il sistema resta in attesa che venga premuto il pulsante START (e riprenderà da dov'è arrivato) oppure il pulsante RESET (ricomincerà dall'inizio).
Il compromesso è che prima di giungere a tale condizione l'algoritmo conclude l'ultimo gruppo di comandi che sta eseguendo.