Go Down

Topic: One button, press and press+hold analog input (Read 676 times) previous topic - next topic

Matt1995

You could wait for the release event to do anything. If the switch that was released had been held a short time, do one thing. If it had been held a long time, do something else. Nothing would happen on press, except for recording the time that the press started.
I believe I was looking at an "instructable" that did this. The button press didn't do anything but
set a timer, then when released did the event. How long it took from press to release was then mapped out
to 2 different events. Is this what you are describing? Knowing what i'm trying to do, does this seem the best approach? Again, Thank you.

PaulS

Quote
Is this what you are describing?
Yes.

Quote
Knowing what i'm trying to do, does this seem the best approach?
It seems like the only approach that will work.
The art of getting good answers lies in asking good questions.

Matt1995

Anyone have any code examples to try?...I just cant figure this out. About to ditch the one-button-two-function idea completely...frustration is setting in...

Robin2

Anyone have any code examples to try?...I just cant figure this out. About to ditch the one-button-two-function idea completely...frustration is setting in...
Post the latest version of your program - the complete program.

...R
Two or three hours spent thinking and reading documentation solves most programming problems.

Matt1995

This is the code version that was suggested by Morgan, and i made it work. This activates volume+ first, then hold button, then it does volume down. Press/release needs to be volume up, press/hold needs to be volume down without vol up first.  Thanks for the help.
Code: [Select]
void loop(void)
{
  int button, button2, pressed_button;
  static unsigned long buttonPressTime;
  static boolean buttonWasHeldDown = false;
  const unsigned long BUTTON_LONG_PRESS = 2000; //milliseconds - the duration of a 'long' press
  button = getButton();
  if (button != old_button)
  {
    delay(50);                   // debounce
    button2 = getButton();

    if (button == button2)
    {
      old_button = button;
      pressed_button = button;
      Serial.println(pressed_button);
      if (pressed_button == 1)
      {
        ble.print("AT+BleHidControlKey=");
        ble.println("VOLUME+");

      }

      if (pressed_button == 2)
      {
        ble.print("AT+BleHidControlKey=");
        ble.println("PLAYPAUSE");
      }
    }
    buttonWasHeldDown = false;
    buttonPressTime = millis(); //record when the button was initially pressed
  } else {
    //the button is not a new button - is it held down long enough?
    //Well, first we are only interested in one or two buttons that have the long-press function
    if(button == 1)
    {
      if(!buttonWasHeldDown)
      {
        //so far, we have not detected it as a held-down button
        if(millis() - buttonPressTime > BUTTON_LONG_PRESS)
        {
          buttonWasHeldDown = true; //set this so we don't do the held-down action more than once
          Serial.println("button was held down");
          ble.print("AT+HidBleControlKey=");
          ble.println("VOLUME-");
        }       
      }
    }
  }
}
     



/**************************************************************************/
/*!
    Checks for user input via the Steering Wheel Control wire
*/
/**************************************************************************/

int getButton()         
 {
 
  int i, z, sum ;
  int button;

  sum = 0;
  for (i=0; i < 4; i++)
  {
     sum += analogRead(A0);   
  }
  z = sum / 4;
  if (z > 650 && z < 690) button = 0;                                             
  else if (z > 840 && z < 860)  button = 1;                                         
  else if (z > 970 && z < 1010) button = 2;   
             
  else button = 0;
  return button;
 
 }

Matt1995

Ok..finally got something working. After you guys explaining to me about all this, I referenced this
code here

 http://www.instructables.com/id/Arduino-Dual-Function-Button-Long-PressShort-Press/?amp_page=true

Made some changes, and pretty much ditched the whole loop from my original code, and just used
the "getButton()" function as that works perfectly. Now I just have to figure out adding regular buttons.
Really appreciate all the help here. Don't know how you guys do this lol.
Code: [Select]
boolean LED1State = false;
boolean LED2State = false;

long buttonTimer = 0;
long longPressTime = 1000;

boolean buttonActive = false;
boolean longPressActive = false;
int button = 0 ;
int buttonVal = HIGH ;

void loop()

   button = getButton();
   delay(50);
   

  if (button == 1) {
       buttonVal == LOW ;

    if (buttonActive == false) {

      buttonActive = true;
      buttonTimer = millis();

    }

    if ((millis() - buttonTimer > longPressTime) && (longPressActive == false)) {

      longPressActive = true;
      LED1State = !LED1State;
     // Serial.println("button one event one");
        ble.print("AT+BleHidControlKey=");
        ble.println("VOLUME-");

    }

  } else {

    if (buttonActive == true) {

      if (longPressActive == true) {

        longPressActive = false;

      } else {

        LED2State = !LED2State;
       // Serial.println("button one event 2 ");
          ble.print("AT+BleHidControlKey=");
          ble.println("VOLUME+");

      }

      buttonActive = false;

    }

  }

}

cattledog

Here's some example code which determines a short or long press on an analogReading. It waits for a button release to determine the timing, but the long press could be placed on a time out instead of a release.

I made the code to check the reading into a function. My test environment was to switch 3.3v to an analogPin, with a default to ground when no press. You may find some of this useful.

Code: [Select]

#define noEvent    0
#define shortPress 1
#define longPress  2

const byte analogReadPin = A5;

void setup() {
  Serial.begin(115200);
  Serial.println("Long/Short analogRead Button Press");
}

void loop() {
  byte event = checkAnalogRead(analogReadPin);//checks for short or long press

  switch (event) {
    case shortPress:
      Serial.println("Run Shortpress Event Code ");
      //do short press code
      break;

    case longPress:
      Serial.println("Run longPress Event Code ");
      //do long press code
      break;
  }
}

byte checkAnalogRead(byte analogReadPin)
{
  const unsigned long shortTime = 1500;// if values are the same, all presses are either short or long
  const unsigned long longTime = 1500;

  static boolean startTimeOut = false;
  static int reading = 0;
  static int previousReading = 0;
  static unsigned long startOn = 0;
  static unsigned long buttonPressDuration = 0;

  const int targetReading = 685;//3.3v
  const byte tolerance = 50;

  #define lowBound  targetReading - tolerance
  #define highBound targetReading + tolerance

  byte result = noEvent;

  reading = analogRead(analogReadPin);
  previousReading = reading;
  delay(50);//debounce
  reading = analogRead(analogReadPin);

  //are the two reading the same and timeOut not started
  if (startTimeOut == false && ((reading > lowBound && reading < highBound) && (previousReading > lowBound && previousReading < highBound))) //pressed
  {
    Serial.println("pressed");
    startOn = millis();
    startTimeOut = true;
  }

  if (startTimeOut == true && (reading < lowBound || reading > highBound))//released
  {
    Serial.println("released");
    buttonPressDuration = millis() - startOn;
    startTimeOut = false;
  }

  if (buttonPressDuration >= longTime)
  {
    Serial.print("long press  ");
    Serial.println(buttonPressDuration);
    buttonPressDuration = 0;
    result = longPress;
  }

  if (buttonPressDuration > 0 && buttonPressDuration <= shortTime)
  {
    Serial.print("shortpress  ");
    Serial.println(buttonPressDuration);
    buttonPressDuration = 0;
    result = shortPress;
  }
  return result;
}




Matt1995

Thanks cattledog! I'm actually in the process now of trying to make 2 separate functions for press/release
and press/hold. What I ended up doing was modifying the code I found on that Instructable link for the one button-two-function part, then using the code I originally posted in the start of this thread for press/release. Both are all in the loop(), but I want to clean it up a bit and put those into separate
functions. The way it works, the 2 function code can time it so it reads the duration of the button press, then after the defined time, issue the command, and then also keeps track of the button state for press/hold functionality.  The button code for press/release only,  makes it that only one command is issued, even if you hold the button down. Problem I was having is that I was trying to merge other example code that uses button timers of "on" duration, but the code was ignoring the "on" time because of several statements in the code to determine button states. Hope that's not confusing lol. Appreciate the code!

Go Up