fbpixel
Etiquetas: , ,
5
(1)

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 0Timer 1Timer 2Papel
TCNT0TCNT1LTCNT2Timer (bit 0 a 7)
TCNT1HTimer (bit 8 a 15)
TCCR0ATCCR1ATCCR2ARegistro de controle
TCCR0BTCCR1BTCCR2BRegistro de controle
TCCR1CRegistro de controle
OCR0AOCR1ALOCR2AOutput Compare (bit 0 a 7)
OCR1AHOutput Compare (bit 8 a 15)
OCR0BOCR1BLOCR2BOutput Compare (bit 0 a 7)
OCR1BHOutput Compare (bit 8 a 15)
ICR1LInput Capture (bit 0 a 7)
ICR1HInput Capture (bit 8 a 15)
TIMSK0TIMSK1TIMSK2Interrupt Mask
TIFR0TIFR1TIFR2Interrupt 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

How useful was this post?

Click on a star to rate it!

Average rating 5 / 5. Vote count: 1

No votes so far! Be the first to rate this post.

As you found this post useful...

Follow us on social media!

We are sorry that this post was not useful for you!

Let us improve this post!

Tell us how we can improve this post?