About
In this post, we’ll take a look at interrupts and timers in microcontrollers. I will show you how to implement it with an Arduino and with an ESP8266 or ESP32.
When an interrupt is triggered, the microcontroller will pause what it’s doing and immediately run an ISR(Interrupt Service Routine) before returning to where it left off before.
External: You can have interrupts that are triggered by external events via an input pin.
Internal: Or you can have internal interrupts triggered by something like a timer you’ve set up.
External hardware interrupt example for the Arduino:
//Any variable used by interrupts need to be marked as volatile.
//This prevents the compiler from optimizing it and missing the changed value.
volatile int pulseCount = 0;
void setup() {
Serial.begin(9600);
//Define interrupt on pin 2(on uno/duemilanove pins 2 and 3 can be used for external interrupts).
//On rising edge function countPulse() will be called.
pinMode(2, INPUT);
attachInterrupt(digitalPinToInterrupt(2), countPulse, RISING);
}
void loop() {
Serial.println("Interupts triggered: " + pulseCount);
delay(1000);
}
//ISR function called by the interrupt.
void countPulse() {
pulseCount++;
}
External hardware interrupt example for the ESP:
//Any variable used by interrupts need to be marked as volatile.
//This prevents the compiler from optimizing it and missing the changed value.
volatile int pulseCount = 0;
void setup() {
Serial.begin(9600);
//Define interrupt on pin. On rising edge function countPulse() will be called.
//Check which pins can be used for interrupts for your specific board.
pinMode(4, INPUT);
attachInterrupt(digitalPinToInterrupt(4), countPulse, RISING);
}
void loop() {
Serial.println("Interupts triggered: " + pulseCount);
delay(1000);
}
//ISR function called by the interrupt. For the ESP the interrupt function must be marked with ICACHE_RAM_ATTR.
void ICACHE_RAM_ATTR countPulse() {
pulseCount++;
}}
Internal interrupt example for the Arduino using a timer. For more info, check the official documentation.
//Any variable used by interrupts need to be marked as volatile.
//This prevents the compiler from optimizing it and missing the changed value.
volatile boolean timerTriggered = false;
void setup() {
//Disable interrupts to avoid any accidental interrupts during setup.
noInterrupts();
//Clear timer control registers.
TCCR1A = 0;
TCCR1B = 0;
//Reset actual timer value.
TCNT1 = 0;
//Set timer count. 15624 value will be rached every 1s assuming the prescaler is set to 1024 and the clock is 16MHz.
OCR1A = 15624;
//Set timer in CTC(Clear Timer on Compare Match). This will reset the timer count value in TCNT1 whenever it reaches the value set in OCIE1A.
TCCR1B |= (1 << WGM12); // CTC mode
//Set the timer prescaler to 1024 by setting the bits to 101. See section "15.11.2 TCCR1B – Timer/Counter1 Control Register B" in documentation.
TCCR1B |= (1 << CS12) | (1 << CS10);
//Enable compare interrupt. Every time the timer value reaches the value we specified in OCR1A the timer interrupt will be triggered.
TIMSK1 |= (1 << OCIE1A);
//Re-enable interrupts after setup.
interrupts();
Serial.begin(9600);
}
void loop() {
//Check if timer was triggered.
if (timerTriggered) {
//Reset flag.
timerTriggered = false;
Serial.println("Timer triggered.");
}
}
//Specify ISR to be triggered by TIMER1.
ISR(TIMER1_COMPA_vect) {
//Set flag.
timerTriggered = true;
}
Timer triggers every 1s.





