Closed scottkelso closed 3 years ago
Hi @scottkelso,
The library DeepSleepScheduler
does not support debouncing as such. I only added the possibility to schedule a task once until it is actually executed.
It does this by first removing all scheduled tasks of the same task and then add it again. This means that as soon as the tasks executes, it can be added again if the interrupt still triggers an execution. That's why you see multiple executions of your task measure_rotation()
.
I suggest to still follow the recommendations of the EnableInterrupt's Debounce example and call scheduleOnce()
instead of digitalWrite()
in that example.
Do not use delay()
in an ISR
as it must run as short as possible and as I remember does delay()
do nothing inside an ISR
.
I suggest something like the following.
Cheers, Pete
#include "DeepSleepScheduler.h"
#define DEBOUNCE_DELAY_MS 100
#define INTERRUPT_PIN 2
#define LED_PIN LED_BUILTIN
unsigned long lastInterruptTimeMs = 0;
unsigned long isrCount = 0;
void task() {
Serial.print("isrCount: ");
Serial.println(isrCount);
digitalWrite(LED_PIN, !digitalRead(LED_PIN));
}
void isrInterruptPin() {
isrCount++;
unsigned long interruptTimeMs = millis();
if (interruptTimeMs - lastInterruptTimeMs > DEBOUNCE_DELAY_MS) {
scheduler.scheduleOnce(task);
}
lastInterruptTimeMs = interruptTimeMs;
}
void setup() {
Serial.begin(115200);
delay(150);
Serial.println("======================= start");
pinMode(INTERRUPT_PIN, INPUT_PULLUP);
attachInterrupt(digitalPinToInterrupt(INTERRUPT_PIN), isrInterruptPin, FALLING);
pinMode(LED_PIN, OUTPUT);
digitalWrite(LED_PIN, HIGH);
scheduler.acquireNoSleepLock();
}
void loop() {
scheduler.execute();
}
Description
I would find it very helpful if you provided a debounce example and how that works with DeepSleepScheduler. I have tried with my own intuition and have been so far unsuccessful.
Problem
I am trying to fire a single interrupt on pin 2 of my Elegoo Mega2560 using the CLK pin of a rotary encoder. My aim is to wake up my system from sleep with a turn of the rotary encoder, turning on an LCD display eta. When I attempt to implement this myself using DeepSleepScheduler, instead of the expected one interrupt on rotation of the rotary encoder, I get 2 (I also see sometimes 1 and 3, although less frequently).
Steps to Reproduce
I suspect this is due to debounce and my bad implementation of it in your library. Below I have the non-DeepSleepScheduler version which works, followed by non-working versions which use DeepSleepScheduler.
This is a working example that doesn't use the DeepSleepScheduler library and works correctly - firing only once for each turn of the rotary encoder.
This is what I assumed the same code might look like using DeepSleepScheduler. Notice the
scheduleDelayed
with the same 4 milliseconds for debouncing. Increasing the value here made no difference. I also tried delayed re-attaching of the interrupt, and combination ofscheduleOnce
andscheduleDelayed
to make sure only onemeasure_rotation
call was ever in the job queue. However, nearly every time there was a second delayedmeasure_rotation
call.This example was an attempt inspired by EnableInterrupt's Debounce example. This, unfortunately, did not allow any interrupt calls.
Any advice or guidance would be much appreciated. Thanks!