sto creando uno sketch su un arduino micro (leonardo) con gli interrupt.
voglio che l'interrupt si attivi una sola volta dopo aver ricevuto un comando da tastiera (singolo carattere qualunque).
di conseguenza, appena la ISR è entrata in azione, utilizzo un comando detachInterrupt() per disabilitare ogni successivo interrupt fino a un nuovo impulso di tastiera.
per quanto abbia provato, il comando detachInterrupt() mi ha sempre dato cilecca e sono stato costretto a sostituirlo inventandomi una ISR fake, in questo modo:
void loop()
{
while(Serial.available() > 0) {
indice = Serial.read();
attachInterrupt(digitalPinToInterrupt(IPIN),segnalazioneImpulso,RISING);
}
if (impulso == true) { //impulso può essere abilitata solo dalla ISR.
ripristinoInterrupt(DEVICE0);
detachInterrupt(digitalPinToInterrupt(IPIN));
attachInterrupt(digitalPinToInterrupt(IPIN),funzioneVuota,RISING); //questa riga non dovrebbe esistere.
impulso = false;
sprintf(str,"{\"r\":%d,\"t\":%lu}\n", indice, tEvento);
Serial.print(str);
Serial.flush();
}
}
mi sembra che Guglielmo si stia riferendo a istruzioni eseguite all'interno della ISR. Io ho collocato il detachInterrupt nel loop, quindi non sto generando conflitti tra interrupt. Inoltre, il mio programma utilizza un unico interrupt e la ISR è già ridotta al minimo.
tuttavia mi sono accorto che il mio programma può funzionare benissimo senza detach, spostando il ripristinoInterrupt e aggiungendo un breve ritardo di protezione:
void loop()
{
while(Serial.available() > 0) {
ripristinoInterrupt(DEVICE0); //questo ripristino riguarda il sensore, non gli interrupt di arduino (riattiva la produzione di eventi rising).
delay(1); // questo ritardo è assolutamente indispensabile.
attachInterrupt(digitalPinToInterrupt(IPIN),segnalazioneImpulso,RISING);
indice = Serial.read();
}
if (impulso == true) { //impulso può essere abilitata solo dalla ISR.
//ripristinoInterrupt(DEVICE0);
//detachInterrupt(digitalPinToInterrupt(IPIN));
//attachInterrupt(digitalPinToInterrupt(IPIN),funzioneVuota,RISING); //questa riga non dovrebbe esistere.
impulso = false;
sprintf(str,"{\"r\":%d,\"t\":%lu}\n", indice, tEvento);
Serial.print(str);
Serial.flush();
}
}
rimane il fatto che il detach non funziona. e se non funziona in una situazione così semplice, faccio fatica a capire a cosa serva e come lo dovrei usare.
magari ci torno se incontro una situazione in cui mi dovesse risultare assolutamente indispensabile.
Si ma se leggi quello che ti hanno scritto, non hai bisogno di fare detach e non ci sono "conflitti" di interrupt.
Comunque senza vedere il contenuto delle funzioni che citi e usi (ripristinoInterrupt e segnalazioneImpulso) è difficile darti un aiuto più preciso.
Ma dai?
Non funziona per lo scopo che immaginavi tu, non è che non funziona. Evidentemente serve, ma in contesti diversi dal tuo, dove non hai alcuna necessità di fare detach.
grazie.
in realtà, nei miei post, cerco sempre di isolare la parte di codice che ritengo importante.
gli utenti del forum non sono mica i correttori dei miei pasticci.
capisco che a volte chi desidera essere utile si trova in difficoltà, ma alla fine è comunque meglio così.
per esempio, dall'intervento dei Datman, che forse non è perfettamente centrato su questo preciso problema, ho ricevuto informazioni preziosissime relative al comportamento degli interrupt, che per me sono di grande interesse.
dal tuo, ho definitivamente sotterrato il desiderio di attribuire a detachInterrupt la causa delle mie paturnie.
alla fine dei conti è responsabilità mia individuare la soluzione che ritengo opportuna.
quindi cerco soprattutto risposte e consigli, piuttosto che soluzioni pronte.
in ogni caso, siccome me lo hai chiesto, allego comunque il codice che sto utilizzando.
rispetto a prima ho cercato di alzare il livello del debug nel mio sketch, acquisendo il timing di ogni operazione e credo di avere finalmente capito dove fosse il guaio che mi persegutava.
osserva questo output da tastiera:
l'evento generato da printf si verifica circa 8 millisecondi dopo che ho premuto il tasto invio.
in precedenza, mancando il controllo dei tempi, attribuivo il fatto a un errore del software, che mi avrebbe passato un evento precedente al tasto invio.
adesso sono convinto di osservare un evento fisico: ho semplicemente premuto invio premuto con un po' troppa energia.
infatti, sto usando delle soglie piuttosto basse e (provvisoriamente) un cavetto usb corto, di modo che la basetta giace sul tavolo al fianco del pc.