Arduino/ESP8266 仅当脉冲之间的时间差为零时,去抖动(使用中断)才会失败
Arduino/ESP8266 debounce (using interrupt) fails only when time difference is zero between pulses
我有一块ESP8266(NodeMCU)开发板。我正在尝试在使用中断时在连接到 GPIO5 的触觉按钮上实现软件去抖动。对于“relayPin”,我暂时使用板载 LED (GPIO16)。
当我尝试按下按钮并非常快速地摆动它时,去抖动在大多数情况下都有效。然而,它在极少数情况下会失败,并且仅当两个不同检测到的脉冲之间的时间间隔为零时才会失败。所以基本上,当时间间隔大于 0 且小于去抖时间 (200ms) 时,它永远不会失败。请查看串行监视器的图像。
虽然这个问题发生在极端条件下(开关不会以这种方式使用),但我仍然想弄清楚这是否与我的代码有关或我不知道的其他方面.
Image 1: Push-button circuit
Image 2: Code & serial monitor
int swButton = 5;
int relayPin = 16;
bool relayOn = false; // Present on/off state of the relay.
int debounceTime = 200; // Debounce time in ms.
volatile bool switchToggle = false; // True when button press is valid (and not bounce noise).
volatile unsigned long nowPush = 0; // The millis() time of the present button press.
volatile unsigned long lastPush = 0; // The millis() time of the previous button press.
volatile unsigned long timeGap = 0; // The difference of the nowPush and lastPush times.
// Interrupt Service Routine on button press (falling edge).
ICACHE_RAM_ATTR void swButtonISR() {
nowPush = millis();
timeGap = nowPush - lastPush;
// Debouncing stuff, recognizing this button-press as a valid one.
if (timeGap > debounceTime) {
switchToggle = true;
lastPush = nowPush;
}
}
// Function that toggles the relay when called upon.
void toggleRelay () {
if (relayOn) {
digitalWrite(relayPin, LOW); // Turn off relay.
relayOn = false;
Serial.println((String)"Relay ON. Time gap: "+timeGap);
return;
}
else {
digitalWrite(relayPin, HIGH); // Turn on relay.
relayOn = true;
Serial.println((String)"Relay OFF. Time gap: "+timeGap);
return;
}
return;
}
void setup() {
Serial.begin(115200);
pinMode(swButton, INPUT);
pinMode(relayPin, OUTPUT);
pinMode(greenLED, OUTPUT);
attachInterrupt(digitalPinToInterrupt(swButton), swButtonISR, FALLING);
}
void loop() {
if (switchToggle == true) {
toggleRelay();
switchToggle = false;
}
}
您可以进行一些更改,以在“释放按钮”后强制延长延迟时间。 (您也可以只附加一个带有 CHANGE 条件的中断处理程序,以捕获 FALLING 和 RISING边。)
添加这个
attachInterrupt(digitalPinToInterrupt(swButton), swButtonISR2, RISING);
改变这个
ICACHE_RAM_ATTR void swButtonISR() {
nowPush = millis();
timeGap = nowPush - lastPush;
// Debouncing stuff, recognizing this button-press as a valid one.
if (timeGap > debounceTime) {
switchToggle = true;
}
lastPush = nowPush;
}
添加这个
ICACHE_RAM_ATTR void swButtonISR2() {
lastPush = millis();
}
我有一块ESP8266(NodeMCU)开发板。我正在尝试在使用中断时在连接到 GPIO5 的触觉按钮上实现软件去抖动。对于“relayPin”,我暂时使用板载 LED (GPIO16)。
当我尝试按下按钮并非常快速地摆动它时,去抖动在大多数情况下都有效。然而,它在极少数情况下会失败,并且仅当两个不同检测到的脉冲之间的时间间隔为零时才会失败。所以基本上,当时间间隔大于 0 且小于去抖时间 (200ms) 时,它永远不会失败。请查看串行监视器的图像。
虽然这个问题发生在极端条件下(开关不会以这种方式使用),但我仍然想弄清楚这是否与我的代码有关或我不知道的其他方面.
Image 1: Push-button circuit
Image 2: Code & serial monitor
int swButton = 5;
int relayPin = 16;
bool relayOn = false; // Present on/off state of the relay.
int debounceTime = 200; // Debounce time in ms.
volatile bool switchToggle = false; // True when button press is valid (and not bounce noise).
volatile unsigned long nowPush = 0; // The millis() time of the present button press.
volatile unsigned long lastPush = 0; // The millis() time of the previous button press.
volatile unsigned long timeGap = 0; // The difference of the nowPush and lastPush times.
// Interrupt Service Routine on button press (falling edge).
ICACHE_RAM_ATTR void swButtonISR() {
nowPush = millis();
timeGap = nowPush - lastPush;
// Debouncing stuff, recognizing this button-press as a valid one.
if (timeGap > debounceTime) {
switchToggle = true;
lastPush = nowPush;
}
}
// Function that toggles the relay when called upon.
void toggleRelay () {
if (relayOn) {
digitalWrite(relayPin, LOW); // Turn off relay.
relayOn = false;
Serial.println((String)"Relay ON. Time gap: "+timeGap);
return;
}
else {
digitalWrite(relayPin, HIGH); // Turn on relay.
relayOn = true;
Serial.println((String)"Relay OFF. Time gap: "+timeGap);
return;
}
return;
}
void setup() {
Serial.begin(115200);
pinMode(swButton, INPUT);
pinMode(relayPin, OUTPUT);
pinMode(greenLED, OUTPUT);
attachInterrupt(digitalPinToInterrupt(swButton), swButtonISR, FALLING);
}
void loop() {
if (switchToggle == true) {
toggleRelay();
switchToggle = false;
}
}
您可以进行一些更改,以在“释放按钮”后强制延长延迟时间。 (您也可以只附加一个带有 CHANGE 条件的中断处理程序,以捕获 FALLING 和 RISING边。)
添加这个
attachInterrupt(digitalPinToInterrupt(swButton), swButtonISR2, RISING);
改变这个
ICACHE_RAM_ATTR void swButtonISR() {
nowPush = millis();
timeGap = nowPush - lastPush;
// Debouncing stuff, recognizing this button-press as a valid one.
if (timeGap > debounceTime) {
switchToggle = true;
}
lastPush = nowPush;
}
添加这个
ICACHE_RAM_ATTR void swButtonISR2() {
lastPush = millis();
}