Go Down

Topic: Posticipo segnale d'ingresso al variare della frequenza dello stesso (Read 5201 times) previous topic - next topic

ekjk

Scusate avevo fatto un errore: il programma di dalubar funziona correttamente. Nello sketch c'è scritto di impostare il valore di delay nei registri però bisogna impostare il valore di partenza in modo che quello di overflow - partenza =delay, giusto?


lesto

esatto, anche se non è consigliatissimo da fare, devi ricordarti di farlo ad ogni overflow. se non erro puoi invece impostare il valore di overflow: questa tecnica è più pulita. Mettiamo il caso in cui perdi un interrupt dal timer perchè facevi altro, dato che non risetti il valore di partenza, che ripartirà da 0, non solo avrai perso un interrupt ma anche il prossimo verrà generato in modo erroneo
sei nuovo? non sai da dove partire? leggi qui: http://playground.arduino.cc/Italiano/Newbie

leo72

L'uso di un valore iniziale del contatore si fa quando l'intervallo da misurare non può essere ottenuto usando solo il prescaler.

ekjk

Vorrei usare il timer2 perchè mi permette di ottenere con prescaler più piccoli, valori più piccoli di ritardo. dato che non ho bisogno di generare ritardi superiori a 200us, come si imposta l'overflow per ottenere il valore di delay richiesto con il timer2?

Altra cosa: per il timer 1 faccio TCNT1H e TCNT1L per settare il valore di partenza dal quale contare...ma con il timer 2 come si fa?
Perchè il compilatore mi da errore se faccio TCNT2H

lesto

dal sito atmel scarica il manuale (la "bibbia") dell'atmega 328, e da lì vedi i registri di un timer a quale timer corrispondono, vedi i registri dl prescaler, quali valori prescaler puoi settare, e mille altre cose. credimi, se già lavori con i registri troverai sì tante cose in arabo (es. i2c, spi), ma anche delle ottime spiegazioni su TUTTI i registri
sei nuovo? non sai da dove partire? leggi qui: http://playground.arduino.cc/Italiano/Newbie

dalubar

Stai prendendo il codice nel modo giusto...cioè come "spunto" e un "punto di partenza" per un approfondimento e una tua personale personalizzazione (non voleva essere un codice pronto all'uso).
Fai bene a usare il timer2, in modalità CTC. Per il valore del contatore basta usare TCNT2, dato che è un registro a 8 bit.
Per il resto segui il consiglio di Lesto riguardante la "bibbia" dell'ATMega328.

Quote
se non erro puoi invece impostare il valore di overflow: questa tecnica è più pulita. Mettiamo il caso in cui perdi un interrupt dal timer perchè facevi altro, dato che non risetti il valore di partenza, che ripartirà da 0, non solo avrai perso un interrupt ma anche il prossimo verrà generato in modo erroneo

Si, a lui conviene usare la modalità CTC che è facilmente ottenibile cambiando leggermente i registri del timer e praticamente non cambia il principio di funzionamento del sistema. Indubbiamente rende la tecnica più pulita in quanto non si deve ripristinare il valore iniziale. Sul "perdi un interrupt", invece, avrei quache perplessità, dato che solitamente è l'interrupt che interrompe qualcosa e non viceversa, e in un tipo di sistema come quello in oggetto sarà difficile che ci siano altri interrupt concorrenti.

Quote
mamma mia, mi usate i registri per impostare l'interrupt (quando attachInterrupt anadava più che bene)...

Che ti devo dire...volendo sorvolare sui quasi 200byte che l'istruzione attachInterrupt si "mangia" allegramente, usando direttamente il port mapping per settare il timer mi sembrava quasi una "stonatura" usare un'istruzione wiring...ma queste sono fissazioni mie :)

ekjk

Si l'idea del timer2 in CTC mi sembrava migliore. Ho già la bibbia e mi sto documentando ma ad esempio provando a scrivere il codice con timer2 posso generare un pwm in uscita sul pin11 ma non riesco a far partire il timer quando voglio e a fermarlo quando voglio.

lesto


. Sul "perdi un interrupt", invece, avrei quache perplessità, dato che solitamente è l'interrupt che interrompe qualcosa e non viceversa, e in un tipo di sistema come quello in oggetto sarà difficile che ci siano altri interrupt concorrenti.


difficile ma non impossibile, sopratutto se fai funzioni ISR troppo lunghe, o hai interrupt con frequenze troppo alte, o parli spesso via seriale (funziona ad interrupt), o usi PWM, o il timer1 che aggiorna la micros (e quindi la millis), etc.. non è così impossibile perdere un interrupt per concorrenza
sei nuovo? non sai da dove partire? leggi qui: http://playground.arduino.cc/Italiano/Newbie

lesto

i pin PWM usano i timer, certi pin un timer altri un altro. vedi "la bibbia" :)
sei nuovo? non sai da dove partire? leggi qui: http://playground.arduino.cc/Italiano/Newbie

ekjk

il codice per il timer2 è questo

Code: [Select]


#define ledPin 11
int val=0;
void setup()
{
  pinMode(ledPin, OUTPUT);
 
  //timer2
  noInterrupts();           // disable all interrupts
  TCCR2A = 0;
  TCCR2B = 0;
  TCNT2  = 0;

  OCR2A = 100;            // compare match register
  TCCR2B |= (1 << WGM22);   // CTC mode
  TCCR2B |= (1 << CS21);    // 32 prescaler
  TCCR2B |= (1 << CS20);
  TCCR2B &= ~(1 << CS22);
  TIMSK2 |= (1 << OCIE2A);  // enable timer compare interrupt
  interrupts();             // enable all interrupts
}

ISR(TIMER2_COMPA_vect)          // timer compare interrupt service routine
{
  val=!val;
  digitalWrite(ledPin, val);   // toggle LED pin

}

void loop()
{

}


Il problema è che cambiando il valore di OCR2A non cambia la durata della forma d'onda. e poi comunque vorrei che una volta raggiunto il valore, dentro ISR(TIMER2_COMPA_vect) si generi il segnale di uscita e si fermi il timer per poi riprendere all'arrivo di un nuovo fronte del segnale d'ingresso con il nuovo delay settato. Ma in OCR2A il valore caricato cosa è un intero? cosa rappresenta?


dalubar

Ora hai il libro della "conoscenza"...usalo! :)

Quote
difficile ma non impossibile, sopratutto se fai funzioni ISR troppo lunghe...

Si, Lesto, mi trovi d'accordissimo in tutto ciò che hai detto...solo che io mi riferivo specificamente al "suo" caso, cioè non credo che la sua applicazione contempli dialoghi con la seriale. Ovvio che dovendo performare il tutto per lo scopo prefissato si prenderanno tutte le (normali) precauzioni che si hanno quando si scrivono handler interrupt: ovvero poche istruzioni, uso minimo di registri, etc.
Per il millis, in verità ero convinto che Arduino gestisse uno stack interrupt...ma forse ricordo male io. Anzi se hai qualche notizia certa in merito ti sono grato :)

ekjk

Ci sono dietro da un bel pò ma non ci capisco. E' la prima volta che mi imbatto nei timer, ho bisogno di una bella spinta  :~

dalubar

Nella modalità CTC il timer viene azzerato ogni volta che il valore del contatore TCNT2 raggiunge un particolare registro denominato, appunto,  OCR2A.
E' come se l'hw del micro eseguisse una istruzione del tipo:
Code: [Select]
if (TCNT2 == OCR2A) ISR(TIMER2_COMPA_vect)
OCR2A, quindi, definisce il valore TOP per il contatore (0xFF).


ekjk

Ok chiaro, ma nel codice che ho postato non mi cambia il duty cycle della forma d'onda cambiando il valore di quel registro, perchè?
E comunque se volessi fare che una volta raggiunto il conteggio, nella chiamata alla ISR addetta volessi stoppare la ripartenza del conteggio?

Perchè lui poi riparte da zero, invece io voglio che riparta solamente quando glielo dico io.

dalubar

Quote
Ok chiaro, ma nel codice che ho postato non mi cambia il duty cycle della forma d'onda cambiando il valore di quel registro, perchè?

Non può cambiare il duty cycle per il semplice fatto che la modalità CTC NON è una modalità PWM. Quindi otterrai sempre e solo periodi al 50%.

Quote
...io voglio che riparta solamente quando glielo dico io.

Allora si ritorna al sistema precedente, ovvero CTC + INT0

Go Up