Try my secret template, once you understand the flow, you can use it in many cases. And it is just plain codes, no library or any dependency, good luck.
int LED1 = 12;
int LED2 = 13;
int button = 3;
boolean LED1State = false;
boolean LED2State = false;
long buttonTimer = 0;
long longPressTime = 250;
boolean buttonActive = false;
boolean longPressActive = false;
void setup() {
pinMode(LED1, OUTPUT);
pinMode(LED2, OUTPUT);
pinMode(button, INPUT);
}
void loop() {
if (digitalRead(button) == HIGH) {
if (buttonActive == false) {
// do things once key pressed
buttonActive = true;
buttonTimer = millis();
}
if ((millis() - buttonTimer > longPressTime) && (longPressActive == false)) {
// do things once long pressed
longPressActive = true;
LED1State = !LED1State;
digitalWrite(LED1, LED1State);
}
} else {
if (buttonActive == true) {
if (longPressActive == true) {
// do things after long pressed
longPressActive = false;
} else {
//do things after key released
LED2State = !LED2State;
digitalWrite(LED2, LED2State);
}
buttonActive = false;
}
}
}
Have a variable in the button object that records its state
Differentiate between the states you foresee; e.g. "idle", "held", "short press", "long press"
Have the button object cycle through the states depending on the environment. E.g. as soon as the button is pressed, it transitions from "idle" to "held". If it's released within the short press period, transition to "short press". If it's held for longer than that, transition to "long press"
Make a function that can be called to retrieve the button's state. The return value denotes the state; you can simply return the variable that the object uses to maintain its state
Make the button object reset its state after a short or long press event is retrieved by a caller.
You can use millis() to keep track of time and an update() function in your button object that's called frequently from loop() to ensure the button object cycles through the states as desired.
The advantage of the above is that you don't have much redundancy in your code; the same code runs for both of your buttons, and it can easily be scaled up for many more buttons. You can cycle through button objects using arrays.
PS: I see you're configuring a timer. If you're not allowed to use millis(), you can use a timer that triggers an interrupt every millisecond to increment an unsigned long variable that you can use instead of millis(). If you can use millis(), you don't need to configure a timer at all.
A state machine is pretty much the way to go here.
For one button it could look like this:
Every box is a state. To change the state you need to walk an arrow.
Each arrow come with conditions that need to be met and when you walk an arrow, you need to do something.
e.g.
Arrow Idle -> Debounce
Conditions:
* button == down
Actions:
* Start timer
Arrow Debounce -> Idle
Conditions:
* timer > 10ms
* button == up
Actions:
* <none>
Arrow Long -> Long
Conditions:
* timer > 1s
Actions:
* Start timer
* var += 10