Timer 1 usato due volte in modi diversi

Il timer 1 in modalità Input Capture Unit lavora col pin ICP1 (pin D8 dell'Arduino) o con l'ADC per cui se la scheda è già fatta, allora non si può lavorare con esso.

Intanto bisognerebbe che tu postassi il codice che stai usando, almeno vediamo di analizzare su cosa stai lavorando e capire la logica che vuoi applicare

Intanto grazie per i chiarimenti.

Non riesco a postare il codice ora ma appena possibile lo faccio.
Spero che sia chiaro ciò che vorrei fare.
Se riuscissi a resettare il timer sarei a cavallo.

Comunque utilizzando la funzione pulseIn() potrei leggere la durata dell'impulso o no? Svantaggi?

Ciò che voglio fare è questo:

1.Per sapere i giri di un motore mi voglio basare sulla larghezza dell'impulso del sensore e non solo sulla distanza tra due fronti alti.
2.All'accensione del motore devo contare i giri utilizzando magari attachInterrupt che fa partire una routinesul fronte alto: e questo lo so fare.
3.Allo stesso tempo però voglio sapere la larghezza dell'impulso d'ingresso, cioè il tempo tra fronti HIGH e LOW, così posso calcolare con la legge oraria quanto spazio in gradi corrisponde alla larghezza dell'impulso e alla sua frequenza: alpha=t2pif, e la salvo in una variabile
4.Quindi conoscendo f data dal tempo tra HIGH e successivo HIGH e conoscendo t dato dal tempo tra HIGH e LOW conosco alpha.
5.Ora conoscendo alpha posso ricavare f (i giri motore) invertendo la relazione e contando la larghezza dell'impulso.
6.Questo mi permette di poter conoscere i giri motore appena finisce il segnale del sensore senza aspettare il nuovo fronte HIGH.

Spero sia chiaro, sggerimenti sono apprezzati. Grazie

Qualche idea?

questo è il codice che uso ora, ma che calcola gli rpm solo dopo aver generato l'impulso di uscita.

void counterISR()
{      
  TCCR1B |= (1 << CS11);    
  val=!val;
  fire=true;
}

ISR(TIMER1_COMPA_vect)
{
  if(!NotRun && fire) PORTD = PORTD | B00010000;
  else PORTD =PORTD & B11101111;
  
  TCCR1B &= ~(1 << CS11);  
  
  fire=false;
  flag=true;
  
  if(val) tempo_iniziale=micros();

  if(!val)tempo_finale=micros();
          
  if(tempo_finale>=tempo_iniziale) {freq=(int)(1000000.0/(tempo_finale-tempo_iniziale));} 
  if(tempo_finale<tempo_iniziale) {freq=(int)(1000000.0/(tempo_iniziale-tempo_finale));} 
          
  if(freq<0) freq=0;
  if(freq>250) freq=250;
}

al fronte di salita in ingresso si va in counterISR dove abilito il conteggio di timer 1 in ctc.
Quando timer1 arriva a OCR1A (settata di volta in volta nel loop in base alla freq di rotazione) si passa in TIMER1_COMPA_vect che alza il pin di uscita così ritardato del valore che voglio e poi calcolo la freq di rotazione...lo faccio così perchè introduco meno ritardo rispetto a farla quando arriva il primo fronte nell counterISR.

Facendo così però, il ritardo che applico (OCR1A) è calcolato sulla frequenza tra un fronte e quello successivo e quindi il timer applica il vero valore di ritardo solamente al secondo fronte, perchè al primo fronte OCR1A non è settato al valore giusto in quanto per ricavare tale valore serve la frequenza che viene calcolata solo all'arrivo del fronte successivo, il secondo.

Forse con la pulseIn potresti risolvere. Su che ordine di grandezza di tempi stiamo ragionando? La pulseIn misura da 10 uS in su. Sarebbero sufficienti?
Stavo poi ragionando sul modo con cui usi il timer 1.
Che cosa faresti con CS11? Quel flag è usato per impostare il prescaler, non la modalità di funzionamento del timer

Ho provato con la pulseIn() a misurare la durata dell'impulso, sotto i 10us non ci vado mai, ma ho notato che il codice rallenta molto.

CS11 lo metto a zero per fermare il timer (dato che secondo il prescaler che uso anche gli altri CS sono a zero) che sennò continuerebbe a contare generando un pwm.

ekjk:
Ho provato con la pulseIn() a misurare la durata dell'impulso, sotto i 10us non ci vado mai, ma ho notato che il codice rallenta molto.

Il codice rallenta perché la pulseIn ferma tutto e si mette in attesa dell'impulso, misurandone poi la durata.

CS11 lo metto a zero per fermare il timer (dato che secondo il prescaler che uso anche gli altri CS sono a zero) che sennò continuerebbe a contare generando un pwm.

Ah, ho capito. Togli il segnale di clock al timer.
Ricordati però che quando riattivi il timer dandogli il clock (mettendo CS12 ad 1), il timer potrebbe non ripartire subito, subendo un certo ritardo proporzionale al fattore di prescaler. Tu usi un prescaler di 256, mi pare.
void counterISR da chi viene chiamata?

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?