In questo tutorial vediamo come settare i timer di Arduino (qui la lezione dedicata).
Visto la complessità dell’argomento sarà un tutorial un pò lungo.
Per il tutorial sfrutteremo sia il monitor seriale del software Arduino, sia la basetta di prova a cui collegheremo un Led con relativa resistenza, utile ma non indispensabile è anche un oscilloscopio che ci permetterà di leggere i dati dell’onda sviluppata quando questa sarà troppo “veloce” per vederla nel lampeggio del Led.
Materiale necessario
Se siete interessati al materiale, cliccateci sopra e sarete indirizzati alla pagina Amazon
Come detto nella lezione dedicata, Arduino ha un clock che lavora a 16Mhz, questa frequenza viene inviata ad un prescaler che è un divisore che divide la frequenza di ingresso tramite un gruppo di valori prestabiliti (1024, 256, 64, 8, 1), questo poi viene passato a dei registri di conteggio chiamati timer, il valore che assume il prescaler sarà la frequenza con cui verrà incrementato il timer fino al valore massimo.
All’interno del timer si può precaricare un valore in modo da non avere un conteggio da 0 a 65535, ma da un valore x stabilito da noi fino a fine conteggio, in cui otterremo la generazione del segnale.
I registri su cui lavorare per settore questi dati del prescaler sono: TCCRxA e TCCRxB (dove x è il numero del timer), abbiamo inoltre il comando TCNTx per caricare all’interno del timer il valore minimo da cui partirà il conteggio.

Riguardo la configurazione del TCCR1B (userò il timer1 per il tutorial), la parte di configurazione che a noi interessa sono solo i CS12 – CS11 – CS10, che secondo come vengono impostati modificano il divisore del clock, così da ottenere la frequenza che vogliamo in uscita dal prescaler.
Passiamo ad un esempio così da chiarire le idee, creiamo un sketch che genera un segnale che farà lampeggiare un led, montato nella PCB di prova, in cui ho collegato anche un osclilloscopio per vedere la frequenza quando questa sarà troppo veloce per vedere il lampeggio del Led.

Passiamo allo sketch, per questo tutorial lavoreremo solo sul void Setup, non essendo necessario nessun loop.
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
void setup() { pinMode(13, OUTPUT); Serial.begin(9600); TCCR1A = 0; TCCR1B = 0; TCCR1B |= B00000101; //1024 TCNT1 = 65342; TIMSK1 |= (1 << TOIE1); } void loop() {} ISR(TIMER1_OVF_vect) { TCNT1 = 65342; digitalWrite(13, !digitalRead(13)); } |
Impostiamo il pin 13 come uscita, ed attiviamo la seriale con il comando Serial.begin(9600)
|
1 2 |
TCCR1A = 0; TCCR1B = 0; |
Iniziamo a lavorare con i registri dei timer, volendo lavorare con il timer 1, userò il comando TCCR1A e TCCR1B, impostati entrambi a 0 così da ottenere un Reset dei registri.
|
1 |
TCCR1B |= B00000101; //1024 |
Una volta resettato il registro, inizio a lavorare sui divisori, che come detto sopra vanno impostati tramite l’impostazione dei bit (CS12 – CS11 -CS10).
I metodi di setup, sono molti io preferisco lavorare in bit così da avere visivamente più chiaro come sono impostati tutti i bit del registro, prendendo il comando sopra avrò che il TCCR1B è impostato con tutti i registri in off eccetto il CS11 e CS10, ottenendo così un fattore di divisione pari a 1024.
Ma che frequenza ottengo con un divisore uguale a 1024?
Basta dividere la frequenza di partenza 16MHz per 1024:
16Mhz = 16.000.000 Hz quindi: 16.000.000/1024=15.625 cioè 15.6 KHz in uscita dal prescaler.
|
1 |
TCNT1 = 65342; |
Utilizziamo il contatore con il comando TCNT1, all’interno di questo posso inserire un valore per far partire il conteggio non da 0 ma da un valore x fino ad arrivare a fine conteggio, che nel nostro caso essendo un timer 16bit sarà 65535.
|
1 |
TIMSK1 |= (1 << TOIE1); |
Quando il conteggio arriva al valore massimo scatterà un interrupt, per rilevarlo occorre richiamare un ulteriore registro chiamato TIMSK1 in cui va impostato il bit TOIE1.
Come detto in precedenza lasciamo vuoto il loop dello sketch e definiamo la routine che viene richiamata quando si arriva all’overflowe
|
1 2 3 4 |
ISR(TIMER1_OVF_vect) { TCNT1 = 65342; digitalWrite(13, !digitalRead(13)); } |
ISR(TIMER1_OVF_vect) è un comando predefinito che siamo obbligati ad usare, dentro questo inseriamo nuovamente il contatore con il valore dato in precedenza, così da far ripartire il conteggio sempre dallo stesso punto, successivamente richiamo il pin 13 in cui è collegato il Led tramite il comando digitalWrite e darò ad esse un valore opposto a quello che ha fino a quell’istante, per dare questo valore dico ad Arduino di invertire il valore tramite il simbolo “!”, letto nel pin 13 (digitalRead(13)).
Continuiamo con un po di calcoli per capire meglio lo sketch.
All’interno dello sketch abbiamo inserito un comando TCTN1 che come detto imposta il punto di partenza del conteggio diverso da 0.
Supponiamo di impostare un conteggio da 0 a 65535 con un fattore di divisione del prescaler impostato a 1024 (uso questo valore perchè altrimenti il simulatore non funziona bene), abbiamo una frequenza di conteggio pari a 15 Khz.
Ma a 15 Khz quanto è il passo?
La relazione tra frequenza (F) è periodo (T) si calcola con la formula: F= 1/T
Se voglio quindi trovare il periodo basta fare T= 1/F
Nel nostro caso T = 1/15Khz, facendo il conto avremo che il nostro periodo è di 66,6 µs (microsecondi).
Quindi 65535*66,6µs = 4.364.631 µs cioè il tempo totale per ottenere un conteggio da 0 a 65535 step del timer, ossia 4,36 secondi (ricordatevi che 1 µs ha un fattore scala di 1.000.000, quindi per convertire i µs in secondi basta dividere per 1.000.000).
Ma se noi volgiamo modificare il passo, quindi modificare il valore di TCNT1 in modo da avere un conteggio totale ogni 3 secondi come facciamo?
convertiamo 3 secondi in µs moltiplicando per 1.000.000 e successivamente dividiamo per 66,6 µs che come detto prima è il tempo totale per il conteggio da 0 a 65535 con una frequenza di 15 Khz.
3*1000000=3.000.000
3.000.000/66,6 = 45.045,045 step
Quindi il nostro conteggio deve partire 45.045,045 step sotto al livello massimo del timer.
Il prescaler TCNT1 dovrà avere un valore di 65.535-45.045,045= 20.489,95 step arrotondiamo a 20490 step

Ecco spiegato il valore dato ad inizio tutorial al TCNT1, alcuni preferiscono convertire il valore in esadecimale, personalmente preferisco lasciarlo in decimale per comodità.
Provate a sperimentare modificando il TCNT1, oppure in maniera più semplice modificando il divisore del prescaler TCCR1B.
Vi informo che nel simulatore, io ho impasto un valore di TCNT1 pari a 35504 ossia per un conteggio della durata di 2 secondi, solamente perchè il simulatore non dava un lampeggio visibile con il valore trovato nei calcoli sopra.
Il tutorial è finito, come sempre se avete dubbi o domande potete lasciare un commento qui sotto.
Allegati
In questa pagina sono presenti link di affiliazione che garantiscono a questo sito una piccola quota di ricavi, senza variazione del prezzo per l'acquirente.