salve a tutti vorrei fare un piccolo semaforo usando la scheda arduino 1, ma utilizzzando l' interrupt; ho cercato di documentarmi riguardo l' interrupt ed ho visto alcuni esempi [u internet; espongo i miei dubbi.
allora specifiche:
- incrocio semaforico che in condizioni normali funziona e fin qui tutto tranquillo: ho aggiunto soltanto un led di segnalazione che normalmente è lampeggiante;
- quando viene attivato un cambio di stato sul pin 2 (a cui collego un pulsante per l' interrupt) voglio che i 4 semafori diventino rossi il led di segnalazione si accende di colore verde per un determinato tempo (diciamo 3 secondi): magari in quella determinata corsia far passare un mezzo di emergenza con una priorità maggiore.
- passati i 3 secondi il programma deve ritornare nello stato di normale funzionamento ed in particolare deve riprendere dallo stato precedente (ad esempio de il semaforo 1 dell' incrocio era verde ed il 2 era rosso, deve riprendere dalla stessa condizione)
i miei dubbi in particolare sono questi:
- come implementare la funzione ritardo dentro un interrupt (ho letto dal sito che delay e millis non possono essere utilizzate); posso creare io una funzione con un ciclo for che viene eseguito 1000000 di volte (1 istruzione 1 usec ad esempio) ?
- come posso memorizzare lo stato precedente del semaforo e magari rprendere da li il valore da immettere dopo la fine dell' interrupt? esiste qualche funzione dentro arduino che mi fa ciò oppure devo crearmi delle variabili dove memorizzare il tutto?
uso interrupt
5 messaggi
• Pagina 1 di 1
2
voti
Secondo me diventa tutto più semplice se si lascia perdere il lato "arduino" e si inizia a considerare il lato "atmega328p"
Mi spiego meglio. Il microcontrollore che c'è sull' arduino, ha dei contatori interni ( TIMER ) che si attivano programmando opportunamente dei registri ( PRESCALER ).
I TIMER vengono decrementati dall' hardware ad ogni ciclo di clock, senza "consumare" cicli macchina come farebbe un programma. Quando arrivano a zero fanno scattare un altro interrupt.
Quindi, potresti programmare l'hardware del TIMER per far scattare uno di questi interrupt diciamo ogni 100 millisecondi, nell'interrupt service routine ( ISR ) sai quale interrupt è stato appena generato ( TIFR0 ) e se è questo incrementi un altro contatore. Sempre nell' ISR, quando questo contatore arriva a 30, sai che sono passati 30*100=3000 millisecondi=3 secondi e metti a 1 una certa variabile che definisci tu, o se vuoi fare il figo un bit di una variabile che fa da bandierina.
Quando il flusso del programma torna nel main, testi quella bandierina e fai quello che deve essere fatto dopo i 3 secondi poi rimetti la bandierina a 0.
Con i microcontrollori si fa così ed è molto semplice, arduino incasina solo le cose semplici secondo me.
Il datasheet dell' atmega, ad esempio nel capitolo 15 "8-bit Timer/Counter0 with PWM" spiega tutto.
Mi spiego meglio. Il microcontrollore che c'è sull' arduino, ha dei contatori interni ( TIMER ) che si attivano programmando opportunamente dei registri ( PRESCALER ).
I TIMER vengono decrementati dall' hardware ad ogni ciclo di clock, senza "consumare" cicli macchina come farebbe un programma. Quando arrivano a zero fanno scattare un altro interrupt.
Quindi, potresti programmare l'hardware del TIMER per far scattare uno di questi interrupt diciamo ogni 100 millisecondi, nell'interrupt service routine ( ISR ) sai quale interrupt è stato appena generato ( TIFR0 ) e se è questo incrementi un altro contatore. Sempre nell' ISR, quando questo contatore arriva a 30, sai che sono passati 30*100=3000 millisecondi=3 secondi e metti a 1 una certa variabile che definisci tu, o se vuoi fare il figo un bit di una variabile che fa da bandierina.
Quando il flusso del programma torna nel main, testi quella bandierina e fai quello che deve essere fatto dopo i 3 secondi poi rimetti la bandierina a 0.
Con i microcontrollori si fa così ed è molto semplice, arduino incasina solo le cose semplici secondo me.
Il datasheet dell' atmega, ad esempio nel capitolo 15 "8-bit Timer/Counter0 with PWM" spiega tutto.

2
voti
Quello che vuoi fare puoi farlo con e senza interrupt. Quello con gli interrupt è più efficiente e più preciso ma devi conoscere molto bene come funziona il microconrollore. API di Arduino semplifica la programmazione di alcuni aspetti molto semplici del microcontrollore ma nasconde le parti più complesse e più importanti sul funzionamento del microcontrollore.
MAI fare cicli di ritardo lunghi in un interrupt, se vengono fatti significa che non si è capito nulla su come funziona un microcontrollore e su come scrivere del codice efficiente e pulito.
Per memorizzare lo stato basta una semplice variabile intera a 8 bit, l'importante se si usano gli interrupt è che sia gestita nel modo corretto, la lettura, la scrittura e il confronto devono essere fatte in modo atomico
Qui trovi un esempio:
https://www.arduino.cc/en/Reference/attachInterrupt
la keyword "volatile" è fondamentale, impedisce al compilatore di ottimizzare l'uso, se manca molto probabilmente il codice generato non funziona (dipende fai flag di ottimizzazioni abilitati).
L'uso di una variabile a 8 bit rende la lettura e scrittura atomica su di un microcontrollore a 8 bit, l'uso di variabili più lunghe complica la scrittura del codice.
MAI fare cicli di ritardo lunghi in un interrupt, se vengono fatti significa che non si è capito nulla su come funziona un microcontrollore e su come scrivere del codice efficiente e pulito.
Per memorizzare lo stato basta una semplice variabile intera a 8 bit, l'importante se si usano gli interrupt è che sia gestita nel modo corretto, la lettura, la scrittura e il confronto devono essere fatte in modo atomico
Qui trovi un esempio:
https://www.arduino.cc/en/Reference/attachInterrupt
la keyword "volatile" è fondamentale, impedisce al compilatore di ottimizzare l'uso, se manca molto probabilmente il codice generato non funziona (dipende fai flag di ottimizzazioni abilitati).
L'uso di una variabile a 8 bit rende la lettura e scrittura atomica su di un microcontrollore a 8 bit, l'uso di variabili più lunghe complica la scrittura del codice.
0
voti
Condivido i post di Guru e xyz, con le seguenti sfumature:
per gestire un evento asincrono (vedi un ingresso) entro alcunie decine di microsecondi, non rimane che ì'interrupt.
Per gestire un sistema di controllo (vedi semaforo) le cui uscite potrebbero venire gestite con una imprecisione temporale di alcune decine di milisecondi, adoperavo un unico task eseguito periodicamente ogni (per esempio) 10 ms, comandato dalla struttura:
{
cont = millis()
if ((cont - contp) > 10 )
{ contp = cont;
..... metti le istruzioni da eseguire ogni 10 ms ....
}
}
le istruzioni da eseguire devono impiegare meno di 10 ms per compiersi, non usare ritardi...
Per i ritardi e la logica usavo una struttura da macchina a stati:
case (stato)
{
stato=1
...............
stato=2
......................
}
sono almeno un anno che non lo adopero, purtroppo non mi ricordo più la sintassi di arduino

per gestire un evento asincrono (vedi un ingresso) entro alcunie decine di microsecondi, non rimane che ì'interrupt.
Per gestire un sistema di controllo (vedi semaforo) le cui uscite potrebbero venire gestite con una imprecisione temporale di alcune decine di milisecondi, adoperavo un unico task eseguito periodicamente ogni (per esempio) 10 ms, comandato dalla struttura:
{
cont = millis()
if ((cont - contp) > 10 )
{ contp = cont;
..... metti le istruzioni da eseguire ogni 10 ms ....
}
}
le istruzioni da eseguire devono impiegare meno di 10 ms per compiersi, non usare ritardi...
Per i ritardi e la logica usavo una struttura da macchina a stati:
case (stato)
{
stato=1
...............
stato=2
......................
}
sono almeno un anno che non lo adopero, purtroppo non mi ricordo più la sintassi di arduino

1
voti
MarcoD ha scritto: sono almeno un anno che non lo adopero, purtroppo non mi ricordo più la sintassi di arduino
Arduino non ha nessuna sintassi proprietaria, è semplicemente un subset del C++ e in questo caso è quella del C (il compilatore usato è il GCC per AVR).
Questo è quello che volevi scrivere (almeno credo):
- Codice: Seleziona tutto
switch (stato) {
case 1:
....
break;
case 2:
....
break;
}
5 messaggi
• Pagina 1 di 1
Chi c’è in linea
Visitano il forum: Nessuno e 12 ospiti

Elettrotecnica e non solo (admin)
Un gatto tra gli elettroni (IsidoroKZ)
Esperienza e simulazioni (g.schgor)
Moleskine di un idraulico (RenzoDF)
Il Blog di ElectroYou (webmaster)
Idee microcontrollate (TardoFreak)
PICcoli grandi PICMicro (Paolino)
Il blog elettrico di carloc (carloc)
DirtEYblooog (dirtydeeds)
Di tutto... un po' (jordan20)
AK47 (lillo)
Esperienze elettroniche (marco438)
Telecomunicazioni musicali (clavicordo)
Automazione ed Elettronica (gustavo)
Direttive per la sicurezza (ErnestoCappelletti)
EYnfo dall'Alaska (mir)
Apriamo il quadro! (attilio)
H7-25 (asdf)
Passione Elettrica (massimob)
Elettroni a spasso (guidob)
Bloguerra (guerra)





