A utilização de timers, ou temporizadores, no Arduino é um método avançado para executar códigos sem perturbar o resto do programa. Eles permitem ativar funções a intervalos de tempo precisos. Os timers são utilizados em muitas bibliotecas, de forma completamente transparente para o usuário (milis(), Servo.h, PWM, etc.)
Em alguns casos, é possível utilizar bibliotecas que configuram timers, para simplificar o uso.
Material
- Arduino UNO
- Cabo USB A/ USB B
Descrição
Os timers são registros do microprocessador que aumentam de acordo com impulsos de relógio ou impulsos externos. É possível configurá-los para modificar o seu comportamento.
O microprocessador Arduino UNO (ATmega328P) tem 3 temporizadores:
- timer0 (8 bits) conta de 0 a 256 e controla o PWM dos pinos 5 e 6. É também utilizado pelas funções delay(), millis() e micros().
- timer1 (16 bits) conta de 0 a 65535 e é utilizado para o comando PWM dos pinos 9 e 10. É também utilizado pela biblioteca Servo.h
- timer2 (8 bits) que é utilizado pela função Tone() e pela geração de PWM nos pinos 3 e 11.
Configuração dos timers
A parte mais complicada da utilização dos sensores é a sua configuração. Um temporizador é configurado por meio do seu registro de controle. Veja um resumo dos registros.
| Timer 0 | Timer 1 | Timer 2 | Papel |
|---|---|---|---|
| TCNT0 | TCNT1L | TCNT2 | Timer (bit 0 a 7) |
| – | TCNT1H | – | Timer (bit 8 a 15) |
| TCCR0A | TCCR1A | TCCR2A | Registro de controle |
| TCCR0B | TCCR1B | TCCR2B | Registro de controle |
| – | TCCR1C | – | Registro de controle |
| OCR0A | OCR1AL | OCR2A | Output Compare (bit 0 a 7) |
| – | OCR1AH | – | Output Compare (bit 8 a 15) |
| OCR0B | OCR1BL | OCR2B | Output Compare (bit 0 a 7) |
| – | OCR1BH | – | Output Compare (bit 8 a 15) |
| – | ICR1L | – | Input Capture (bit 0 a 7) |
| – | ICR1H | – | Input Capture (bit 8 a 15) |
| TIMSK0 | TIMSK1 | TIMSK2 | Interrupt Mask |
| TIFR0 | TIFR1 | TIFR2 | Interrupt Flag |
O registro TCNTx contém o valor do temporizador/contador. Os TCCRxA e TCCRxB são os registros de controle. Os OCRxA e OCRxB contêm os valores de registro a serem comparados. O TIMSKx contém a máscara de interrupção e o TIFRx contém as flags de ativação.
Código usando o timer2
Para este exemplo, utilizamos o timer2 que é codificado em 8bits (256). Desse modo, precisamos introduzir um contador adicional.
unsigned long elapsedTime, previousTime;
void onTimer() {
static boolean state = HIGH;
elapsedTime=millis()-previousTime;
Serial.print(F("Set LED 13 : "));
if(state){
Serial.print(F("ON"));
}else{
Serial.print(F("OFF"));
}
Serial.print(F(" - "));Serial.print(elapsedTime);Serial.println(F("ms"));
digitalWrite(13, state);
state = !state;
previousTime=millis();
}
void setup(){
Serial.begin(9600);
pinMode(13, OUTPUT);
cli(); // disable all interrupts
TCCR2A = (1<<WGM21)|(0<<WGM20); // Mode CTC
TIMSK2 = (1<<OCIE2A); // Local interruption OCIE2A
TCCR2B = (0<<WGM22)|(1<<CS22)|(1<<CS21); // Frequency 16Mhz/ 256 = 62500
OCR2A = 250; //250*125 = 31250 = 16Mhz/256/2
sei(); // enable all interrupts
}
ISR(TIMER2_COMPA_vect){ // timer compare interrupt service routine
static int counter=0;
if (++counter >= 125) { // 125 * 4 ms = 500 ms
counter = 0;
onTimer();
}
}
void loop(){
}
Código usando o timer1
Neste exemplo, vamos utilizar o timer1.
unsigned long elapsedTime, previousTime;
void onTimer() {
static boolean state = HIGH;
elapsedTime=millis()-previousTime;
Serial.print(F("Set LED 13 : "));
if(state){
Serial.print(F("ON"));
}else{
Serial.print(F("OFF"));
}
Serial.print(F(" - "));Serial.print(elapsedTime);Serial.println(F("ms"));
digitalWrite(13, state);
state = !state;
previousTime=millis();
}
void setup(){
Serial.begin(9600);
pinMode(13, OUTPUT);
cli(); // disable all interrupts
TCCR1A = 0;
TCCR1B = 0;
TCNT1 = 0;
OCR1A = 31250; // compare match register 16MHz/256/2 = 31250
TCCR1B = (1 << WGM12); // CTC mode
TCCR1B = (1 << CS12); // // Frequency 16Mhz/ 256 = 62500
TIMSK1 = (1 << OCIE1A); // Local interruption OCIE1A
sei(); // enable all interrupts
}
ISR(TIMER1_COMPA_vect){ // timer compare interrupt service routine
onTimer();
}
void loop(){
}
Obs: Acrescentamos uma medição do tempo decorrido para exemplificar, mas é preciso ter cuidado ao utilizar funções baseadas em interrupções nas funções chamadas por interrupções. Pode haver interferência.
Resultado
Uma vez iniciado o programa, o LED de bordo acende e apaga a cada 500ms
Fontes
Retrouvez nos tutoriels et d’autres exemples dans notre générateur automatique de code
La Programmerie

