Newsgroup: it.hobby.elettronica.digitale
Titolo: Interrupt on change per leggere encoder di motore

Ho un motore con encoder ad effetto hall, con due sonde a 90°. Ne tiro
fuori un segnale logico e metto una sonda in RB4 e l'altra in RB5 di
un PIC16 (16F819 per la precisione).
Non ho ancora avuto modo di fare dei test con l'oscilloscopio per
vedere quanto è lungo (in tempo) l'impulso che viene fuori
dall'encoder.
Il mio dubbio è che se questo è abbastanza lungo (> 30 us a grandi
spanne) finisce la routine di interrupt prima che sia tornato basso il
segnale, quindi mi ritrovo un secondo interrupt pure quando nessun
segnale è stato mandato dall'encoder. E quindi dovrei mettere del
codice per controllare che tipo di cambio è stato (basso->alto di
qualcosa oppure è tutto basso?).
Avete esperienze e mi potete dire che comportamento aspettarmi? Oppure
lo scoprirò il giorno che metto le mani sull'encoder?


A parte che stare bloccati in un interrupt non e' mai una
bella cosa, usa un pin di capture e associa l' interrup al fronte
di salita o discesa, come preferisci, perche' devi lavorare su livello?
Di solito si assume che in interrupt deve essere servito
piu' velocemente dell' evento che lo scatena :-)
A.

 qualcosa oppure è tutto basso?).
L'interrupt viene generato solo sui fronti e non sui livelli per cui
quando esci dall'interrupt non c'è pericolo di una seconda chiamata.
L'unica cosa da verificare è lo stato logico dei segnali a seguito
dell'interrupt visto che sia RB4 che RB5 possono esserne la causa e su
fronti che potrebbero non interessare.
Quindi direi che subito dopo l'interrupt dovresti effettuare l'input
di RB4 ed RB5 e confrontarli con lo stato assunto nel precedente
interrupt traendone le conseguenze.
Piccio.

 piu' velocemente dell' evento che lo scatena :-)
Mah... A me serve sapere chi ha scatenato il trigger se la sonda 1 o
la 2. Per questo ho pensato che l'interrupt on change fosse perfetto.
Se un qualsiasi pin fa qualcosa mi prendo un interrupt.
Poi il capture non posso usarlo perchè sto usando quel modulo per
generare un segnale PWM.
Poi devo lavorare sul livello per sapere se l'interrupt me l'ha dato
la sonda 1 o la 2.
Col capture non so come potrei fare (se potessi farlo!).
Comunque... il numero di operazioni che devo fare ad ogni interrupt è
quello, più velocemente non posso andare. E non vedo come potrei fare
ciò senza interrupt. (magari coi loop che cercano se si è accesa una
porta....ma il concetto è uguale!! e nel frattempo avrei il pic
bloccato che non può fare le altre cose!).
Ma alla fine non vedo problemi. A 4 MHz ho un'operazione ogni
microsecondo. Nel mio interrupt ho meno di 50 righe di codice compresi
dei goto che non fanno mai eseguire tutto. facciamo 50us in totale? E
nel frattempo mi aspetto un interrupt ogni 10 ms nel caso peggiore.
Mi sembra di avere ampio margine!

 interrupt traendone le conseguenze.
Io, più semplicemente, metto l'interrupt su un solo input e controllo il
livello dell'altro per sapere la direzione.

 livello dell'altro per sapere la direzione.
Mi pare di aver constatato dallo schema della porta che non è
possibile selezionare il fronte per l'interrupt per cui questo avviene
ad ogni cambiamento.
E' bene quindi verificare il livello della sorgente di interrupt.
In effetti basterebbe una sola sorgente di int ma si dimezza la
risoluzione.
Comunque tra poco vi romperò le scatole anch'io con degli encoder
perché a maggio mi hanno garantito la consegna della sezione taglio
della "gnoccatrice" (5 motori in cc e 4 encoder).  :-)
Piccio.

 lo scoprirò il giorno che metto le mani sull'encoder?
Io lo feci anni fa. Le due fai encoder entravano sulla porta con 
interrupt on change abilitato. Per definizione di "change" l'interrupt 
parte solo sui fronti. La routine di interrupt prendeva i livelli dei due 
ingressi attuali, i due livelli memorizzati alla attivazione precedente e 
li  per accedere ad una tabella di lookup dove era memorizzata la 
macchina a stati di decodifica. 
Con questo trucchetto decodificavo due encoder indipendenti a velocità 
"quasi" da pld!

 ad ogni cambiamento.
Già. Scusate, devo smetterla di rispondere a chi usa controller scrausi. :D

 Mi sembra di avere ampio margine!
In genere gli interrupt sono 1-2 linee per ogni evento. L'unica cosa che 
devono fare è settare dei flag e pulire quelli di interrupt. Il programma 
principale dovrà poi gestire l'evento.
Questo serve ad evitare che possa scatenarsi un altro interrupt mentre si è 
a gestirlo (che verrebbe ignorato).
Puoi fare il tutto con delle variabili globali, facendo attenzione che 
l'accesso sia di tipo "atomico", cioè durante il tuo accesso non possa 
essere scatenato un evento che va a modificare la variabile
In questo modo puoi vedere il "programma principale" e il "programma 
interrupt" come se fosse programmazione concorrente e sincronizzata, 
appunto, tramite queste variabili globali
Ciao
CG 

 Già. Scusate, devo smetterla di rispondere a chi usa controller scrausi. :D
i pic hanno le linee int_ext per poter decidere il fronte su cui
agganciarsi;
l'int-on-change è una feature diversa che torna utile in certi casi e
volendo la si può usare come sorgente simile ad un int_ext ma con
qualche "complicazione" a livello di codice (caso dell'op)
-ice-

 essere scatenato un evento che va a modificare la variabile
se proprio non si può garantire un accesso atomico bisogna vedere se è
possibile perdere *eventualmente* qualche int e inserire il codice che
modifica la variabile fra una coppia cli/sti
-ice-