Go Down

Topic: Timer 1 usato due volte in modi diversi (Read 3316 times) previous topic - next topic

leo72


Io c'è l'ho l'oscilloscopio...infatti verifico queste cose.
Non c'è un modo per imbrogliare il timer?

Io vorrei che si fermasse...Nella modalità count normale quando va in overflow che succede? Chiama una routine e poi riparte?

Come detto, se lo fermi e lo riattivi, passa un certo lasso di tempo.
Quando il timer manda in overflow il suo contatore, questo semplicemente riparte da zero. Viene chiamata una ISR se è stato attivato il flag per sollevare il corrispondente interrupt.

Non potresti semplicemente salvare il valore del contatore e poi reinserircelo quando ti serve far ripartire il conteggio?

ekjk



Non potresti semplicemente salvare il valore del contatore e poi reinserircelo quando ti serve far ripartire il conteggio?


Si potrei, ma supponiamo di caricare in OCR1A il valore 1000, con un tick di 0.5us il timer impiega 500us a contare per arrivare a 1000 e poi si riazzera e riparte di nuovo, generando una onda quadra.

Io invece necessito solo di un impulso, cioè alzare una uscita quando arriva a 1000 (per es) e poi lui deve star fermo fino al prossimo valore di OCR1A, al prossimo fronte di salita del segnale d'ingresso.

C'è un modo per fare così?

leo72

No, che io sappia. Se fermi il timer, incorri nel problema suddetto.
Però forse ti sfugge il fatto che puoi staccare il pin a cui è collegato semplicemente mettendolo come input e poi puoi ricollegarlo mettendolo come output. In questo modo il timer continua a ciclare ma non genera nessun segnale sui pin esterni.

ekjk

Ecco a questa cosa non ci avevo pensato... Mi hai dato un buon consiglio. Ma nel fare questa operazione genero un ritardo secondo te?

leo72

Se metti il pin in input manipolando direttamente i registri del micro il ritardo è minimo, quantificabile nel tempo che serve al micro a decodificare a livello assembly l'operazione. Se usi la funzione pinMode il ritardo è nettamente maggiore.

http://www.arduino.cc/en/Reference/PortManipulation

ekjk

Ciao' ho appena provato come dici tu ma ho visto con oscilloscopio che l uscita cosi non sta ferma ma si.muove

leo72

Disconnetti allora il pin impostando a 0 i flag COM2Ax e COM2Bx (dipende dal pin che stai usando).

ekjk

Uso il pin 4. Quindi quali registri devo settare a zero?
E poi come li ripristino?

leo72

No, aspetta. Io intendevo pin collegati fisicamente al timer.
Ora capisco perché tu, mettendo il pin in input, continuavi a vedere qualcosa con l'oscilloscopio. Perché piloti un pin via software... non ricordavo questo particolare.

Prova usando un flag all'interno della ISR del timer che ti dice se devi pilotare il pin oppure no.

ekjk

Si ma questo lo faccio già: quando il timer arriva al valore va nella ISR e la prima cosa che faccio è di alzare il pin 4...

Il software così funziona ma mi piacerebbe contare la width dell'impulso prima di alzare quel benedetto pin. Cioè, arriva l'impulso in ingresso, conto la width e dopo metto il valore in OCR1A in base a width (lo prendo da un array), il timer conta e quando ha finito alzo il pin 4.


leo72

Ma non puoi suddividere il compito su 2 timer? Hai anche il timer 2. Puoi usare quello come contatore. Vero che usa un contatore ad 8 bit ma nulla ti vieta di implementare un contatore a 32 bit usando una ISR che incrementa una variabile.

PS:
saresti così gentile da spiegarmi un po' più nel dettaglio cosa vuoi fare? Sarò rincogl..., ma ancora non ho capito bene cosa esattamente il tuo codice deve fare.  :smiley-roll-sweat:

ekjk

Ricominciamooooooooooo  :)

Devo:

1. Misurare la frequenza di rotazione di un motore, ho due modi per farlo: il primo è misurare il tempo tra due fronti del sig ingresso; il secondo, conoscendo questo tempo appena misurato e conoscendo la durata dell'impulso (width) in ingresso posso utilizzare questo dato per ricavare alpha°=width*freq; da questo poi misurando solo la width e sapendo che a una data alpha° corrisponde una freq (misurata all'accensione del motore) ricavo freq attuale.
2. Problema: quando arriva il fronte di salita però devo alzare un pin (il 4 nel mio caso) dopo un certo tempo letto da un array in base alla freq di rotazione.

:)

leo72

Per me il "fronte di salita" è un segnale, semplifico un po' OK?

Allora. Arriva questo segnale su un pin. Tu hai su quel pin un interrupt. L'interrupt ti scatta e tu metti su High il pin 4.
Contemporaneamente imposti il contatore del timer 1 (che non viene mai fermato, altrimenti si hanno i problemi noti di lag) ad un valore che è dato dal suo MAX ($FFFF) meno il tempo che deve contare. Esempio: devi contare 1000? Allora metti nel contatore 65535-1000=64535. Hai inoltre attivato l'interrupt sull'overflow del contatore. Quando va in overflow ti viene sollevato l'interrupt e tu dentro alla ISR rimetti a LOW il pin 4 e poi toglie l'interrupt per le volte successive.

ekjk



Allora. Arriva questo segnale su un pin. Tu hai su quel pin un interrupt. L'interrupt ti scatta e tu metti su High il pin 4.



Prima di mettere high il pin 4 devo sapere la width del segnale per sapere quando alzarlo...perchè prima devo conoscere a che velocità sta andado il motore (freq=alpha°/width) per poi applicare un ritardo al segnale di uscita, ovvero un ritardo prima di alzare il pin 4.

Come contare la width che mi può variare tra 50us e 2000us? Per avere una certa accuratezza volevo sempre usare il timer 1, puoi buttare giu due righe? thanks

leo72

Hai un pin a cui hai collegato un interrupt.
Mettiamo che questo interrupt sia di tipo CHANGE, così che scatti sia se il pin passa da 0 a 1 che viceversa.
Quando passa da 0 ad 1, tu azzeri il contatore del timer 1.
Quando passa da 1 a 0, leggi il contatore del timer 1, ed hai la durata del tuo impulso.
Fin qui è corretto, come ho impostato il problema?

Bene. Adesso tu, sempre all'interno della ISR, metti ad 1 il pin 4 e poi carichi il timer 1 come ti ho detto in precedenza, con il valore che tu hai estratto dall'array in base alla precedente lettura. Quando il timer 1 va in overflow, ti mette a 0 il pin 4.

Go Up