/*
Arduino Interrupt Demonstration
Features:
- External interrupt on pin 2
- ISR execution counting
- Debounce handling
- Event timestamping
- Main loop communication via volatile variables
- Interrupt mode switching
*/
const byte BUTTON_PIN = 2;
const byte LED_PIN = 13;
// Variables shared between ISR and main code
volatile unsigned long interruptCount = 0;
volatile unsigned long lastInterruptTime = 0;
volatile bool eventOccurred = false;
unsigned long lastReportTime = 0;
unsigned long modeChangeTime = 0;
enum InterruptMode {
MODE_RISING,
MODE_FALLING,
MODE_CHANGE
};
InterruptMode currentMode = MODE_FALLING;
// ISR
void buttonISR()
{
unsigned long now = millis();
// Simple debounce (50 ms)
if (now - lastInterruptTime < 50)
return;
interruptCount++;
lastInterruptTime = now;
eventOccurred = true;
}
void setup()
{
Serial.begin(115200);
pinMode(BUTTON_PIN, INPUT_PULLUP);
pinMode(LED_PIN, OUTPUT);
attachInterrupt(
digitalPinToInterrupt(BUTTON_PIN),
buttonISR,
FALLING
);
Serial.println("Interrupt Demo Started");
Serial.println("Press the button connected to pin 2");
}
void loop()
{
// Process interrupt events safely
if (eventOccurred)
{
noInterrupts();
unsigned long count = interruptCount;
unsigned long timestamp = lastInterruptTime;
eventOccurred = false;
interrupts();
digitalWrite(LED_PIN, !digitalRead(LED_PIN));
Serial.print("Interrupt detected. Count = ");
Serial.print(count);
Serial.print(" Time = ");
Serial.print(timestamp);
Serial.println(" ms");
}
// Print status every 5 seconds
if (millis() - lastReportTime >= 5000)
{
lastReportTime = millis();
noInterrupts();
unsigned long count = interruptCount;
interrupts();
Serial.println("\n--- Status Report ---");
Serial.print("Total interrupts: ");
Serial.println(count);
Serial.print("Current mode: ");
switch (currentMode)
{
case MODE_RISING:
Serial.println("RISING");
break;
case MODE_FALLING:
Serial.println("FALLING");
break;
case MODE_CHANGE:
Serial.println("CHANGE");
break;
}
Serial.println("---------------------");
}
// Demonstrate changing interrupt modes every 15 seconds
if (millis() - modeChangeTime >= 15000)
{
modeChangeTime = millis();
detachInterrupt(digitalPinToInterrupt(BUTTON_PIN));
switch (currentMode)
{
case MODE_FALLING:
currentMode = MODE_RISING;
attachInterrupt(
digitalPinToInterrupt(BUTTON_PIN),
buttonISR,
RISING
);
Serial.println("Switched to RISING mode");
break;
case MODE_RISING:
currentMode = MODE_CHANGE;
attachInterrupt(
digitalPinToInterrupt(BUTTON_PIN),
buttonISR,
CHANGE
);
Serial.println("Switched to CHANGE mode");
break;
case MODE_CHANGE:
currentMode = MODE_FALLING;
attachInterrupt(
digitalPinToInterrupt(BUTTON_PIN),
buttonISR,
FALLING
);
Serial.println("Switched to FALLING mode");
break;
}
}
}