I had been doing button debounce using a variable called btn_debounce_timer, like so:
Code: Select all
#define DEBOUNCE_DELAY 50
int btn_debounce_timer = 0;
[...]
boolean btn_read(boolean *btn_dwn, int btn_pin) {
if ( (millis() - btn_debounce_timer) <= DEBOUNCE_DELAY ) return false; // too soon to read again
if ( digitalRead(btn_pin) == 0 ) { // the button is pressed
if ( ! *btn_dwn ) { // the state has changed
btn_debounce_timer = millis();
*btn_dwn = true;
return true;
}
} else {
if ( *btn_dwn ) { // the state has changed
btn_debounce_timer = millis();
*btn_dwn = false;
return true;
}
}
return false;
}
The bug was the it seemed to work fine for a while, then it would stop debouncing properly. The problem is that on the arduino/ATmega, the "int" type is a signed 16 bit integer, so after 32767ms (about half a minute) the value of millis() overflows the 16 bit int, and you get weird behavior. Changing the type of btn_debounce_timer to uint32_t fixed all the problems. I've been too used to assuming that an int is 32 bits (or greater).