I'm having trouble making a pin go HIGH for "interval" amount of time where "interval" varies with single press, double press, long press and extra long press of a momentary button. Example: one press and the pin goes HIGH for 500ms, then LOW; double press and it goes HIGH for 1000ms and LOW again...
When I press the button once, it should be storing the time the button was clicked, then run the pin HIGH for 500ms, then LOW (without disrupting the rest of the program that is to be written).
case 1:
Serial.print("Button ");
Serial.print(btn);
switch (event) {
case 1:
Serial.println(" single press");
prevMill = millis();
triggerBoot(500);
break;
The pin remains HIGH as long as the difference between elapsed time and time of click isnt greater than "interval"
void triggerBoot (int interval) {
if (((long)millis() - prevMill) >= interval) {
// prevMill = millis(); //stores current value of millis()
digitalWrite(triggerPin, LOW);
prevMill = 0;
}
digitalWrite(triggerPin, HIGH);
}
There is something fundamentally wrong that i can't see due to my lack of experience.
We need to see your whole program. For instance, all timing variables should be unsigned longs, but are they ?
Personally I would give your variables more meaningful names, for instance startTime instead of prevMill. You would also be wise to have a single currentTime variable copied from millis() at the start of loop(). This gives you a consistent point of reference for all time calculations in the program
/* 4-Way Button: Click, Double-Click, Press+Hold, and Press+Long-Hold Test Sketch
Original Script (1 button for 4 different actions) By Jeff Saltzman
Oct. 13, 2009
Edited for multiple buttons By Mariano Arellano
Sept. 10, 2017
To keep a physical interface as simple as possible, this sketch demonstrates generating four output events from 5 push-buttons.
1) Click: rapid press and release
2) Double-Click: two clicks in quick succession
3) Press and Hold: holding the button down
4) Long Press and Hold: holding the button for a long time
*/
//button quantity (how many buttons you have)
#define BTNQTY 2 //put +1 here, because button 0 in array is null
// Button timing variables
long debounce = 20; // ms debounce period to prevent flickering when pressing or releasing the button
long DCgap = 250; // max ms between clicks for a double click event
long holdTime = 1000; // ms hold period: how long to wait for press+hold event
long longHoldTime = 3000; // ms long hold period: how long to wait for press+hold event
//Actual button pin numbers /0 none /button 1, 2, 3, 4, 5
const uint8_t btn[BTNQTY] = { 0, 2};
//Active Btn
int activebtn;
//Button States
boolean btnstate[BTNQTY];
boolean buttonLast[BTNQTY]; // buffered value of the button's previous state
boolean DCwaiting[BTNQTY]; // whether we're waiting for a double click (down)
boolean DConUp[BTNQTY]; // whether to register a double click on next release, or whether to wait and click
boolean singleOK[BTNQTY]; // whether it's OK to do a single click
long downTime[BTNQTY]; // time the button was pressed down
long upTime[BTNQTY]; // time the button was released
boolean ignoreUp[BTNQTY]; // whether to ignore the button release because the click+hold was triggered
boolean waitForUp[BTNQTY]; // when held, whether to wait for the up event
boolean holdEventPast[BTNQTY]; // whether or not the hold event happened already
boolean longHoldEventPast[BTNQTY];// whether or not the long hold event happened already
//=================================================
#define triggerPin 7
long prevMill = 0;
void setup() {
for (int i = 0; i < BTNQTY; i++) {
pinMode(btn[i], INPUT_PULLUP);
buttonLast[i] = HIGH; // buffered value of the button's previous state
DCwaiting[i] = false; // whether we're waiting for a double click (down)
DConUp[i] = false; // whether to register a double click on next release, or whether to wait and click
singleOK[i] = true; // whether it's OK to do a single click
downTime[i] = -1; // time the button was pressed down
upTime[i] = -1; // time the button was released
ignoreUp[i] = false; // whether to ignore the button release because the click+hold was triggered
waitForUp[i] = false; // when held, whether to wait for the up event
holdEventPast[i] = false; // whether or not the hold event happened already
longHoldEventPast[i] = false;// whether or not the long hold event happened already
}
Serial.begin(9600);
pinMode(triggerPin, OUTPUT); //pin7 Output
}
void loop() {
// Get active button event and act accordingly
checkButtons();
// Serial.print(prevMill);
// Serial.print(" ");
// Serial.println((long)millis() - prevMill);
}
void findMenu(int btn, int event) {
switch (btn) {
case 0:
break;
case 1:
Serial.print("Button ");
Serial.print(btn);
switch (event) {
case 1:
Serial.println(" single press");
prevMill = millis();
triggerBoot(5000);
break;
case 2:
Serial.println(" double press");
break;
case 3:
Serial.println(" hold press");
break;
case 4:
Serial.println(" long press");
break;
}
break;
// case 2:
// Serial.print("Button ");
// Serial.print(btn);
// switch(event){
// case 1:
// Serial.println(" single press");
// break;
// case 2:
// Serial.println(" double press");
// break;
// case 3:
// Serial.println(" hold press");
// break;
// case 4:
// Serial.println(" long press");
// break;
// }
// break;
// case 3:
// Serial.print("Button ");
// Serial.print(btn);
// switch(event){
// case 1:
// Serial.println(" single press");
// break;
// case 2:
// Serial.println(" double press");
// break;
// case 3:
// Serial.println(" hold press");
// break;
// case 4:
// Serial.println(" long press");
// break;
// }
// break;
// case 4:
// Serial.print("Button ");
// Serial.print(btn);
// switch(event){
// case 1:
// Serial.println(" single press");
// break;
// case 2:
// Serial.println(" double press");
// break;
// case 3:
// Serial.println(" hold press");
// break;
// case 4:
// Serial.println(" long press");
// break;
// }
// break;
// case 5:
// Serial.print("Button ");
// Serial.print(btn);
// switch(event){
// case 1:
// Serial.println(" single press");
// break;
// case 2:
// Serial.println(" double press");
// break;
// case 3:
// Serial.println(" hold press");
// break;
// case 4:
// Serial.println(" long press");
// break;
// }
// activebtn = 0;
// break;
}
}
void checkButtons() {
int event = 0;
for (int i = 1; i < BTNQTY; i++) {
btnstate[i] = digitalRead(btn[i]);
if (btnstate[i] == LOW) { //LOW means pressed (i know)
activebtn = i;
break;
}
}
// Button pressed down
if (btnstate[activebtn] == LOW && buttonLast[activebtn] == HIGH && (millis() - upTime[activebtn]) > debounce)
{
downTime[activebtn] = millis();
ignoreUp[activebtn] = false;
waitForUp[activebtn] = false;
singleOK[activebtn] = true;
holdEventPast[activebtn] = false;
longHoldEventPast[activebtn] = false;
if ((millis() - upTime[activebtn]) < DCgap && DConUp[activebtn] == false && DCwaiting[activebtn] == true) DConUp[activebtn] = true;
else DConUp[activebtn] = false;
DCwaiting[activebtn] = false;
}
// Button released
else if (btnstate[activebtn] == HIGH && buttonLast[activebtn] == LOW && (millis() - downTime[activebtn]) > debounce)
{
if (ignoreUp[activebtn] == false)
{
upTime[activebtn] = millis();
if (DConUp[activebtn] == false) DCwaiting[activebtn] = true;
else
{
event = 2;
DConUp[activebtn] = false;
DCwaiting[activebtn] = false;
singleOK[activebtn] = false;
}
}
}
// Test for normal click event: DCgap expired
if ( btnstate[activebtn] == HIGH && (millis() - upTime[activebtn]) >= DCgap && DCwaiting[activebtn] == true && DConUp[activebtn] == false && singleOK[activebtn] == true && event != 2)
{
event = 1;
DCwaiting[activebtn] = false;
}
// Test for hold
if (btnstate[activebtn] == LOW && (millis() - downTime[activebtn]) >= holdTime) {
// Trigger "normal" hold
if (holdEventPast[activebtn] == false)
{
event = 3;
waitForUp[activebtn] = true;
ignoreUp[activebtn] = true;
DConUp[activebtn] = false;
DCwaiting[activebtn] = false;
//downTime = millis();
holdEventPast[activebtn] = true;
}
// Trigger "long" hold
if ((millis() - downTime[activebtn]) >= longHoldTime)
{
if (longHoldEventPast[activebtn] == false)
{
event = 4;
longHoldEventPast[activebtn] = true;
}
}
}
buttonLast[activebtn] = btnstate[activebtn];
if ((activebtn != 0) && (event != 0)) {
findMenu(activebtn, event);
}
}
void triggerBoot (int interval) {
if (((long)millis() - prevMill) >= interval) {
// prevMill = millis(); //stores current value of millis()
digitalWrite(triggerPin, LOW);
prevMill = 0;
}
digitalWrite(triggerPin, HIGH);
}
It looks like your only calling triggerBoot() from within the code that detected a button press. If you want the pin to remain high for the full duration of your interval, you have to continue to call triggerBoot periodically afterward as well.
(also, you need an "else" clause in triggerBoot, or the code will set the pin high immediately after it sets it low.)
Thank you, it's working even though it's not pretty.
#define triggerPin 7
unsigned long previousMillis = 0; // will store last time button was pressed
unsigned long currentMillis;
boolean trigger = false;
int interval = 1000;