Feedback Needed - Multiple Button Presses to Different Actions

The sketch below is a part of a larger project, but I need to focus on this specific section first. My main requirement is to use a single button that can perform five different actions when pressed 1, 2, 3, or 4 times. Each additional press should trigger a different action. I have not come across this kind of functionality using an Arduino before, so I devised the following solution:

I connected one button to an Arduino, specifically to pin 2. Here's how it works:

  • When the button is pressed once, it sends a web post for data logging and instructs the server to send the logged data over email using a PHP script.
  • If the button is pressed twice, it initiates a web post every 15 seconds for one hour, continuously logging data during that time.
  • The same concept applies for 3 and 4 presses, each triggering their unique actions.

Now, I'm seeking feedback on potential alternative approaches to achieve the same functionality using only one button. Any suggestions or improvements are welcome. Sketch provided:
--- Note: this code does work ---

/*
This is part of a much larger project but i am 
shearing it because I could not find anything out there lik it
*/

#define buzzPin 10
const int buttonPin = 2;
int buttonPressCount = 0;

unsigned long lastResetTime = 0; // Variable to store the last time the button was pressed
unsigned long elapsedTime = 0;   // Variable to store the elapsed time since the last reset

void setup() {
  pinMode(buzzPin, OUTPUT);
  Serial.begin(9600);
  pinMode(buttonPin, INPUT);
}

void buzzer() {
  while (buttonPressCount > 0) {
    digitalWrite(buzzPin, HIGH);
    delay(50);
    digitalWrite(buzzPin, LOW);
    delay(400);
    buttonPressCount--;
  }
}

void loop() {

  if (digitalRead(buttonPin) == HIGH) {
    // Button has been pressed, update lastResetTime and increment buttonPressCount
    lastResetTime = millis();
    buttonPressCount++;

    // Provide audible indication using the buzzer
    digitalWrite(buzzPin, HIGH);
    delay(50);
    digitalWrite(buzzPin, LOW);
    delay(500);

    // Print buttonPressCount for debugging purposes
    Serial.print(buttonPressCount);
    Serial.println(" :buttonPressCount");
  }

  // Calculate the elapsed time since the last button press
  elapsedTime = millis() - lastResetTime;

  Serial.print("Elapsed Time (ms): ");
  Serial.println(elapsedTime);

  // Check if the button has been pressed multiple times and within the time window
  if (buttonPressCount >= 1 && buttonPressCount <= 7 && elapsedTime >= 1500 && elapsedTime <= 2000) {
    // Execute corresponding actions based on buttonPressCount
    Serial.print("Stop - Button Pressed - Option: ");
    Serial.println(buttonPressCount);

    switch (buttonPressCount) {
      case 1:
        Serial.println("Option 1 chosen");
        buzzer();
        // add more code here: run motor for sometime foward 
        break;
      case 2:
        Serial.println("Option 2 chosen");
        buzzer();
        // add more code here: run motor for sometime backward 
        break;
      case 3:
        Serial.println("Option 3 chosen");
        buzzer();
        // add more code here: flash light 20 times
        break;
      case 4:
        Serial.println("Option 4 chosen");
        buzzer();
         // add more code here: turn off a buzzer
        break;
      case 5:
        Serial.println("Option 5 chosen");
        buzzer();
         // add more code here: turn off a buzzer but not an led
        break;
      case 6:
        Serial.println("Option 6 chosen");
        buzzer();
        // add more code here: turn off an led but not a buzzer - you get the idea
        break;
      case 7:
        Serial.println("Option 7 chosen");
        buzzer();
        break;
      default:
        Serial.println("Invalid option");
        break;
    }
    digitalWrite(buzzPin, LOW);
    //buttonPressCount = 0; 
    /* not need due to "void buzzer()" 
    function Reset buttonPressCount after 
    button press and option selection*/
    
    Serial.println("Button Press Count reset");
    delay(6000);// This delay is only for helping see text on the serial monitor
  }
}

thanks.

What happens if you keep the button pressed for the duration? As far as I can see it will increment the counter.
What happens if you remove the buzzer code (the delays) in loop()? Note that buttons can bounce which will result in multiple button presses being detected.

@sterretje If you hold the button down, or press the button more than 7 times the count will go up for ever, if the court passes 7 then no action will happen and you should or will get a message "Invalid option" I have not accounted for passing 7 yet, so noting will happen right now.

bounceing is flex but adding a short time elapse before you can press again:

if (buttonPressCount >= 1 && buttonPressCount <= 7 && elapsedTime >= 1500 && elapsedTime <= 2000)

@brdavidosbnm Welcome to the forum!!
counting button presses, did something a few months back..
looked like this..

/*
  Single button, counting presses

  2.25.2023 ~q
*/
#define BTN_PIN 2


byte buttonPresses = 0;
unsigned long lastPress = 0;
int intervalDebounce = 50;
byte lastState = 1;// pulled up
bool timerStarted = false;
unsigned long timerStart = 0;
int intervalTimer = 5000;//5 seconds

void setup()
{
  pinMode(BTN_PIN, INPUT_PULLUP);// Set the switch pin as input with pull up resistor
  Serial.begin(9600);
  Serial.println("Ready");
}

void loop() {

  if (millis() - lastPress >= intervalDebounce) {
    lastPress = millis();
    byte state = digitalRead(BTN_PIN);
    if (state != lastState) {
      lastState = state;
      //start timer to count press..
      if (!timerStarted) {
        timerStarted = true;
        timerStart = millis();
      }
      if (state == HIGH) buttonPresses++;
    }
  }

  if (timerStarted) {
    if (millis() - timerStart >= intervalTimer) {
      Serial.print("Pressed:");
      Serial.println(buttonPresses);
      //do something with presses..


      //reset for next shot
      timerStarted = false;
      buttonPresses = 0;

    }
  }
}

maybe it helps..

delay is a bad word, try not to use it..

have fun.. ~q

1 Like

You need to check for a press and release. While you CAN do this with interrupts its better to use polling so you can use a time delay (millis) to eliminate contact bounce.
You need to separate the "activation" and "action" parts of the program so that it can detect say 6 button presses without acting on 1,2,3,4,5.

Perhaps because its not very robust. Suppose you allow a 6 second period for the button presses. What if the user is disabled and slow? or disturbed during the pressing? or loses count?

1 Like

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.