HELP Ritardatore serio con Interrupt

Ho bisogno di qualche dritta.

Devo realizzare un ritardatore che faccia queste funzioni:

  • arriva un interrupt da una fotocellula
  • l'uscita va a 1 SOLO dopo un ritardo che ho impostato con un Encoder rotativo e visualizzato su un Display
  • quando la fotocellula va a 0 l'uscita la segue sincrona.

Riassumendo: la fotocellula va a 1, l'uscita va a 1 dopo un ritardo impostato precedentemente. la fotocellula va a zero, l'uscita và immediatamente anche lei a zero.

Problemi: i ms impostati DEVONO essere quelli e non soggetti a jitter da delay() vari

Io pensavo di usare l'interrupt hardware al piedino 2 per la fotocellula, che interrompe il refresh del display grafico, ma poi cosa uso per fare il ritardo?

Se all'interrupt chiamo una funzione di delay() con valore associato alla variabile che mi ritorna dall'encoder, qusto delay è "preciso" visto che nella funzione Interrupt tutto il resto è fermo, oppure il delay() usa qualche timer che non può essere usato insieme all'interrupt?

I ms che imposto devono essere quelli, precisi

Poi: risolto questo, come uso l'interrupt per far andare il piedino di uscita a zero in maniera sincrona all'ingresso, se il delay è ancora impegnato?

Spero di essere stato chiaro...

Ti rispondo da semplice hobbysta di Arduino, ma hai provato ad utilizzare la funzione millis() anzichè del delay? XD

Ok, come non detto..

Ho appena visto dentro il file wiring.c, che la funzione delay() disattiva gli interrupt con un cli() prima di partire...

Una volta fatto partire l'interrupt della Fotocellula, cosa uso per creare un ritardo dentro la funzione interrupt?

Niente, nemmeno millis()...

Si ovviamente se scrivi millis(1000) non fa nulla.
Questa funzione è spiegata per bene qui:

Se vai tra gli esempi di Arduino c'è un esempio nella sezione "Digital" che si chiama BlinkWithoutDelay che ti spiega come utilizzarla.
Per me è stata un funzione molto comoda che mi permetteva di far ritardare l'esecuzione di un'istruzione ad Arduino mentre lui stava facendo tutt'altro.

Nono... è una funzione che devo inserire DENTRO l' Interrupt, e non può essere ne un delay() ne un millis().

Va a finire che devo fare una routine in C puro e usare un Timer interno...

Qua ci vuole Astro o qualche altro "cranio".

Qua ci vuole Astro o qualche altro "cranio".

:smiley: Meno male che ci sono loro!

Un'idea sarebbe quella di impostare un timer in base all'encoder. Lo fai partire quando ti arriva un impulso sul pin 2 tramite interrupt.
Quanto il timer va in overflow attiva il pin del segnale in uscita.
Bisogna vedere se puoi legare l'overflow del timer ad un interrupt interno che richiama l'attivazione del pin.
Credo che qui ci voglia Leo.

Regola d'oro: all'interno di un interrupt non si deve MAI mettere niente che inserisca un ritardo nell'esecuzione del codice della ISR.
Detto questo, potresti usare l'idea di Paolo. Al verificarsi dell'interrupt, la ISR imposta un timer configurato in modo da sollevare un interrupt al passare di un determinato lasso di tempo, lasso di tempo che ti calcolerai per benino lavorando di fino con il prescaler del timer stesso scelto.
Fatto questo, esci dalla ISR e per ora il lavoro è finito.
Sarà il timer, raggiunto il valore prefissato, a scatenare un altro interrupt che farà qualcos'altro. Qualcos'altro che, ricordo sempre, deve durare il meno possibile per non fermare tutto quanto.

Stranamente dentro l'iterrupt il delay funziona...

Ho usato un Interrupt a bassa priorità e che funziona solo su CHANGE, mappando in C puro i registri dei piedini dell'ATmega, quindi non i due piedini "boni" 2 e 3 che li hio lasciati per l'encoder.

Dentro la funzione di vettore dell'interrupt ci ho buttato il delay(), tanto per vedere "che effetto che fa" e sembra fuzionare...

BaBBuino:
Ho usato un Interrupt a bassa priorità e che funziona solo su CHANGE,

Bassa priorità mica tanto visto che il vettore di interrupt dei pin generici è subito dopo quello di INT0 e INT1.

Dentro la funzione di vettore dell'interrupt ci ho buttato il delay(), tanto per vedere "che effetto che fa" e sembra fuzionare...

Non è che dentro la ISR le altre funzioni non vanno, delay inclusa, è che se la ISR dura molto ti perdi gli altri eventi per strada.

BaBBuino:
Stranamente dentro l'iterrupt il delay funziona...

Non è strano dato che il delay usa micros() attualmente, che è una funzione che legge direttamente il valore del contatore del timer 0.

Ho usato un Interrupt a bassa priorità e che funziona solo su CHANGE, mappando in C puro i registri dei piedini dell'ATmega, quindi non i due piedini "boni" 2 e 3 che li hio lasciati per l'encoder.

Dentro la funzione di vettore dell'interrupt ci ho buttato il delay(), tanto per vedere "che effetto che fa" e sembra fuzionare...

E' sbagliato il concetto di inserire un ritardo in un interrupt, l'interrupt deve durare il meno possibile.