El uso de temporizadores en Arduino es un método avanzado para ejecutar código sin perturbar el resto del programa. Permiten activar funciones en intervalos de tiempo específicos. Los temporizadores se utilizan en muchas bibliotecas de forma totalmente transparente para el usuario (millis(), Servo.h, PWM, etc.)
En algunos casos, es posible utilizar bibliotecas que configuran temporizadores que simplificarán el uso.
Material
- Arduino UNO
- Cable USB A/ USB B
Descripción
Los temporizadores son registros del microprocesador que se incrementan según los impulsos del reloj o los impulsos externos. Es posible configurarlos para modificar su comportamiento.
El microprocesador Arduino UNO (ATmega328P) tiene 3 temporizadores:
- timer0 (8 bits) cuenta de 0 a 256 y controla el PWM de los pines 5 y 6. También es utilizado por las funciones delay(), millis() y micros().
- timer1 (16 bits) cuenta de 0 a 65535 y se utiliza para el control PWM de los pines 9 y 10. También es utilizado por la biblioteca Servo.h
- timer2 (8 bits) que es utilizado por la función Tone() y la generación de PWM en los pines 3 y 11.
Configuración del temporizador
La parte más complicada del uso del sensor es su configuración. Un temporizador se configura mediante su registro de control. Aquí está el recordatorio de los registros.
Timer 0 | Timer 1 | Timer 2 | Rôle |
---|---|---|---|
TCNT0 | TCNT1L | TCNT2 | Timer (bit 0 à 7) |
– | TCNT1H | – | Timer (bit 8 à 15) |
TCCR0A | TCCR1A | TCCR2A | Registre de contrôle |
TCCR0B | TCCR1B | TCCR2B | Registre de contrôle |
– | TCCR1C | – | Registre de contrôle |
OCR0A | OCR1AL | OCR2A | Output Compare (bit 0 à 7) |
– | OCR1AH | – | Output Compare (bit 8 à 15) |
OCR0B | OCR1BL | OCR2B | Output Compare (bit 0 à 7) |
– | OCR1BH | – | Output Compare (bit 8 à 15) |
– | ICR1L | – | Input Capture (bit 0 à 7) |
– | ICR1H | – | Input Capture (bit 8 à 15) |
TIMSK0 | TIMSK1 | TIMSK2 | Interrupt Mask |
TIFR0 | TIFR1 | TIFR2 | Interrupt Flag |
El registro TCNTx contiene el valor del temporizador/contador, los registros TCCRxA y TCCRxB son los registros de control. OCRxA y OCRxB contienen los valores de los registros a comparar. TIMSKx contiene la máscara de interrupción y TIFRx contiene las banderas de habilitación.
Código que utiliza timer2
Para este ejemplo, utilizamos el temporizador2 que está codificado en 8bits (256). Así que tenemos que introducir un 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 que utiliza el temporizador1
Para este ejemplo, utilizaremos el temporizador1
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.: Hemos añadido una medida de tiempo transcurrido con fines ilustrativos, pero hay que tener cuidado al utilizar funciones basadas en interrupciones en funciones invocables por interrupción. Puede haber interferencias.
Resultado
Una vez iniciado el programa, el LED de la placa se enciende y se apaga cada 500ms
Fuentes
- Referencia de Arduino sobre los temporizadores
- Wiki on timers
- Ficha técnica de ATmega
- Multitarea con Arduino
Retrouvez nos tutoriels et d’autres exemples dans notre générateur automatique de code
La Programmerie