press+hold with Milli help [SOLVED]

I am trying to add a second push button+hold but can't seem to get it rite !

the first press works, second push+hold for 800ms works and when it comes to the third Push+hold for 1500ms actually goes through the second and then starts the third action.

The second pulse(continousWeld) has break command that exists the loop and when existing it starts the third action also.

Here is what i intent to do
first press and release does one action
Press+hold for 800ms starts ContinousWeld
Press+hold for 2000 starts another action.

void loop()
{
  while (!zeroCrossingFlag) //As a ZC error detect, Set Ready light ON when zero cross detected else OFF.
  {
    digitalWrite(rdy, LOW);
  }
  digitalWrite(rdy, HIGH);

  // Start debug
  if (OldWeldStepValue != WeldStep())
  {
    WeldStepVal();
    OldWeldStepValue = WeldStep();
  }
  //end debug

  PulseSetLed();
  //myServo.write(SrvStartSet());
  //myServo.write(SrvEndSet());
  btnState = digitalRead(btn);
  if (btnState == LOW && buttonLast == HIGH && (millis() - btnUpTime) > long(debounce)) // Test for button pressed and store the down time
  {
    btnDnTime = millis();
  }
  if (btnState == HIGH && buttonLast == LOW && (millis() - btnDnTime) > long(debounce)) // Test for button release and store the up time
  {
    if (ignoreUp == false) Weld(100, 400);
    else ignoreUp = false;
    btnUpTime = millis();
  }
  if (btnState == LOW && (millis() - btnDnTime) > long(holdTime)) // check hold time
  {
    continousWeld();
    ignoreUp = true;
    btnUpTime = millis();
  }
  if (btnState == LOW && (millis() - btnDnTime) > long(holdTime2)) // Test for button held down for longer than the hold time
  {
    SetWeldHead();
    ignoreUp = false;
    btnDnTime = millis();
  }
  buttonLast = btnState;
  zeroCrossingFlag = false;
}

Please post ALL your code next time. See http://snippets-r-us.com/

Problem is, for the 2000ms long press to work correct you can only check if the 800ms pressed happened WHEN the button is released.

Yea i did try to post the whole code but it was way to long. Will use the snippets here on.

So how do i check if the 800ms was actually pressed. sorry, am trying to understand this milli() thing. been a little confusing to me.

Reply, then scroll down and use the Attach button if it's a longer program.

millis() just returns the number of mS since the last reset. Same as you looking at your watch to see how many hours:minutes:seconds since midnight. Note the time, note the time again, if enough time has elapsed do some action, like take the cookies out of the oven.

anishkgt:
Will use the snippets here on.

No don't! Then the help will stop right here.

Next time, instead of a snippet, make a new simpilied sketch with the same problem. So instead of calling complex other functions like continousWeld(), go back to the basics and just do a Serial.print() like Serial.println("Button held for 800ms")

anishkgt:
So how do i check if the 800ms was actually pressed. sorry, am trying to understand this milli() thing. been a little confusing to me.

The problem is not the fact you don't understand millis() :wink: It's the problem you don't understand logic and/or switches :wink:

You can only determine how low a button was long pressed (was it 800 < time < 2000, or was it time > 2000?) AFTER you RELEASED the button. While the button is still pressed you can't tell.

i was trying this bit of the original code

const byte servoPin = 5;
const byte btn = 6 ;
const byte bzr = 7;
const byte L8   = 9; // First LED
const byte L1   = A4; // Last LED
const byte ServoPot = A1; // Servo height preset
int SrvPotMap = 0 ;
int SrvPotValue = 0;
const int debounce = 10; // ms debounce period to prevent flickering when pressing or releasing the button
const int holdTime = 800; // ms hold period: how long to wait for press+hold event
const int holdTime2 = 1200;
int i = 0;
int counter1 = 0;
int counter2 = 0;
int btnState = LOW; // value read from button
int buttonLast = HIGH; // buffered value of the button's previous state
long btnDnTime; // time the button was pressed down
long btnUpTime; // time the button was released
boolean ignoreUp = false; // whether to ignore the button release because the click+hold was triggered

void setup()
{
  pinMode(L1, OUTPUT);
  pinMode(L8, OUTPUT);
  pinMode(bzr, OUTPUT);
  pinMode(btn, INPUT_PULLUP);
  pinMode(ServoPot, INPUT);
  pinMode(servoPin, OUTPUT);
  btnState = digitalRead(btn);
  Serial.begin(9600);
}

void SetWeldHead()
{
  while (counter2 < 10)
  {
    delay(1000);
    btnState = digitalRead(btn);
    if(btnState == LOW)
    {
      Serial.println("SetWeldHead_BREAK");
      break;
    }
  }
  Serial.println("End Adjust");
  counter2 = 0;
}

void ContinousWeld()
{
  while (counter1 < 6)
  {
    delay(1000);
    btnState = digitalRead(btn);
    if(btnState == LOW)
    {
      Serial.println("Continous Weld_BREAK");
      break;
    }
    delay(500);
    Serial.println("Continous Weld");
    counter1++;
  }
  counter1 = 0;
  Serial.println("End Weld");
}

void loop()
{
  btnState = digitalRead(btn);
  if (btnState == LOW && buttonLast == HIGH && (millis() - btnUpTime) > long(debounce)) // Test for button pressed and store the down time
  {
    btnDnTime = millis();
  }
  if (btnState == HIGH && buttonLast == LOW && (millis() - btnDnTime) > long(debounce)) // Test for button release and store the up time
  {
    if (ignoreUp == false) Serial.println("Single Weld");
    else ignoreUp = false;
    btnUpTime = millis();
  }
  if (btnState == LOW && (millis() - btnDnTime) > long(holdTime)) // Test for button held down for longer than the hold time
  {
    ContinousWeld();
    ignoreUp = true;
    btnDnTime = millis();
  }
  if (btnState == LOW && (millis() - btnDnTime) > long(holdTime2)) // Test for button held down for longer than the hold time
  {
    SetWeldHead();
    //delay(500);
    ignoreUp = true;
    btnDnTime = millis();
  }
  buttonLast = btnState;
}

The third action does not seem to be working here.

Here is what i intent to do
first press and release does one action
Press+hold for 800ms starts ContinousWeld
Press+hold for 2000 starts another action.

As septillion says, you need to determine the press duration before knowing it to short/long/longer

Here's some button code which does that, but puts a timeout on the longer press.

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

#define buttonPin 5
#define shortTime 800 //if equal longTime there is no unrecorded press
#define longTime 800
#define longerTime 2000

unsigned long buttonPressStartTimeStamp;
unsigned long buttonPressDuration;

boolean startTimeout = false;

byte previousButtonState = HIGH;
byte buttonState = HIGH;

void setup() {

  Serial.begin(115200);
  Serial.println("Long/Short Button Press");

  // Setup the button with an internal pull-up
  pinMode(buttonPin, INPUT_PULLUP);
}

void loop() {

  switch (checkButton())
  {
    case shortPress:
      Serial.println("short press");
      //do short press code
      break;

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

    case longerPress:
      Serial.println("longer press");
      //do longer press code
      break;
  }
}

byte checkButton()
{
  byte event = noEvent;
  buttonState = digitalRead(buttonPin);

  //button pressed
  if (buttonState == LOW && previousButtonState == HIGH)
  {
    delay(20);//blocking debounce routine
    buttonState = digitalRead(buttonPin);//read button again
    if (buttonState == LOW && previousButtonState == HIGH)
    {
      buttonPressStartTimeStamp = millis();
      startTimeout = true;
    }
  }

  //button released
  if (buttonState == HIGH && previousButtonState == LOW)
  {
    delay(20);//blocking debounce routine
    buttonState = digitalRead(buttonPin);//read button again
    if (buttonState == HIGH && previousButtonState == LOW)
    {
      buttonPressDuration = (millis() - buttonPressStartTimeStamp);
      startTimeout = false;//duration determined no timeout required
    }
  }

  if (buttonPressDuration > 0 && buttonPressDuration <= shortTime)
  {
    event = shortPress;
    buttonPressDuration = 0;
  }

  if (buttonPressDuration > longTime && buttonPressDuration <= longerTime)
  {
    event = longPress;
    buttonPressDuration = 0;
  }

  //button not released and still timing
  if (buttonState == LOW && startTimeout == true && (millis() - buttonPressStartTimeStamp) > longerTime)
  {
    event = longerPress;
    startTimeout = false;
    buttonPressDuration = 0;
  }

  previousButtonState = buttonState;
  return event;
}

Thanks CattleDog, but the short press does not seem to be working. I wish to have the event happen while the button is pressed and not released when it reaches the predefined time. Just like in my previous post. here the event happens only after release the button.

Instead of trying different pieces of code like mad, try to understand why it doesn't work.

You check to see if it's a long press(800<time<2000) or a longlong press (time>2000) while the button is still being pressed. But if the button now is checked, and press time is 900, how will it know the difference between you keeping the button pressed for another 3 seconds of you releasing it 1ms later. It can't look into the future.

Aka, you can only tell which of the two it was AFTER the button is released.

cattleDog's code worked. just clearing a doubt

int const shortTime = 800; //if equal longTime there is no unrecorded press

what does the comment mean and is it necessary that the short time and longerTime be same ?

what does the comment mean and is it necessary that the short time and longerTime be same ?

No, they do not have to be the same. If, for example the duration of a short press is <300ms, and the duration of a long press is between 800ms and 1500ms then any press with a duration between 300 and 800 will not register as either.