I am building a control panel with several illuminated push-buttons. The indicator of the button needs to be in a different state/phase depending on how many times the button has been pressed, the phases are:-
0. (default state) the indicator must blink on and off every second,
1. (after 1st press) the indicator must stay illuminated until the 2nd press,
2. (after 2nd press) the indicator must extinguish for a predetermined amount of time before reverting back to phase 0, during this phase the loop() still needs to run.
The problem I am having is that currently I can only achieve phase 2 using a delay, which prevents the loop() from running, this is acceptable with short delays but on some buttons this delay will need to be up to a minute.
Code is below:-
#include <OneButton.h> // load OneButton library
const int indicator = 17; // define indicator pin
int phaseCount = 0; // define variables:
bool butStatePre = true;
bool butStateCur = true;
unsigned long millisPre = 0;
unsigned long millisCur;
unsigned long phaseStart;
const int phaseDelay = 3000; // delay for phase to timeout
OneButton but = OneButton(4, true, true); // define OneButton instance
void setup() { // put your setup code here, to run once:
pinMode(indicator, OUTPUT); // initialise indicator pin
but.attachClick(butClick); // attach OneButton state event
Serial.begin(9600); // initialise the serial monitor
}
void loop() { // put your main code here, to run repeatedly:
millisCur = millis(); // update current time
but.tick(); // query button
while (phaseCount == 0) { // blink indicator when required (phase 0 case):
digitalWrite(indicator, (millis() / 1000) % 2);
but.tick();
}
}
void butClick() { // button process flow:
if (butStateCur != butStatePre) { // test if button state has changed
butStatePre = butStateCur; // update current button state
phaseCount ++; // increment phase counter
} if (phaseCount == 0) { // phase 1 case:
digitalWrite(indicator, HIGH); // illuminate indicator
phaseCount ++; // increment phase counter
Serial.println("Button pressed Phase = 1"); // print message to serial monitor
} else if (phaseCount == 1) { // phase 2 case:
phaseStart = millis(); // store current time
digitalWrite(indicator, LOW); // extinguish indicator
Serial.println("Button pressed Phase = 2"); // print message to serial monitor
//if (phaseStart - millis() >= phaseDelay) {// WHEN TIMER EXPIRES (WILL NEED TO BE UP TO A MINUTE ON OTHER BUTTONS)
delay(phaseDelay); // loop() STILL NEEDS TO RUN WHILE THIS DELAY IS BEING EXECUTED
phaseCount = 0; // reset phase counter
Serial.println("Timeout Phase = 0"); // print message to serial monitor
//}
}
}
The part I am having trouble with (CAPS in comments) is allowing the loop() to run whilst the indicator is being held low before the timer expires.
I don't know if it's relavent or not, but the microcontroller is a Teensy 2.0.
Any suggestions or comments would be greatly appreciated.