faccio un esempio: se ho un sensore che impiega 1 minuto per rendermi un dato, e questo dato devo metterlo in una variabile, con il polling il micro sta' li fermo ad aspettare il sensore, se ad esempio devo far lampeggiare contemporaneamente un led, il led si fermera'.
Usando un interrupt e quindi mettendo la lettura di questo sensore nella ISR, non mi sembra che cambi molto, perche' quando il micro andra' a svolgere le funzioni della ISR sempre 1 minuto dovra' stare ad aspettare, ed il led si fermera'.
Capisco l'uso dell'interrupt nelle condizioni opposte, cioe' quando il sw ha lunghi tempi di esecuzione mentre nell'interrupt mettiamo tipo la rilevazione di uno switch, ma non capisco come gestire invece il contrario, coe' quando e' l'evento che attendiamo ad essere lungo.
grazie a chi volesse perdere un po' di tempo a beneficio della comunita' nel chiarire questi aspetti
L'interrupt lo puoi usare solo se hai un evento specifico che lo scatena, p.e. il passaggio per lo zero di un timer, un pin che cambia stato, una periferica di comunicazione che ha disponibile un nuovo dato.
Anche il polling prevede il controllo di una condizione specifica per eseguire una certa operazione, spesso si usano gli stessi flag hardware degli interrupt per rilevare questa condizione senza attivare uno specifico interrupt.
Non è assolutamente vero che il polling ti blocca per forza in attesa dell'evento senza fare nulla, esempio pratico hai un loop dove fai lampeggiare un led a 1 Hz tramite la millis(), quindi il programma gira sempre senza aspettare, vuoi che il lampeggio passi a 2 Hz se il pin 2 va a 0 logico, normalmente si trova a 1 tramite una pull up.
Per risolvere il problema utilizzi la tecnica del polling, cioè testare ciclicamente una condizione, controllando lo stato del pin 2 ad ogni ciclo del loop, se lo trovi a 0 cambi la frequenza di lampeggio a 2 Hz per poi riportarla a 1 Hz quando il pin torna a 1, in questo modo il tuo programma non si ferma mai e puoi fare altre cose mentre aspetti il cambio di stato del pin.
In alternativa puoi collegare un interrupt al cambio di stato del pin e quando questo avviene all'interno della ISR cambi un flag che dice al main loop quale frequenza di lampeggio usare.
All'interno della ISR non fare mai nulla di complicato o che richiede lunghi tempi di esecuzione, p.e. esempio calcoli complessi o, peggio, usare una delay, la ISR deve durare il minimo possibile, già 10 microsecondi sono troppi, ci si deve limitare a verificare le condizioni e settare variabili e/o flag che dicono al main loop cosa deve fare esattamente.
capisco, ma tu hai fatto esempi con tempi brevi, sui tempi brevi ci siamo, ma nel caso che ho fatto io ? 1 minuto ?
Polling: ho il mio bel led che lampeggia con la tecnica (blink without delay), poi vado a leggere il sensore, ma nel momento in cui chiedo al sensore il dato, tutto si ferma, il micro essendo monosessione puo' fare solo una cosa alla volta.
quando il sw chiede il dato dal sensore non puo' andare al prossimo step fino a che non lo ha ricevuto. quindi credo che per 1 minuto il led non lampeggera'.
e visto che parliamo di 1 minuto, anche gestirlo nella ISR non serve giusto ?
ma i sensori analogici rendono il dato disponibile in maniera continuativa, e quelli digitali hanno un'area di memoria dove viene bufferizzato il dato in uscita fino alla prossima lettura.
Nel caso del sensore digitale si può istruire il software a proseguire l'esecuzione del programma qualora il dato non sia ancora disponibile.
Testato:
capisco, ma tu hai fatto esempi con tempi brevi, sui tempi brevi ci siamo, ma nel caso che ho fatto io ? 1 minuto ?
Non esiste un sensore che ci mette 1 minuto per risponderti, si ragiona sempre in termini di microsecondi o, al massimo, qualche millisecondo
Semmai se tu da programma che lo vai a leggere una volta al minuto usando la millis.
Se il sensore, o il device che vuoi interrogare, è lento nell'acquisire i dati, p.e. un datalogger che legge i canali ogni tot minuti, avrai sempre disponibile un comando, o un flag hardware (pin), che ti informa se dati sono pronti o no, in questo caso ad ogni passaggio controlli solo lo status,se sono pronti acquisisci i dati altrimenti vai avanti col tuo programma.
il mio era un caso estremo per fare un esempio, ma utile a capire, cioe' lasciando da parte le soluzioni proposte per sensori reali, semmai esistesse un sensore digitale (ma non lo costruiranno mai logicamente), che consegnerebbe il dato richiesto dopo un minuto, senza pin di controllo come da te spiegato, il problema sarebbe non risolvibile su arduino, ne' in polling ne' con interrupt.
si dovrebbe usare una soluzione esterna tipo un secondo arduino per la gestione del solo sensore.
a questo ad esempio puo' servire la pico85 ?
(in realta' mi ci sono imbattuto in un probelma del genere, ricorderete ho postato la soluzione sul forum Sensor, e bastavano 10ms per crearmi il problema, per questo, per chiarire la questione, ho fatto un esempio da 1 minuto)
E cosa cambierebbe? seguendo il tuo ragionamento anche il secondo micro (o Arduino) avrebbe il tuo stesso problema.
Tu stai affrontando il problema come se si parlasse di un'abitazione con una porta a cui bussare. Il sensore non è il postino che se non trova in casa nessuno prende e se ne va e se tu non apri in tempo non ricevi la posta XD
Il sensore dà sempre un segnale della sua presenza, quindi per un sensore che da un valore analogico, avrai quel valore analogico sempre presente sul pin: immagina una fotoresistenza, ad esempio. Nel momento in cui quel valore servirà, non dovrai far altro che leggere il pin. Tornando all'esempio del postino, è come se il postino ti lascia ad intervalli regolari la posta in cassetta. Quando tu ne hai voglia, esci di casa, apri la cassetta e prendi la posta.
Se invece il sensore invia un segnale digitale, allora puoi benissimo agganciare un interrupt al pin e controllarne il cambiamento di stato. In questo caso ripensa a quelle barriere ad infrarossi di Menniti che davano un segnale preciso (0 o 1) all'attraversamento del raggio. In questo caso, immagina di aver assunto un domestico che riceve la posta per conto tuo. L'interrupt viene "attivato" dal segnale sul pin e poi esso richiama la funzione che vuoi tu. Immagina, tornando all'esempio, di aver assunto un maggiordomo: passa il postino e suona (segnale sul pin), il maggiordomo apre al posto tuo (interrupt attivato) e poi mette la posta sulla tua scrivania. A quel punto, quando la vuoi leggere, vai sulla scrivania e guardi cos'è arrivato (apri la variabile).
Testato:
il mio era un caso estremo per fare un esempio, ma utile a capire, cioe' lasciando da parte le soluzioni proposte per sensori reali, semmai esistesse un sensore digitale (ma non lo costruiranno mai logicamente), che consegnerebbe il dato richiesto dopo un minuto, senza pin di controllo come da te spiegato, il problema sarebbe non risolvibile su arduino, ne' in polling ne' con interrupt.
Stai facendo una ipotesi assurda, se il sensore, o il device, ci mette un minuto per fornirti il nuovo dato sei tu che a vai leggerlo una volta al minuto, non stai certo fermo per un minuto, leggi il sensore, esegui un ciclo e rimani fermo un altro minuto.
Il ciclo main continua alla massima velocità possibile, cosa fare lo deicidi in base a dei flag, settati da funzioni o ISR, oppure in base al tempo trascorso.
Testato:
il mio era un caso estremo per fare un esempio, ma utile a capire, cioe' lasciando da parte le soluzioni proposte per sensori reali, semmai esistesse un sensore digitale (ma non lo costruiranno mai logicamente), che consegnerebbe il dato richiesto dopo un minuto, senza pin di controllo come da te spiegato, il problema sarebbe non risolvibile su arduino, ne' in polling ne' con interrupt.
si dovrebbe usare una soluzione esterna tipo un secondo arduino per la gestione del solo sensore.
a questo ad esempio puo' servire la pico85 ?
(in realta' mi ci sono imbattuto in un probelma del genere, ricorderete ho postato la soluzione sul forum Sensor, e bastavano 10ms per crearmi il problema, per questo, per chiarire la questione, ho fatto un esempio da 1 minuto)
come no? o con la delay, oppure l'interrupt che legge il dato e setta la flag che un nuovo dato p disponibile. Non vedo quale sia il problema tra 1 ms e 1 minuto (tranne gli overflow dei timer, che bisogna sempre tenerne conto!)
facciamo un esempio piu' reale, nel mio caso avevo una funzione di visualizzazione realtime, cioe' il dato doveva essere spedito in continuazione verso la visualizzazione, la visualizzazione non aveva nessun buffer o latch di memoria, questa routine di visualizzazione impiegava 10ms per lavorare, quindi ogni 10ms veniva refreshato il dato. se anche il dato non era cambiato, veniva cmq rifleshato. Non so se mi spiego, non e' come il serial monitor dove tu invii la scritta PIPPO e lei resta li' finche' non viene riscritto pippo.
Nella mia visualizzazione devo inviare pippo in continuazione, almeno ogni 10ms, altrimenti se perdo tempo vedo pippo scomparire.
bene, il dato PIPPO arriva da un sensore che impiega 1 secondo a rendere disponible il dato, su protocollo 1wire, quindi niente pin di controllo o altro. solo due fili.
il risultato e' che pippo compare per un istante e poi scompare per un secondo.
c'e' soluzione ? entrano in campo gli interrupt ?
i maggiordomi sono comodi, ma non ho capito una cosa, io posso restare seduto e continuare a leggere mentre il maggiordono si alza e va a prendere la posta ?
il monothread di arduino mi fa pensare che e' vero che posso assumere maggiordomi, fino a 2 se non sbaglio, ma quando loro vanno a prendere la posta io devo smettere di leggere il libro
Testato:
bene, il dato PIPPO arriva da un sensore che impiega 1 secondo a rendere disponible il dato, su protocollo 1wire, quindi niente pin di controllo o altro. solo due fili.
Il tuo problema, e te lo avevo già detto e spiegato, è che la libreria one wire che usavi è fatta male.
Se il sensore ci mette 750 ms per darmi un nuovo dato perché è il suo tempo di conversione interno non significa assolutamente che devo aspettare 750ms i suoi comodi, lo vado a leggere una volta al secondo e nel frattempo faccio quello che mi pare.
Anche i sensori one wire hanno lo status register che ti dice se il nuovo dato è pronto o meno, se non vuoi fare conti sul tempo basta che ad ogni ciclo leggi lo status, se è ok leggi il dato altrimenti vai avanti.
Se poi la lettura del sensore, a livello di singoli bit di un bus seriale non gestito in hardware, può risultare troppo lunga per le esigenze del programma eseguendola tramite polling software la fai tramite interrupt on change slegando completamente l'esecuzione del programma dalle attese sul bus, e anche questa cosa te lo avevo già detta in quel thread.
fai leggere la posta al maggiordomo che se la ricorderà fino al prossimo messaggio.
cioè memorizzi l'ultimo valore ricevuto in una variabile fino a che non ne ricevi ( o diventa disponibile) uno differente, e al display mandi ogni 10ms quello memorizzato (sempre l'ultimo disponibile) invece della lettura diretta. (in maniera asincrona)
Oh, meno male che qualcuno si è accorto dell'esempio del postino..
Cmq, fai "ricevere" la posta (segnale) al maggiordomo (interrupt), che la depositerà sulla scrivania (variabile globale) da dove poi il padrone di casa (sketch) potrà leggerla (controllare il valore della variabile) a tempo debito.
scusa astro se soo sembrato ripetitivo, ho fatto quell'esempio per parlare di un esempio piu' reale, ma appunto e' un esempio, restiamo sulla teoria, e poi ora capisco di piu' quello che mi scrivete rispetto ad allora, la mia insistenza e' legata alla voglia di capire ma anche direttamente proporzionale alla mia ignoranza
Anche i sensori one wire hanno lo status register che ti dice se il nuovo dato è pronto o meno
le tue due cose che mi hai detto ora le ritego fondamentali, e le devo imparare e "testare"
mica hai per le mani un esempio per verificare su codice come funziona questa storia qui ?
per Brain: la tecnica da te descritta senza mettere in atto il discorso del register o dell'interrupt non funziona, sempre perche' il dato non essendo disponibile blocca l'esecuzione del loop. Il loop va avanti passo per passo, e quindi quando chiede il dato, per copiarlo dove vuoi tu, blocca tutto.
Purtroppo se non fai una prova con un segnale reale che devi attendere per un bel po non ti rendi conto.
per leo: questa dell'interrupt io l'avevo messa in campo, ma torniamo sempre allo stesso punto, o mi manca qualche punto (molto facile) oppure il problema resiste.
vediamo un po', io la vedo cosi'. setto un interrupt sul pin di input tramite timer (non ho un evento esterno per farlo), quindi al momento giusto inizio a leggere con la ISR il dato. e durante questo tempo io con il micro devo stare fermo, visto che il dato della ISR arrivera' dopo 1 secondo, per un secondo non posso pilotare la visualizzazione.
Dove sbaglio ? (togliamo da mezzo i maggiordomi, chiamiamoli con il loro nome
No, tu non stai fermo per niente. Te l'ha spiegato anche astrobeed.
Il timer genera un interrupt, la routine dell'interrupt legge il sensore.
Ma non sta ad aspettare il valore, lo legge sulla porta. Se c'è un valore, lo legge, se non c'è registra 0. In entrambi i casi è come se il "maggiordomo" si affacciasse alla porta 1 volta ogni x ms e guardasse se c'è il postino. Se c'è, prende la posta e l'appoggia sulla scrivania, se non c'è richiude la porta.
Ma questa azione è trasparente e non blocca nulla. Tu, in casa, continui a fare i tuoi compiti. Il segnale di reset sarebbe come il campanello suonato alla porta: con l'orecchio lo senti ma te ne freghi tanto sai che c'è il maggiordomo a ricevere la posta per te. Tu quando la vuoi devi solo andare a prenderla sulla scrivania.
Io più chiaro di così non so spiegartelo, mi arrendo XD
Non ci ho capito nulla.
Forse l'esempio del maggiordomo confonde.
Proviamo con il puntatore PC.
Tu con i tuoi occhi leggi una parola (istruzione) dopo l'altra e ne incontri con un numerino(interrupt), sai che devi sospendere la lettura salvare il punto (PC) in cui ai sospeso e salti a fondo pagine (ISR), leggi la nota a fondo pagina e ritorni a leggere dalla parola successiva al punto PC.
Se per leggere la nota ci impieghi un minuto, per questo tempo il resto del programma non viene eseguito, allora potresti fare un confronto del tipo: Il dato che ho in memoria e uguale a quello che sto leggendo. Si lo è esco dalla ISR a fare altro. No non lo è, allora è un dato nuovo lo salvo ed esco dalla ISR.
Le ISR sono richieste di interuzzione a cui il micro risponde spostano il PC (program counter) alla indirizzo prestabilito raggiungibile tramite l'uso della macro ISR vect.
Se hai invece un sensore che acquisisce dei dati per un secondo e vuoi sapere quando una nuova acquisizione è disponibile, deve essere il sensore a comunicare ciò.
Forse se esponi meglio la tua necessita in modo concreto si arriva facilmente alla conclusione.
Mauro, Testato crede che la lettura di un sensore su un pin blocchi lo sketch. Il tempo impiegato è quello che serve a convertire la lettura analogica in un valore intero, non devo stare ad aspettare che il sensore si aggiorni.
Allora prima di tutto non serve un interrupt sul tempo.
Togliamo di mezzo il protocollo per un secondo.
dallo sketch invii la richiesta (senza attendere risposta), attivi sul filo un interrupt di cambio stato, e vai avanti a eseguire il tuo programma. Appena viene rilevato un cambio stato, l'interrupt legge il dato piazzandolo in una variabile temporanea (dato che ogni messaggio, a meno che non sia di un solo bit, sarà composto da più cambi di stato, devi giocartela un pò di bitshif), quando rileva la fine dato copia il dato temporaneo in una varibaile globale, magari setta pure una booleana (detta flag) a true che avvisa che un nuovo dato è stato letto, poi si auto-disattiva.
al prossimo loop il tuo sketch legge la flag(perchè lo fa ad ogni loop), vede che è a true e quindi arrivato il dato, mette la flag di nuovo a falso, re-invia la richiesta, riattiva l'interrupt ed elabora il dato.
volendo puoi evitare il fatto di attivare e disattivare l'interrupt, se non serve inviare nessuna richiesta ma il sensore in automatico invia il dato ogni tot(altrimenti l'interrupt "leggerebbe" anche la richiesta).
(piccolo particolare: quando arriva un interrupt, il tuo programma si interrompe e viene eseguito il codice dell'interrupt, quindi cerca di mantenerlo il più veloce possibile)
ORA riaggiungiamo il protocollo: ovviamente andare a giocare con gli interrupt sul protocollo one-wire è una mezza sciocchezza, perchè (in teoria) il protocollo fa già questo lavoro in automatico, piazzando i dati in arrivo in un buffer, esattamente come fa la seriale, e andare a sminchiare gli interrupt manda in palla la libreria.
Questo però non è obbligatorio: per esempio la SoftSerial di default di arduino non usa gli interrupt, infatti se ti arriva un dato mentre NON stai facendo la read (che blocca il programma) lo perdi. A quanto pare questo è anche il caso della tua libreria.
Come risolvere?
usi un'altra libreria, nel caso della seriale la NewSoftSerial
PROVI ad usare gli interrupt, però prima devi essere sicuro che le modifiche che fai ai registri non entrino in conflitto con le necessità della libreria.
leo72:
Mauro, Testato crede che la lettura di un sensore su un pin blocchi lo sketch. Il tempo impiegato è quello che serve a convertire la lettura analogica in un valore intero, non devo stare ad aspettare che il sensore si aggiorni.
No, Leo, togliamo da mezzo il discorso dell'analogico, parlo di sensori digitali.
Quello di cui parlo, e finalmente ne vedo conferma e' questo:
MauroTec:
Se per leggere la nota ci impieghi un minuto, per questo tempo il resto del programma non viene eseguito
ed anche questo:
lesto:
piccolo particolare: quando arriva un interrupt, il tuo programma si interrompe e viene eseguito il codice dell'interrupt, quindi cerca di mantenerlo il più veloce possibile
Al quale problema ci sono poi tutte le serie di soluzioni esposte.
Questo tentavo di spiegare, probabilmente a chi programma ad esempio in C per PC normali non e' evidente questo problema, perche' usa CPU multisessione, e' corretto ?
Ringrazio quindi tutti per le soluzioni proposte, che di certo saranno utili a me ed altri.