Dominar los Temporizadores Internos de Arduino para Temporización Precisa
Componentes y suministros
| Componente | Cantidad |
|---|---|
| Arduino UNO | 1 |
| LED (genérico) | 1 |
| Resistencia 220 Ω | 1 |
Sobre el proyecto
Visión general
Si necesitas contar tiempo con precisión, debes usar un temporizador (timer) hardware. La función delay() bloquea la CPU, pero con un timer puedes hacer otras tareas mientras esperas: cuando llega el momento, se activa una interrupción (ISR).
Este tutorial explica el uso del Timer0 (el más sencillo) en un Arduino UNO (ATmega328P). En el futuro cubriré Timer1 y Timer2.
Cómo funciona
El Timer0 es un contador de 8 bits (registro TCNT0). Recibe pulsos del reloj del sistema (16 MHz) a través de un preescaler que divide la frecuencia. Cada pulso incrementa TCNT0.
En modo CTC (Clear Timer on Compare), se compara TCNT0 con el registro OCR0A. Cuando coinciden, se genera una interrupción (TIMER0_COMPA_vect) y el contador se reinicia a 0.
Configuración del preescaler (registro TCCR0B)
| CS02 | CS01 | CS00 | Divisor | Frecuencia resultante |
|---|---|---|---|---|
| 0 | 0 | 1 | 1 | 16 MHz |
| 0 | 1 | 0 | 8 | 2 MHz |
| 0 | 1 | 1 | 64 | 250 kHz |
| 1 | 0 | 0 | 256 | 62.5 kHz |
| 1 | 0 | 1 | 1024 | 15.625 kHz |
Cálculo de OCR0A para 1 ms
Con preescaler 64: 16.000.000 / 64 = 250.000 ciclos/seg. Para 1 ms → 250 ciclos. Como el contador empieza en 0, OCR0A = 249 (0xF9).
Código de configuración para interrupción cada 1 ms
TCCR0A |= (1 << WGM01); // Modo CTC
OCR0A = 0xF9; // 249 → 1 ms @ 16MHz/64
TIMSK0 |= (1 << OCIE0A); // Habilitar interrupción Compare Match A
sei(); // Habilitar interrupciones globales
TCCR0B |= (1 << CS01) | (1 << CS00); // Preescaler 64 (inicia el timer)
Importante: Configura el preescaler al final, porque el timer empieza a contar inmediatamente. Para pararlo, pon a 0 los bits CS0x de TCCR0B.
Ejemplo completo: Parpadear LED cada 1 segundo sin delay()
int timer = 0;
bool state = false;
void setup() {
pinMode(13, OUTPUT);
TCCR0A = (1 << WGM01); // CTC mode
OCR0A = 0xF9; // 1 ms
TIMSK0 |= (1 << OCIE0A); // Interrupt on compare match
sei(); // Global interrupts
TCCR0B |= (1 << CS01) | (1 << CS00); // Prescaler 64
}
void loop() {
if (timer >= 1000) { // 1000 ms = 1 s
state = !state;
timer = 0;
}
digitalWrite(13, state);
}
ISR(TIMER0_COMPA_vect) {
timer++; // Se ejecuta cada 1 ms
}
Ventajas: el loop() sigue libre para otras tareas (leer sensores, comunicaciones, etc.) mientras el temporizador lleva la cuenta en segundo plano.
Esquemático
LED en pin 13 con resistencia 220Ω a GND. Ver imagen adjunta.
Proceso de manufactura
- Construye un Spybot controlado por Bluetooth con Arduino
- FlickMote: Mando IR por gestos para Smart Home
- TV‑B‑Gone DIY con Arduino: Mando universal para apagar cualquier TV
- Construye un Reloj Maestro LED Personalizado con Alarma – Visible desde 12 Metros
- Find Me: Localizador Inteligente de Objetos con Arduino y Bluetooth
- Soluciones de Alimentación Optimizadas para Proyectos Arduino
- Tres en raya con Arduino, matriz LED MAX7219 y carcasa de cartón
- Construye un Robot Cuadrúpedo Inteligente con Arduino: Guía Paso a Paso
- Construye un volante joystick personalizado con Arduino para gaming
- Construye una Máquina CNC Totalmente Funcional con Arduino Nano R3
- Earth Analyzer: Kit Avanzado IoT de Sensores para Monitorización Ambiental