Timer 1 usato due volte in modi diversi

Ciao,
io uso un prescaler = 8, il tick diventa quindi 0.5us.
void counterISR viene chiamata da attachInterrupt sul pin 3 e su fronte RISING.

ekjk:
Ciao,
io uso un prescaler = 8, il tick diventa quindi 0.5us.

Sì, scusa. Avevo scritto CS12 per sbaglio e su quello mi basavo.

void counterISR viene chiamata da attachInterrupt sul pin 3 e su fronte RISING.

OK.

Comunque continuo a non capire la logica del tuo codice.
Vedendo le prime istruzioni della ISR agganciata all'interrupt di comparazione, tu fermi subito il timer.
Se ho capito è: arriva un segnale su un pin, richiamo un interrupt che fa partire il timer 1. Quando questo arriva al valore impostato da OC1A, fermo il timer. E poi?

Quando il timer arriva al valore OCR1A per prima cosa faccio

if(!NotRun && fire) PORTD = PORTD | B00010000;
  else PORTD =PORTD & B11101111;

Alzo il pin 4.

Dopo di che fermo il timer e calcolo i giri basandomi sul fronte di salita attuale e su quello successivo.

Non so se è chiaro, ma conoscendo la frequenza poi devo applicare un ritardo al segnale di uscita (pin 4) che scriverò in OCR1A e quando il timer arriva a tale valore alzo il pin 4 e fermo il timer.

Sì, ho capito.
Ma non posso aiutarti più di tanto perché per i tempi che servono a te occorrerebbe un oscilloscopio per vedere in quanto reagisce il timer a queste continue attivazioni/disattivazioni, strumento che io non ho. Cambiare valore di OCR1A in corsa non è un problema. Il problema secondo me nasce dall'attivazione/disattivazione del timer. Secondo me il timer riparte (non può non ripartire come dici tu) ma con un certo ritardo, per cui salti delle letture.

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?

ekjk:
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?

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

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.

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

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