Salto fine codice dopo interupt

Durante l'esecuzione del codice, alla pressione di un pulsante ( gestito come interupt sul pin 2) il programma salta ad eseguire una funzione() per poi ritornare al punto in cui è stato interrotto dall'interupt.

Io vorrei che non appena venga eseguita la funzione() anziché tornare al punto precedente l'interruzione, il programma riprenda esattamente dall'inizio ""void loop()"", ma non ho capito come fare.

xzero2

ehm, una richiesta strana e insolita.

Spiegaci meglio quello che vuoi fare perché la soluzione alla tua idea é parecchio complicata: goto e eliminare parecchi byte dallo stack per evitare che quello vada in overflow a causa di indirizzi di ritorno non cancellato. Per farlo servirebbe una profonda conoscenza del compilatore / linguaggio macchina prodotto dal compilatore. Inoltre il numero di byte parcheggiati sullo stack e percui da cancellare dipende da piú fattori come in quale funzione / ciclo for while switch ecc o if era prima del interrupt

Come detto spiegaci la necessitá della Tua richiesta per potrti suggerie un alternativa piú semplice.

Non é possibile che non usi l'interrupt per leggere il Tuo pulsante?

Ciao Uwe

Richiesta strana.. sì. ;)

Il loop è ripetuto di continuo, all'inizio ci torni sempre. Se vuoi saltare una porzione di codice potresti aggiornare da dentro la tua ISR una variabile globale, in modo che il tuo programma, quando si accorge che tale variabile è stata cambiata, evita di eseguire il resto del programma, che separi mettendo dentro ad una funzione. Ad esempio:

boolean interruptEseguito = false
.......
void loop() {
  if (!interruptEseguito) {
    cicloPrincipale();
  } else {
    interruptEseguito = false;
  }
}

In questo modo cicloPrincipale viene eseguito solo se l'interrupt non è scattato.

2) La seconda alternativa è quella di inserire alla fine della routine di interrupt questo comando:

asm volatile (" jmp 0");

Salta all'indirizzo $0000, che equivale al riavvio del tuo codice. Attenzione che questo è un reset software, per cui perdi tutti i dati elaborati dal programma.

leo72: Richiesta strana.. sì. ;)

Il loop è ripetuto di continuo, all'inizio ci torni sempre. Se vuoi saltare una porzione di codice potresti aggiornare da dentro la tua ISR una variabile globale, in modo che il tuo programma, quando si accorge che tale variabile è stata cambiata, evita di eseguire il resto del programma, che separi mettendo dentro ad una funzione. Ad esempio:

boolean interruptEseguito = false
.......
void loop() {
  if (!interruptEseguito) {
    cicloPrincipale();
  } else {
    interruptEseguito = false;
  }
}

In questo modo cicloPrincipale viene eseguito solo se l'interrupt non è scattato.

2) La seconda alternativa è quella di inserire alla fine della routine di interrupt questo comando:

asm volatile (" jmp 0");

Salta all'indirizzo $0000, che equivale al riavvio del tuo codice. Attenzione che questo è un reset software, per cui perdi tutti i dati elaborati dal programma.

Leo il Tua primo suggerimento non funziona vome xzero2 vuole perché non fa ripartire il loop() da qualsiasi posizione da dove viene interrotto dal interrupt ma solo da certe determinate dove hai inserito il if, anche se puoi inserirlo in piú posizioni del codice.

La seconda soluzione fa perdere tutti i valori delle variabili memorizzati nella ram.

Il jmp $0000 fa eseguire il bootloader o no?

Ciao Uwe

uwefed: Leo il Tua primo suggerimento non funziona vome xzero2 vuole perché non fa ripartire il loop() da qualsiasi posizione da dove viene interrotto dal interrupt ma solo da certe determinate dove hai inserito il if, anche se puoi inserirlo in piú posizioni del codice.

Sì, vero. Ma era un'idea, non sapendo esattamente cosa vuol fare lui.

La seconda soluzione fa perdere tutti i valori delle variabili memorizzati nella ram.

Il jmp $0000 fa eseguire il bootloader o no?

Ciao Uwe

Jmp$0000 non esegue il bootloader, il bootloader è posto molto più avanti nella memoria.

Allora aspettiamo una risposta e vediamo per cosa serve a xzero2 questa cosa particolare.

Ciao Uwe

leo72: Jmp$0000 non esegue il bootloader, il bootloader è posto molto più avanti nella memoria.

Se salti alla locazione 0 è un reset software a tutti gli effetti e fai avviare anche il bootloader perché a quella locazione c'è un jump alla prima locazione di memoria dove si trova il bootloader, se ci pensi bene anche il reset hardware ha come effetto di far partire l'esecuzione del programma dalla locazione 0.

Intanto grazie a tutti per le risposte.

Quello che sto facendo è una attrezzatura per testare dei quadri elettrici.

Tanto per spiegarvi le cose:

Inizialmente con arduino alla pressione di un tasto "START" do 220 al quadro e controllo che ci siano e siano corrette 5 basse tensioni presenti sul quadro;

a questo punto utilizzo 22 uscite di arduino ( che simulano interruttori e pulsanti ) e 9 ingressi ( che simulano elettrovalvole, lampade ecc) .

In 25 passi imposto varie combinazioni di uscite e mi aspetto altrettante combinazioni di ingressi.

Fin qui tutto ok.

Quello che volevo fare io a questo punto è:

Se per caso durante il test qualche cosa non va, in qualsiasi passo mi trovi ( fumate varie ecc) premendo il pulsante ""Emergenza"" collegato al pin 2 di arduino, quindi come segnale di interrupt, il programma deve passare subito ( quindi non posso mettere il controllo di un ingresso generico) ad una funzione ( che casualmente ho chiamato emergenza() ) che stacchi il 220volt e setti le uscite in una sequenza stabilita.

Fatto questo nasce il mio problema.

Appena eseguita la funzione il programma tornerebbe ad eseguire i passi rimanenti il che non avrebbe senso, il programma dovrebbe invece ripartire dall'inizio ed attendere la pressione del pulsante start.

Le soluzioni proposte sono altrettanto valide,

potrei inserire una variabile settata dall'interupt, ed eseguire la sua verifica durante il programma. Ma eseguita la funzione emergenza() il programma tornerebbe ad essere eseguito fino al successivo punto di controllo della variabile,

Oppure potrei inserire jmp $0000 che mi resetterebbe tutto, tanto non c'è nessuna variabile da ricordare, ma non vorrei che durante il reset le uscite si settassero a caso ....

Aspetto fiducioso .....

Xzero2

xzero2:
quindi come segnale di interrupt, il programma deve passare subito ( quindi non posso mettere il controllo di un ingresso generico) ad una funzione ( che casualmente ho chiamato emergenza() ) che stacchi il 220volt e setti le uscite in una sequenza stabilita.

Lo spegnimento della 220 lo gestisci all’interno della ISR abbinata al pulsante emergenza inoltre setti un flag che segnala tale stato e all’interno della loop devi controllarlo prima di eseguire ciascuno dei vari step, qui tocca vedere come hai organizzato la cosa, se la sequenza è controllata tramite una switch è facile uscirne subito, se hai fatto una cascata di if, o di funzioni, devi per forza controllare il flag in ciascuna di esse.

Come dice Astrobeed setti il flag di emergenza e setti le uscite nel stato di sicurezza. Se tale flag é settato ogni modifica di un uscita non viene eseguita. al inizio del loop() puoi poi bloccare l’ esecuzione del programma.

Comunque Ti consiglio di eseguire tale sicurezza non attraverso un pulsante collegato a Arduino, ma tramite un interuttore a fungo togliendo alimentazione 230V alle uscite simulate da Arduino. Puoi sempre prendere un interuttore con doppi contatti e fare tutte due le cose.

Ciao Uwe