Multi Function Button

im trying to setup a multi function button. for now im trying to get the short/long press function to work. im not sure but i think the way i have this code below is wrong, when i press the button i think it runs all of the if statements or maybe just the last one?. what am i doing wrong here?

  }
const unsigned long shortPress = 2000;
const unsigned long  longPress = 5000; 
const unsigned long  UltraPress = 8000;
const unsigned long  CalibratePress = 15000;

typedef struct Buttons {
  const byte pin = A5; 
  const int debounce = 10;

  unsigned long counter = 0;
  bool prevState = NOT_PRESSED;
  bool currentState;
} Button;
Button button;

button.currentState = digitalRead(button.pin);

  if (button.currentState != button.prevState) {
    button.currentState = digitalRead(button.pin);
    if (button.currentState == PRESSED) {
      button.counter = millis();
    }

    if (button.currentState == NOT_PRESSED) {

      unsigned long currentMillis = millis();
      if ((currentMillis - button.counter >= shortPress) && !(currentMillis - button.counter >= longPress) ) {

        handleShortPress();
      }
      if ((currentMillis - button.counter >= longPress) && !(currentMillis - button.counter >= UltraPress))   {

        handleLongPress();
      }
      if ((currentMillis - button.counter >= UltraPress) && !(currentMillis - button.counter >= CalibratePress)) {

        handleUltraPress();
      }
      if ((currentMillis - button.counter >= CalibratePress))
        calibratewait = millis();
      Calibratepress();

    }

Did you forget to post some of your code ?

You started building the button switch as a class, why not finish the job?

Have you considered using Switch Manager by Nick Gammon.

 /*SwitchManager skeleton 
 
 This sketch is to introduce new people to the SwitchManager library written by Nick Gammon
 
 The library handles switch de-bouncing and provides timing and state change information in your sketch.
 The SwitchManager.h file should be placed in your libraries folder, i.e.
 C:\Users\YourName\Documents\Arduino\libraries\SwitchManager\SwitchManager.h
 You can download the library at:
 http://gammon.com.au/Arduino/SwitchManager.zip    Thank you Nick!
 
 In this example we have 2 normally open (N.O.) switches connected to the Arduino - increment and decrement.
 The increment switch will also be used as a "Reset" switch if pressed for more than two seconds.
 The two switches are connected between GND (0 volts) and an Arduino input pin.
 The library enables pull-up resistors for your switch inputs.
 Pushing a switch makes its pin LOW. Releasing a switch makes its pin HIGH.
 
 The SwitchManager library provides 10ms de-bounce for switches. 
 i.e. enum { debounceTime = 10, noSwitch = -1 };
 If you need more time, edit the SwitchManager.h file
 i.e. enum { debounceTime = 50, noSwitch = -1 }; //here it is changed to 50ms
 */

#include <SwitchManager.h>             
//object instantiations
SwitchManager myIncSwitch;
SwitchManager myDecSwitch;

unsigned long currentMillis;
unsigned long heartBeatMillis;
unsigned long heartFlashRate  = 500UL; // time the led will change state       
unsigned long incShortPress   = 500UL; // 1/2 second
unsigned long incLongPress    = 2000UL;// 2 seconds 
unsigned long decShortPress   = 500UL; // 1/2 second

const byte heartBeatLED       = 13;
const byte incSwitch          = 4; //increment switch is on Arduino pin 4
const byte decSwitch          = 5; //decrement switch is on Arduino pin 5

int myCounter;

//======================================================================

void setup()
{
  Serial.begin(9600);

  //gives a visual indication if the sketch is blocking
  pinMode(heartBeatLED, OUTPUT);  

  myIncSwitch.begin (incSwitch, handleSwitchPresses); 
  myDecSwitch.begin (decSwitch, handleSwitchPresses);
  //the handleSwitchPresses() function is called when a switch changes state

} //                   E N D  O F  s e t u p ( )

//======================================================================

void loop()
{
  //leave this line of code at the top of loop()
  currentMillis = millis();

  //***************************
  //some code to see if the sketch is blocking
  if (CheckTime(heartBeatMillis, heartFlashRate, true))
  {
    //toggle the heartBeatLED
    digitalWrite(heartBeatLED,!digitalRead(heartBeatLED));
  }

  //***************************
  //check to see what's happening with the switches
  //"Do not use delay()s" in your sketch as it will make switch changes unresponsive 
  //Use BlinkWithoutDelay (BWD) techniques instead.
  myIncSwitch.check ();  
  myDecSwitch.check (); 

  //***************************
  //put other non-blocking stuff here


} //                      E N D  O F  l o o p ( )


//======================================================================
//                          F U N C T I O N S
//======================================================================


//                        C h e c k T i m e ( ) 
//**********************************************************************
//Delay time expired function
//parameters:
//lastMillis = time we started
//wait = delay in ms
//restart = do we start again  

boolean CheckTime(unsigned long  & lastMillis, unsigned long wait, boolean restart) 
{
  //has time expired for this task?
  if (currentMillis - lastMillis >= wait) 
  {
    //should this start again? 
    if(restart)
    {
      //yes, get ready for the next iteration
      lastMillis += wait;  
    }
    return true;
  }
  return false;

} //                 E N D   o f   C h e c k T i m e ( )


//                h a n d l e S w i t c h P r e s s e s( )
//**********************************************************************

void handleSwitchPresses(const byte newState, const unsigned long interval, const byte whichPin)
{
  //  You get here "ONLY" if there has been a change in a switches state.

  //When a switch has changed state, SwitchManager passes this function 3 arguments:
  //"newState" this will be HIGH or LOW. This is the state the switch is in now.
  //"interval" the number of milliseconds the switch stayed in the previous state
  //"whichPin" is the switch pin that we are examining  

  switch (whichPin)
  {
    //***************************
    //are we dealing with this switch?
  case incSwitch: 

    //has this switch gone from LOW to HIGH (gone from pressed to not pressed)
    //this happens with normally open switches wired as mentioned at the top of this sketch
    if (newState == HIGH)
    {
      //The incSwitch was just released
      //was this a short press followed by a switch release
      if(interval <= incShortPress) 
      {
        Serial.print("My counter value is = ");
        myCounter++;
        if(myCounter > 1000)
        {
          //limit the counter to a maximum of 1000
          myCounter = 1000; 
        }
        Serial.println(myCounter);
      }

      //was this a long press followed by a switch release
      else if(interval >= incLongPress) 
        //we could also have an upper limit
        //if incLongMillis was 2000UL; we could then have a window between 2-3 seconds
        //else if(interval >= incLongMillis && interval <= incLongMillis + 1000UL) 
      {
        //this could be used to change states in a StateMachine
        //in this example however, we will just reset myCounter
        myCounter = 0;
        Serial.print("My counter value is = ");
        Serial.println(myCounter);
      }

    }

    //if the switch is a normally closed (N.C.) and opens on a press this section would be used
    //the switch must have gone from HIGH to LOW 
    else 
    {
      Serial.println("The incSwitch was just pushed");
    } 

    break; //End of case incSwitch

    //*************************** 
    //are we dealing with this switch?
  case decSwitch: 

    //has this switch gone from LOW to HIGH (gone from pressed to not pressed)
    //this happens with normally open switches wired as mentioned at the top of this sketch
    if (newState == HIGH)
    {
      //The decSwitch was just released
      //was this a short press followed by a switch release
      if(interval <= decShortPress) 
      {
        Serial.print("My counter value is = ");
        myCounter--;
        if(myCounter < 0) 
        {
          //don't go below zero
          myCounter = 0;
        }
        Serial.println(myCounter);
      }

    }

    //if the switch is a normally closed (N.C.) and opens on a press this section would be used
    //the switch must have gone from HIGH to LOW
    else 
    {
      Serial.println("The decSwitch switch was just pushed");
    } 

    break; //End of case decSwitch

    //*************************** 
    //Put default stuff here
    //default:
    //break; //END of default

  } //End switch (whichPin)

} //      E n d   o f   h a n d l e S w i t c h P r e s s e s ( )


//======================================================================
//                      E N D  O F  C O D E
//======================================================================

yea i just realized i forget the opening and closing brackets of that last if statement. it seems like there is a lot of code involved in making a button detect short/long presses AND double/triple fast presses

notsolowki:
yea i just realized i forget the opening and closing brackets of that last if statement. it seems like there is a lot of code involved in making a button detect short/long presses AND double/triple fast presses

Here is another that I wrote which instead uses callback functions (which are set in the constructor).

test sketch

#include "MultiPress.h"

#define LEDPIN 13
#define BUTTON_A 2
#define BUTTON_B 3

void A_ButtonActions(void);  // Callback function definitions are required...
void B_ButtonActions(const int value);

MultiPress pushButtonSwitches[]= {
  {BUTTON_A, 100, A_ButtonActions},  // pin, interval, callback-on-pressed
  {BUTTON_B, 500, B_ButtonActions, true},
};

void setup()
{
  Serial.begin(9600);
  pinMode(LEDPIN, OUTPUT);
  Serial.println(MultiPress::getCount());
  MultiPress::beginAll();
  MultiPress::setDebounceAll(50);
}

void loop()
{
  MultiPress::update();
}

void A_ButtonActions(void)  // simple example of registering "Pressed"
{
  digitalWrite(LEDPIN, !digitalRead(LEDPIN));
}

void B_ButtonActions(const int value)  // example of registering Multi-Presses
{
  Serial.print(F("Button B:\t"));
  switch(value)
  {
    case -1:
      Serial.println(F("Long Press"));
      break;
    case 1:
      Serial.println(F("One Press"));
      break;
    case 2:
      Serial.println(F("Two Presses"));
      break;
    case 3:
      Serial.println(F("Three Presses")); // can do more!
      break;
    default:
      Serial.println(F("Whole Lotta Presses"));
      break;
  }
}

header:

#ifndef MULTIPRESS_H
#define MULTIPRESS_H

#include "Arduino.h"

#define MAX_BUTTON_INSTANCES 8
#define DEFAULT_DEBOUNCE_MILLISECONDS 75

class MultiPress{
  using funcPtr = void(*)(void);
  using returnFuncPtr = void(*)(const int value);
  public:
    MultiPress(int _pin, uint32_t _pressInterval, returnFuncPtr returnCallback, bool repeat = false);
    MultiPress(int _pin, uint32_t _pressInterval, funcPtr _callBack);
    bool begin();
    int setDebounce(uint8_t dbounce);
    static void setDebounceAll(uint8_t dbounce);
    int8_t pressed();
    static void update(void);
    static bool beginAll();
    static int getCount();
  private:
//    enum {
//      NOT_PRESSED,
//      PRESSED,
//    } switchState;
    bool repeatHold;
    byte pressCount;
    byte lastState;
    byte pin;
    uint32_t lastMillis;
    uint8_t debouncePeriod;
    uint16_t pressInterval;
    returnFuncPtr returnCallback;
    funcPtr callBack;
    static uint8_t instanceCount;
    static MultiPress* instances[MAX_BUTTON_INSTANCES];
};

#endif

implementation:

#include "MultiPress.h"

MultiPress* MultiPress::instances[MAX_BUTTON_INSTANCES];
uint8_t MultiPress::instanceCount = 0;

MultiPress::MultiPress(int _pin, uint32_t _pressInterval, returnFuncPtr _callback, bool repeat) : pin(_pin), pressInterval(_pressInterval), returnCallback(_callback), repeatHold(repeat){
  debouncePeriod = DEFAULT_DEBOUNCE_MILLISECONDS;
  instances[instanceCount] = this;
  instanceCount++;
}

MultiPress::MultiPress(int _pin, uint32_t _pressInterval, funcPtr _callBack)
{
  callBack = _callBack;
  pin = _pin;
  debouncePeriod = DEFAULT_DEBOUNCE_MILLISECONDS;
  pressInterval = _pressInterval;
  instances[instanceCount] = this;
  instanceCount++;
}

bool MultiPress::begin()
{
  pinMode(pin, INPUT_PULLUP);
  lastState = HIGH;
  Serial.println(pin);
  return true;
}

bool MultiPress::beginAll()
{
  for (size_t button = 0; button < instanceCount; button++)
  {
    instances[button]->begin();
  }
  return true;
}

void MultiPress::update(void)
{
  for (size_t button = 0; button < instanceCount; button++)
  {
    int8_t pressed = instances[button]->pressed();
    if(pressed)
    {
      if(instances[button]->returnCallback)
      {
        instances[button]->returnCallback(pressed);
      }
      else if(instances[button]->callBack)
      {
        instances[button]->callBack();
      }
    }
  }
}

int8_t MultiPress::pressed()
{
  byte nowState = digitalRead(pin);
  if(nowState != lastState)
  {
    //Serial.println(F("CHANGED STATE"));
    if(millis() - lastMillis < debouncePeriod) return 0;
    if(nowState == LOW)
    {
      lastMillis = millis();
      pressCount++;
    }
    else
    {
      if (millis() - lastMillis > pressInterval) // a long press
      {
        lastState = nowState;
        pressCount = 0;
        return -1;
      }
    }
  }
  if(pressCount != 0)
  {
    if(millis() - lastMillis > pressInterval and nowState == HIGH)
    {
      int presses = pressCount;
      pressCount = 0;
      return presses;
    }
  }
  lastState = nowState;
  return 0;
}

int MultiPress::setDebounce(uint8_t dbounce)
{
  debouncePeriod = dbounce;
  return debouncePeriod;
}

void MultiPress::setDebounceAll(uint8_t dbounce)
{
  for (size_t button = 0; button < instanceCount; button++)
  {
    instances[button]->setDebounce(dbounce);
  }
}

int MultiPress::getCount()
{
  return instanceCount;
}