#define WOKWI
// https://wokwi.com/projects/359175277281658881
// ec2021
// 2023-03-14
// Define the external interrupt pin
#define INTERRUPT_PIN 32 // Pin to detect an external signal
#define INTERRUPT_OUT_PIN 33 // Pin to simulate this "external signal"
#define LED0 26 // Pin where green LED is connected to
// is switched on by External Interrupt routine
// and switched off by onTimer
#define LED1 25 // Pin where red LED is connected to
// is toggled by External Interrupt routine
// Define the delay time in milliseconds
#define INITIAL_DELAY_COUNT 100 // msec
#define MAX_DELAY_COUNT 901 // msec
#define DELAY_STEPS 100 // msec
#define INTERRUPT_EVERY 1000 // msec
// Define the timer object
hw_timer_t *timer = NULL;
volatile boolean InterruptDetected = false; // set to true when an external interupt was detected
// used by onTimer to count the msec since it became
// true
volatile unsigned long delayCount = INITIAL_DELAY_COUNT; // Used by onTimer to count the number of
// onTimer calls while InterruptDetected was true
volatile boolean onTimerDone = false; // set to true by the onTimer routine when
// the counter "count" has reached the value of "delayCount"
volatile unsigned long lastInterrupt = 0; // Used by ExternalInterruptDetected() to store the
// time in millis() when an external interrupt was detected
volatile unsigned long lastOnTimer = 0; // Used by onTimer() to store the time when
// the counter "count" has reached the value of "delayCount"
void IRAM_ATTR onTimer() {
static int count = 0; // counter that counts the number of onTimer-Events
if (InterruptDetected) { // if (InterruptDetected) is true
if (count > delayCount) { // When count has reached delayCount count msec are elapsed
lastOnTimer = millis(); // Stores the time when this happened
// So that it can be printed in loop()
delayCount += DELAY_STEPS; // delayCount is increased by DELAY_STEPS every time this happens
// just to give different delay times
if (delayCount >= MAX_DELAY_COUNT) delayCount = INITIAL_DELAY_COUNT;
// Resets delayCount to the initial value
// not to exceed a certain limit, here MAX_DELAY_COUNT
InterruptDetected = false; // Resets the boolean InterruptDetected for the next interrupt
count = 0; // Resets count to zero for the next interrupt
digitalWrite(LED0, LOW); // Switches off LED0
onTimerDone = true; // Signalizes to loop() that new data are available
// from onTimer
}
count++; // Count the number of events while (InterruptDetected)
// was true
}
}
void IRAM_ATTR ExternalInterruptDetected() { // Fires everytime an external interrupt was detected
lastInterrupt = millis(); // Stores the time when it was detected
digitalWrite(LED0, HIGH); // Switch on LED0 (green) to visualize "Interrupt raised"
digitalWrite(LED1, !digitalRead(LED1)); // Visualize interrupt call by toggling LED1 (red)
InterruptDetected = true; // Signalizes to onTime that an Interrupt was detected
}
void setup() {
// Initialize serial communication
Serial.begin(115200);
// Initialize LEDs
pinMode(LED0, OUTPUT);
digitalWrite(LED0, HIGH);
pinMode(LED1, OUTPUT);
digitalWrite(LED1, LOW);
// Initialize Pin to simulate "External Interrupts"
pinMode(INTERRUPT_OUT_PIN, OUTPUT);
digitalWrite(INTERRUPT_OUT_PIN, HIGH);
delay(10);
// Attach the interrupt to the interrupt pin
pinMode(INTERRUPT_PIN, INPUT_PULLUP);
attachInterrupt(digitalPinToInterrupt(INTERRUPT_PIN), ExternalInterruptDetected, FALLING);
// Prepare timer for repetitive use, fires every 1 msec
int divisor = 80;
#ifdef WOKWI // In Wokwi simulation the divisor has to be 40 instead of 80 to get a clock tick of 1 microsec
divisor = 40;
#endif
timer = timerBegin(0, divisor, true);
timerAttachInterrupt(timer, &onTimer, true);
timerAlarmWrite(timer, 1000, true);
timerAlarmEnable(timer);
}
unsigned long lastChange = 0;
void loop() {
if (millis() - lastChange > INTERRUPT_EVERY) { // Create an Interrupt signal every INTERRUPT_EVERY msec
lastChange = millis(); // Store the actual time in msec
digitalWrite(INTERRUPT_OUT_PIN, LOW); // Create a Falling Edge
digitalWrite(INTERRUPT_OUT_PIN, HIGH); // Prepare for next interrupt creation
Serial.print("Last Interrupt @\t"); // Print the time when this last interrupt
Serial.print(lastInterrupt); // was registered by ExternalInterrupt()
Serial.print("\t");
}
if (onTimerDone) {
onTimerDone = false;
Serial.print("Last onTimer @\t\t"); // Print when onTimer was called last
Serial.print(lastOnTimer);
Serial.print("\tTime elapsed = \t"); // Print the time difference between when the external
Serial.println(lastOnTimer - lastInterrupt); // Interrupt was raised and onTimer was called
}
}