Étiquettes : , ,
4
(1)

L’utilisation des timers en Arduino est une méthode avancées permettant d’exécuter du code sans perturber le reste du programme. Ils permettent notamment d’activer des fonctions à des intervalles de temps précis. Les timers sont utilisées dans bon nombre de librairie de manière complètement transparente pour l’utilisateur (millis(), Servo.h, PWM, etc.)

Dans certains cas, il est possible d’utiliser des librairies qui configure les timers qui simplifierons l’utilisation.

Matériel

  • Arduino UNO
  • Câble USB A/ USB B

Description

Les timers sont des registres du microprocesseur qui s’incrémente en fonction des impulsions d’horloge ou d’impulsions extérieures. Il est possible de les configurer pour modifier leur comportement.

Le microprocesseur de l’Arduino UNO (ATmega328P) possède 3 timers:

  • timer0 (8 bits) compte de 0 à 256 et commande la PWM des broches 5 et 6. Il est aussi utilisé par les fonctions delay(), millis() et micros().
  • timer1 (16 bits) compte de 0 à 65535 et est utilisé pour la commande PWM des broches 9 et 10. Il est utilisé également par la libriaire Servo.h
  • timer2 (8 bits) qui est utilisé par la fonction Tone() et la génération de la PWM sur les broches 3 et 11.

Configuration des Timers

La partie la plus compliqué de l’utilisation du capteur est leur configuration. Un timer est configuré à l’aide de son registre de controle. Voici le rappel des registre.

Timer 0Timer 1Timer 2Rôle
TCNT0TCNT1LTCNT2Timer (bit 0 à 7)
TCNT1HTimer (bit 8 à 15)
TCCR0ATCCR1ATCCR2ARegistre de contrôle
TCCR0BTCCR1BTCCR2BRegistre de contrôle
TCCR1CRegistre de contrôle
OCR0AOCR1ALOCR2AOutput Compare (bit 0 à 7)
OCR1AHOutput Compare (bit 8 à 15)
OCR0BOCR1BLOCR2BOutput Compare (bit 0 à 7)
OCR1BHOutput Compare (bit 8 à 15)
ICR1LInput Capture (bit 0 à 7)
ICR1HInput Capture (bit 8 à 15)
TIMSK0TIMSK1TIMSK2Interrupt Mask
TIFR0TIFR1TIFR2Interrupt Flag

Le registre TCNTx contient la valeur du timer/counter, le registre TCCRxA et TCCRxB sont les registres de contrôles. OCRxA rt OCRxB contiennent les valeurs de registre à comparer. TIMSKx contient le masque d’interruption et TIFRx, quant à lui, contient les flags d’activation.

Code utilisant le timer2

Pour cette exemple, nous utilisons le timer2 qui est codé sur 8bits (256). Il nous faut donc introduire un compteur supplémentaire.

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(){
}

Code utilisant le timer1

Pour cette exemple, nous allons utiliser le 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(){
}

N.B. : Nous avons rajouté une mesure du temps écoulé à titre d’illustration mais il faut faire attention lorsqu’on utilise des fonctions basées sur les interruptions dans les fonctions appelées par des interruptions. Il peut y avoir des interférences.

Résultat

Une fois le programme lancé, la LED embarquée s’allume et s’éteint toutes les 500ms

Sources

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 4 / 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?