As I learned that millis() doesn't increment inside an ISR, I figured out a way to detect short/long press with attachInterrupt. It is really simple I use the rising and the falling edge, and then calculate the time spent between the two ISRs. But I need help finding a way to stop this "timer" in the falling edge, because it doesn't stop and after some short presses it detects it as a long press.
unsigned long firstv;
unsigned long secondv;
const int button = 3;
void setup() {
// put your setup code here, to run once:
Serial.begin(9600);
pinMode(button, INPUT);
attachInterrupt(digitalPinToInterrupt(3), up, RISING);
attachInterrupt(digitalPinToInterrupt(3), down, FALLING);
}
void loop() {
// put your main code here, to run repeatedly:
}
void up() {
firstv = millis();
}
void down() {
secondv = millis();
if((secondv - firstv) >= 3000) {
firstv = secondv;
Serial.println("Long press");
}
else {
Serial.println("Short press");
}
}
There are a few button libraries for the Arduino; I use the EasyButton.h library to detect long or short presses.
I've never used interrupts in my projects, but there are a couple if interrupt exampled with the library.
Contact bounce. If the interval is less than 50ms ignore it for a short press event.
Also some tips...
There is nothing you couldn’t have done here with millis() timing in loop. Interrupts are generally wholly unsuited to detecting button presses (and other events that happen on a glacial timescale). One of the reasons is as you have discovered here.
You can detect the long press and short press without interrupt. There is one dedicated tutorial on button long press and short press without using interrupt
Sorry, I did not post the whole code, but that thing is really complex and a lot of things are going on there so the interrupt is a must in my case. Also, I have a perfectly clean signal as I used a schmitt trigger to debounce the button.
If your switch is active high and you have denounced your switch then your code is perfect as far as I can see.
Did you try ignoring really short presses less than 50ms?
I don't think I can ignore really short presses. Actually I've found out that it does not execute the up function. I used serial to display the first value and then the second value. I only saw the second one and it only shows the first when I delete the attachInterrupt for the down function.
You can only have one ISR per pin. The last one you set is the only one active. In your case, you will only get interrupts for falling edges. The way to work around the restriction is put an attachInterrupt() for the 'up' interrupt in the 'down' ISR and put an attachInterrupt() for the 'down' interrupt in the 'up' ISR.