Timer 1 usato due volte in modi diversi

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.

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

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

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

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.

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.

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. :cold_sweat:

Ricominciamooooooooooo :slight_smile:

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.

:slight_smile:

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.

leo72:
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

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.

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?

E' giusto ma che valore devo mettere al timer1 per far in modo che non vada in overflow prima di aver finito di contare? sempre FFFF?

leo72:
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.

Devo fare il contrario, cioè mettere a 1 il pin 4 solo quando va in overflow, prima è basso...poi dovrò tirarlo giù di nuovo ma questo non è un problema..

ekjk:

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?

E' giusto ma che valore devo mettere al timer1 per far in modo che non vada in overflow prima di aver finito di contare? sempre FFFF?

Questo dipende dalla durata massima dell'ampiezza dell'impulso. Immagino che questo motore avrà un regime minimo di rotazione. Sapendo che il max valore del contatore del timer 1 è appunto 65535, se con il prescaler ad 1 (quindi clock a 16 MHz) non ti basta l'intervallo del contatore per misurare l'ampiezza dell'impulso, proverai ad usare un fattore di prescaler superiore.

Dai proverò oggi....puoi solamente scrivermi le impostazioni per il timer1 (WG21 ecc) in modo che conti fino all'overflow? per i CS ci penso io.

Grazie

Basta impostarlo in modalità 0 (normale). WGM13..0 a 0000.

Non ho ancora provato perché sono fuori per lavoro..appena torno ci provo :grin:
Grazie di tutto

OK.

Leo una altra cosa...come faccio a staccare il timer 1 dal pin al quale normalmente è collegato?

ekjk:
Leo una altra cosa...come faccio a staccare il timer 1 dal pin al quale normalmente è collegato?

Mi pareva di avertelo detto... comunque hai 2 strade:

  1. imposti il pin in input:
    pinMode(PIN, INPUT);
    e poi lo reimposti in output quando vuoi riagganciarlo:
    pinMode(PIN, OUTPUT);

  2. modifichi i bit COM1Ax e COM1Bx (a seconda del pin) nel registro TCCR1A (vedi pag. 132 del datasheet)