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?
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.
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:
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.