How can I Hold a button state for 500ms, regardless of actual input

I am having trouble programming a "button-state" (regardless of time pressed) to last for 500ms.

What I would like is to have any input for the button too last for 500ms, regardless of actual "button-state". So, if you press the button, it will stay for 500ms- no longer, no less.

int button = 3;
int unsigned long currentMillis = millis();

unsigned long buttonPress;
unsigned long shotRelease = 500;   //adjusts timing of jumpshot animation in milliseconds
unsigned long shotStart = 200;
bool buttonState = false;

void setup() {
     Serial.begin(9600);
     pinMode(button, OUTPUT);
}

void loop() {
    int sensorValue = analogRead(button);
    Serial.println(sensorValue);
  delay(1);
    
    int buttonState = false;
    
    if (analogRead(button) == 0 && (buttonState == false)) {
      buttonPress = currentMillis;
      buttonState = true;
    }
    
    if ((buttonState == true) && shotStart + buttonPress); {
    analogWrite(button, 0);
    Serial.println("HOLD");
    }
    
    if (analogRead(button) == 0 && (buttonState == true && shotRelease + buttonPress)) {
      analogWrite(button, !0);
      Serial.println("Green");
      delay(1000);
      buttonState = false;
    }
   
    
}

Once you have an input, save it. Don't reread the button or change the saved value for 500 ms.

Why are you using analogRead() for a button? Most people use digitalRead().

bc I am a rookie, this is my first time going at it.

  • changing from analogRead() to digitalRead().

You can save the input or save the changed value for 500ms :astonished: ,

Teach me this code wizard.

okay I did this and it worked in the serial monitor, I am going to test on my equipment now. Only issue is, that If I physically keep the button it will loop() the input in 200ms intervals. Thats lame.

I wish it would stop and wait for a false button before starting the loop() again.

int button = 3;
int unsigned long currentMillis = millis();

unsigned long buttonPress;
//unsigned long shotRelease = 500;   //adjusts timing in milliseconds
//unsigned long shotStart = 200;
bool buttonState = false;

void setup() {
     Serial.begin(9600);
     pinMode(button, INPUT);
}

void loop() {
    int sensorValue = buttonState;
    Serial.println(sensorValue);
  delay(10);
    
    while (analogRead(button) > 0) {
      buttonState = false;
      Serial.println("n");
    }
    
    while (analogRead(button) <= 2) {
      buttonState = true;
      Serial.println("y");
    }
    
    if (buttonState == true) {
      buttonPress = currentMillis;
      analogWrite(button, 0);
      Serial.println("green");
      delay(200);
    }
   
}

Finding your wording difficult.

Just tell use what you are trying to do.

Thanks for using code tags!

Looks like you know about millis() therefore you are not really a brand new noob :wink:

Using ‘while’ can result in blocking code, suggest you avoid it unless there is a good reason to use it.

An example covering timing and switch monitor for you to review:

#define OFF LOW
#define ON  HIGH

unsigned long ledOnMillis;
const unsigned long onTime = 5000;

boolean ledOnFlag          = false;

const byte redLED          = 13;
const byte onSwitch        = 2;
const byte auxOnSwitch     = 3;
const byte auxOffSwitch    = 4;

byte lastOnSwitchState;


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

  pinMode(redLED, OUTPUT);
  digitalWrite(redLED, OFF);

  //switch wired so a press give a LOW
  pinMode(onSwitch, INPUT_PULLUP);
  //initialize the last State variable
  lastOnSwitchState = digitalRead(onSwitch);

  pinMode(auxOnSwitch, INPUT_PULLUP);
  pinMode(auxOffSwitch, INPUT_PULLUP);

} //END of setup()


//*********************************************************************************
void loop()
{
  //**************************************
  byte currentState = digitalRead(onSwitch);

  //when timing is disabled, has the ON switch changed state?
  if (ledOnFlag == false && lastOnSwitchState != currentState)
  {
    //update to the new state
    lastOnSwitchState = currentState;

    //did the switch just get pressed i.e. LOW?
    if (currentState == LOW)
    {
      //turn the red LED ON
      digitalWrite(redLED, ON);
      Serial.println("Turn LED ON");

      //the time when the red LED went ON
      ledOnMillis = millis();

      //enable timing
      ledOnFlag = true;

    }

    //switch must have gone HIGH
    else
    {
      //nothing to do here
    }

  } //END of    if (ledOnFlag == false && lastOnSwitchState != currentState)

  //**************************************
  //if timing is enabled, has the timing interval expired?
  if (ledOnFlag == true && millis() - ledOnMillis >= onTime)
  {
    //turn the red LED OFF 5 seconds after it went ON
    digitalWrite(redLED, OFF);
    Serial.println("Turn LED OFF");

    //disable timing
    ledOnFlag = false;    //  <------<<<<<

    //maybe do some other stuff

  }

  //**************************************
  //when the auxiliary on switch is pressed, turn ON the red LED
  if (digitalRead(auxOnSwitch) == LOW)
  {
    //turn the red LED ON
    digitalWrite(redLED, ON);
    Serial.println("Turn LED ON");
  }

  //**************************************
  //when the auxiliary off switch is pressed, turn OFF the red LED
  if (digitalRead(auxOffSwitch) == LOW)
  {
    //turn the red LED Off
    digitalWrite(redLED, OFF);
    Serial.println("Turn LED OFF");

    //disable timing
    ledOnFlag = false;
  }


} //END of loop()

//*********************************************************************************

Agreed, delays are not cool. Take a look at the Blink Without Delay and Arduino State Change examples.

Layman terms:

I have a remote that is controlled by one button. When that by is pressed I would like the action to take place for 500ms, regardless of how long the button is pressed. Then the action would stop, reset and wait for the next button press.

In this case water a plant for 500ms or 0.5s. Holding button longer would flood the plant, tapping the button wouldn't give the plant enough water...

Is this an IR hand held remote or a simple push button switch?
If it is an IR remote, give us a link to the remote?

"In this case water a plant for 500ms or 0.5s. "
How much water comes out in 1/2 second?

When you looked at the sample code offered in post #4, did you understand how the switch was handled and how you can make a timer?

If not, what did you not understand?

I would like the action to take place for 500ms

Study the Blink Without Delay example.

Suppose the button is pressed for 1 minute, then the plant is watered for only 500ms. That I understand.
But what if the button is pressed multiple times very quickly while the plant is being watered ? Do you want the 500ms to have ended and the button to be released before a new press is accepted ?

@larryd, your example is how it should be done of course, but can you do "if ( !ledOnFlag && lastOnSwitchState..." and "if ( ledOnFlag && millis..." ?

Suggest new people not use short cuts when starting out.

Typing out the complete syntax helps new people in documenting their code.

TIMINGflag == true and TIMINGflag== false is unambiguous

Better still, #define ENABLED true #define DISABLED false

TIMINGflag == ENABLED and TIMINGflag== DISABLED

Koepel:
Suppose the button is pressed for 1 minute, then the plant is watered for only 500ms. That I understand.
But what if the button is pressed multiple times very quickly while the plant is being watered ? Do you want the 500ms to have ended and the button to be released before a new press is accepted ?

@larryd, your example is how it should be done of course, but can you do "if ( !ledOnFlag && lastOnSwitchState..." and "if ( ledOnFlag && millis..." ?

Great question. Yes I would want the 500ms to have ended, and the button to be released before a new press is accepted.

You can use my one shot timer: Fun_with_millis/millis_single_delay.ino at master · Koepel/Fun_with_millis · GitHub.
Then add the StateChangeDetection to it: https://www.arduino.cc/en/Tutorial/StateChangeDetection.
And add an extra if-statement to only start the timer-with-millis when the button is pressed and timer-with-millis is not running.
The result would be the sketch that larryd already gave :wink:

@EugeneBatiste
If you want help, you should answer the questions put to you.
When you don't answer us, we have no way of knowing where you are having problems.

Do you follow what is happening here?

//Version 1.01

//***********************************************************************
#define PUSHED    LOW
#define NotPUSHED HIGH

#define PUMPon    HIGH
#define PUMPoff   LOW

#define ENABLED   true
#define DISABLED  false

//***********************************************************************
const byte button     = 2;
const byte waterPump  = 3;

byte lastButtonState;

bool  timingFlag      = DISABLED;

unsigned long lastMillis;
unsigned long timingMillis;
const unsigned long timingInterval = 5000;  // 5 second

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

  pinMode(waterPump, OUTPUT);
  digitalWrite(waterPump, PUMPoff);

  pinMode(button, INPUT_PULLUP);
  lastButtonState = digitalRead(button);

} //END of setup()


//***********************************************************************
void loop()
{
  //*****************************
  //time to check the switches?
  if (millis() - lastMillis > 50)
  {
    //restart timer
    lastMillis = millis();

    checkSwitches();
    
  }

  //*****************************
  //when the timer is enabled, has the interval expired?
  if (timingFlag == ENABLED && millis() - timingMillis >= timingInterval)
  {
    //disable timing
    timingFlag = DISABLED;

    //stop watering
    digitalWrite(waterPump, PUMPoff);
    Serial.println("Water is OFF");
    
  }


  //*****************************
  //other none blocking code
  //*****************************

} //END of loop()


//***********************************************************************
void checkSwitches()
{
  byte currentState = 0;

  currentState = digitalRead(button);

  //***********************************************
  //has the switch changed state?
  if (lastButtonState != currentState)
  {
    //update to the new state
    lastButtonState = currentState;

    //*****************************
    //when timing is disabled, was the button pushed/closed?
    if (timingFlag == DISABLED && currentState == PUSHED)
    {
      //enable timing
      timingFlag = ENABLED;

      //reset the timer
      timingMillis = millis();

      //start watering
      digitalWrite(waterPump, PUMPon);
      Serial.println("Water is ON");
      
    }

  } //END of      if (lastButtonState != currentState))

  //***********************************************
  //future switches go here
  //***********************************************

} //END of checkSwitches()


//***********************************************************************

Yup makes sense, thanx. larryd.