Adding button "long press" to switch case

Hi,

I have a code using a push button and switch case. When I push the button the code goes from case 0 to 1, then 2 and so on. At the end I have the "default" part of the switch case.

In my code I have 8 cases, and if I am at case 1 and I want to go all the way to "default", I have to pust the button many times. Is it possible to add a function that makes a long press of the button the switch case to jump all the way to "default" skipping case x-8?

It is possible, but depends on how you already wrote your code. Please provide it or provide only the part with the switch / case and the button definitions (incl. libraries), this will help us help you.

Basically, you can code something that detects a change of state of the button (from HIGH to LOW then from LOW to HIGH). You initiate a chronometer at the first change (HIGH to LOW, I suppose you declared it as INPUT_PULLUP), and stop it when you detect the second change. If the time difference between those 2 instants is longer than your threshold, go to your 8th case.

You have not shared your code (HINT) so we don't know what currently causes a change of state but there is no reason why you cannot cause a change of state using a long press.

Save the value of millis() as the start time when the button becomes pressed (not when it is pressed) then each time through loop() check whether the button is still pressed and if so whether the required long press period has elapsed. This can all go in a function called from any state or even loop() itself. Once the period has elapsed set the state to the required new one.

Hi, sorry for the late reply.
Here is my code:

//    V02.Q119  Hodelykt

const int UV = 7;
const int NL = 8;
const int X1A = 9;
const int X1B = 10;
const int X1C = 11;
const int LED13 = 13;
const int B20 = 6;
const int B40 = 5;
const int B60 = 4;
const int B80 = 3;
const int B99 = 2;
const int RED = A0;
const int GREEN = A1;
const int BLUE = A2;

const int button = A7;  //A7



int state = 0;
int old = 0;
int buttonPoll = 0;



void setup() {

  
  pinMode(UV, OUTPUT);
  pinMode(NL, OUTPUT);
  pinMode(X1A, OUTPUT);
  pinMode(X1B, OUTPUT);
  pinMode(X1C, OUTPUT);
  pinMode(LED13, OUTPUT);
  pinMode(B20, OUTPUT);
  pinMode(B40, OUTPUT);
  pinMode(B60, OUTPUT);
  pinMode(B80, OUTPUT);
  pinMode(B99, OUTPUT);
  pinMode(RED, OUTPUT);
  pinMode(GREEN, OUTPUT);
  pinMode(BLUE, OUTPUT);
  
  pinMode(button, INPUT);


  digitalWrite(UV,LOW);
  digitalWrite(LED13,LOW);
  digitalWrite(X1A,LOW);
  digitalWrite(X1B,LOW);
  digitalWrite(X1C,LOW);
  digitalWrite(B20,LOW);
  digitalWrite(B40,LOW);
  digitalWrite(B60,LOW);
  digitalWrite(B80,LOW);
  digitalWrite(B99,LOW);
  digitalWrite(RED,LOW);
  digitalWrite(GREEN,LOW);
  digitalWrite(BLUE,LOW);
  digitalWrite(NL, LOW);
  
 
}

void loop() {


  buttonPoll = analogRead(button) > 500 ? 1 : 0;     //For using A7 as button input
  if(buttonPoll == 1){
    delay(50);                                       //For debounce
   buttonPoll = analogRead(button) > 500 ? 1 : 0;
    if(buttonPoll == 0){
      state = old + 1;

    }}

  else{
  delay(100);
  }



  switch (state) {
    
    case 1:    //NL
      
  digitalWrite(UV,LOW);
  digitalWrite(LED13,LOW);
  digitalWrite(X1A,LOW);
  digitalWrite(X1B,LOW);
  digitalWrite(X1C,LOW);
  digitalWrite(B20,LOW);
  digitalWrite(B40,LOW);
  digitalWrite(B60,LOW);
  digitalWrite(B80,LOW);
  digitalWrite(B99,LOW);
  digitalWrite(RED,LOW);
  digitalWrite(GREEN,LOW);
  digitalWrite(BLUE,LOW);
  
  digitalWrite(NL, HIGH);
  old = state;
      break;
      
    case 2:    //25%
      
  digitalWrite(UV,LOW);
  digitalWrite(NL,LOW);
  digitalWrite(LED13,LOW);
  digitalWrite(X1B,LOW);
  digitalWrite(X1C,LOW);
  digitalWrite(B20,LOW);
  digitalWrite(B40,LOW);
  digitalWrite(B60,LOW);
  digitalWrite(B80,LOW);
  digitalWrite(B99,LOW);
  digitalWrite(RED,LOW);
  digitalWrite(GREEN,LOW);
  digitalWrite(BLUE,LOW);
  
  digitalWrite(X1A, HIGH);
  old = state;
      break;
      
    case 3:    //50%
      
  digitalWrite(UV,LOW);
  digitalWrite(NL,LOW);
  digitalWrite(LED13,LOW);
  digitalWrite(X1C,LOW);
  digitalWrite(B20,LOW);
  digitalWrite(B40,LOW);
  digitalWrite(B60,LOW);
  digitalWrite(B80,LOW);
  digitalWrite(B99,LOW);
  digitalWrite(RED,LOW);
  digitalWrite(GREEN,LOW);
  digitalWrite(BLUE,LOW);
  
  digitalWrite(X1A, HIGH);
  digitalWrite(X1B, HIGH);
  old = state;
      break;
      
    case 4:    //100%

  digitalWrite(UV,LOW);
  digitalWrite(NL,LOW);
  digitalWrite(LED13,LOW);
  digitalWrite(B20,LOW);
  digitalWrite(B40,LOW);
  digitalWrite(B60,LOW);
  digitalWrite(B80,LOW);
  digitalWrite(B99,LOW);
  digitalWrite(RED,LOW);
  digitalWrite(GREEN,LOW);
  digitalWrite(BLUE,LOW);
  
  digitalWrite(X1A, HIGH);
  digitalWrite(X1B, HIGH);
  digitalWrite(X1C, HIGH);
  old = state;
      break;
      
    case 5:    //UV
          
  digitalWrite(NL,LOW);
  digitalWrite(LED13,LOW);
  digitalWrite(X1A,LOW);
  digitalWrite(X1B,LOW);
  digitalWrite(X1C,LOW);
  digitalWrite(B20,LOW);
  digitalWrite(B40,LOW);
  digitalWrite(B60,LOW);
  digitalWrite(B80,LOW);
  digitalWrite(B99,LOW);
  digitalWrite(RED,LOW);
  digitalWrite(GREEN,LOW);
  digitalWrite(BLUE,LOW);
  
  digitalWrite(UV, HIGH);
  old = state;
      break;
      
    case 6:    //R
          
  digitalWrite(UV,LOW);
  digitalWrite(LED13,LOW);
  digitalWrite(X1A,LOW);
  digitalWrite(X1B,LOW);
  digitalWrite(X1C,LOW);
  digitalWrite(B20,LOW);
  digitalWrite(B40,LOW);
  digitalWrite(B60,LOW);
  digitalWrite(B80,LOW);
  digitalWrite(B99,LOW);
  digitalWrite(UV,LOW);
  digitalWrite(GREEN,LOW);
  digitalWrite(BLUE,LOW);
  
  digitalWrite(RED, HIGH);
  old = state;
      break;
      
    case 7:    //G
          
  digitalWrite(UV,LOW);
  digitalWrite(LED13,LOW);
  digitalWrite(X1A,LOW);
  digitalWrite(X1B,LOW);
  digitalWrite(X1C,LOW);
  digitalWrite(B20,LOW);
  digitalWrite(B40,LOW);
  digitalWrite(B60,LOW);
  digitalWrite(B80,LOW);
  digitalWrite(B99,LOW);
  digitalWrite(RED,LOW);
  digitalWrite(NL,LOW);
  digitalWrite(BLUE,LOW);
  
  digitalWrite(GREEN, HIGH);
  old = state;
      break;
      
    case 8:    //B
          
  digitalWrite(UV,LOW);
  digitalWrite(LED13,LOW);
  digitalWrite(X1A,LOW);
  digitalWrite(X1B,LOW);
  digitalWrite(X1C,LOW);
  digitalWrite(B20,LOW);
  digitalWrite(B40,LOW);
  digitalWrite(B60,LOW);
  digitalWrite(B80,LOW);
  digitalWrite(B99,LOW);
  digitalWrite(RED,LOW);
  digitalWrite(GREEN,LOW);
  digitalWrite(NL,LOW);
  
  digitalWrite(BLUE, HIGH);
  old = state;
      break;

    default:   //

  digitalWrite(UV,LOW);
  digitalWrite(NL,LOW);
  digitalWrite(X1A,LOW);
  digitalWrite(X1B,LOW);
  digitalWrite(X1C,LOW);
  digitalWrite(B20,LOW);
  digitalWrite(B40,LOW);
  digitalWrite(B60,LOW);
  digitalWrite(B80,LOW);
  digitalWrite(B99,LOW);
  digitalWrite(RED,LOW);
  digitalWrite(GREEN,LOW);
  digitalWrite(BLUE,LOW);
  
  digitalWrite(LED13, HIGH);
  old = 0;
    break;



  }
  delay(1);        // delay in between reads for stability

}

Any tips on how to implement your ideas in the code?

Later I also want to add battery monitoring (using the internal 1.1v referance) and to add a function that makes the code jump to case 1 if the battery level is getting very low

Detect a long press and set state to e.g. 999 which will be handled by the default case.

Any ideas on how I could implement your ideas in my code?

The code in this link illustrates different button presses - it may help.

...R

Robin2:
The code in this link illustrates different button presses - it may help.

...R

Thank you. Been reding this thread a few times, but its a bit too heavy for my understanding.
Do you know of a simpler code? All I need is my code to work like posted above, but to add a long press that makes the code jump from case X to case 0.

Mabye something like:

Short press:
...
if(buttonPoll == 0){
state = old + 1;

Long press:
...
(some code)
state = 0;

HansiFansi:
Thank you. Been reding this thread a few times, but its a bit too heavy for my understanding.

I find a lot of that stuff begins to become clear after the 14th reading. :slight_smile:

If you want to do what that code does then I doubt if there is a significantly easier way.

...R

How about:

  buttonPoll = analogRead(button) > 500 ? 1 : 0;     //For using A7 as button input
  if(buttonPoll == 1){
    delay(50);                                       //For debounce
    unsigned long chrono = millis();
   buttonPoll = analogRead(button) > 500 ? 1 : 0;
    if(buttonPoll == 0){
      state = old + 1;
      if (millis()-chrono > 1000) state = 0; // Long press is over 1 second

    }}

  else{

Give it a try, it may be the beginning of something...

lesept:
How about:

  buttonPoll = analogRead(button) > 500 ? 1 : 0;     //For using A7 as button input

if(buttonPoll == 1){
   delay(50);                                       //For debounce
   unsigned long chrono = millis();
  buttonPoll = analogRead(button) > 500 ? 1 : 0;
   if(buttonPoll == 0){
     state = old + 1;
     if (millis()-chrono > 1000) state = 0; // Long press is over 1 second

}}

else{



Give it a try, it may be the beginning of something...

I will try this after work today. Thanks

Robin2:
I find a lot of that stuff begins to become clear after the 14th reading. :slight_smile:

If you want to do what that code does then I doubt if there is a significantly easier way.

…R

Haha, good point. Hopefully lesept´s code works. Will try that first

 buttonPoll = analogRead(button) > 500 ? 1 : 0;     //For using A7 as button input
  if(buttonPoll == 1){
    delay(50);                                                        //For debounce
    unsigned long chrono = millis();
   buttonPoll = analogRead(button) > 500 ? 1 : 0;
    if(buttonPoll == 0){
      if (millis()-chrono < 1000) state = old + 1;       //Short press under 1 second
      if (millis()-chrono > 1000) state = 0;                //Long press is over 1 second

    }}

  else{

Just to ask, could this be a better solution?

HansiFansi:
Just to ask, could this be a better solution?

What happens when you try it?

Experiment is usually the quickest way to get an answer. The Arduino system is great for learning-by-doing.

...R

Robin2:
What happens when you try it?

Experiment is usually the quickest way to get an answer. The Arduino system is great for learning-by-doing.

...R

I will try after work today. I agree, just thinking out loud here

It's basically the same.

 buttonPoll = analogRead(button) > 500 ? 1 : 0;     //For using A7 as button input
  if(buttonPoll == 1){
    delay(50);                                                        //For debounce
    unsigned long chrono = millis();
   buttonPoll = analogRead(button) > 500 ? 1 : 0;
    if(buttonPoll == 0){
      if (millis()-chrono < 1000) state = old + 1;       //Short press under 1 second
      if (millis()-chrono > 1000) state = 0;                //Long press is over 1 second

    }}

  else{

Tested this code now, but the circuit acts just like before. Both a short and a long press makes the code jump from case x to case x+1

HansiFansi:

 buttonPoll = analogRead(button) > 500 ? 1 : 0;     //For using A7 as button input

if(buttonPoll == 1){
    delay(50);                                                        //For debounce
    unsigned long chrono = millis();
  buttonPoll = analogRead(button) > 500 ? 1 : 0;
    if(buttonPoll == 0){
      if (millis()-chrono < 1000) state = old + 1;      //Short press under 1 second
      if (millis()-chrono > 1000) state = 0;                //Long press is over 1 second

}}

else{





Tested this code now, but the circuit acts just like before. Both a short and a long press makes the code jump from case x to case x+1

Could the solution be to add “else” infront of the second if sentence (else if)?
(I will test this later, but hoping to keep the discussion rolling until I get the code working)

How about:

 buttonPoll = analogRead(button) > 500 ? 1 : 0;  //For using A7 as button input
  if(buttonPoll == 1){
    delay(30);          //For debounce 30ms should be enough
    unsigned long chrono = millis();
    while (buttonPoll == 1) buttonPoll = analogRead(button) > 500 ? 1 : 0;
    if (millis()-chrono < 1000) state = old + 1;   //Short press under 1 second
    else state = 0;                                //Long press is over 1 second
  } else {

lesept:
How about:

 buttonPoll = analogRead(button) > 500 ? 1 : 0;  //For using A7 as button input

if(buttonPoll == 1){
    delay(30);          //For debounce 30ms should be enough
    unsigned long chrono = millis();
    while (buttonPoll == 1) buttonPoll = analogRead(button) > 500 ? 1 : 0;
    if (millis()-chrono < 1000) state = old + 1;  //Short press under 1 second
    else state = 0;                                //Long press is over 1 second
  } else {

That worked! Thank you so much for you help!

Would it be possible to add a third button press function?
Something like “if button is pressed for 10 seconds, do this”