Combining millis with button sensing

I want to sense when an input goes high, and at that moment set counter = millis() and set output as high.

The output should go low once either of two conditions happens;

  1. The input goes low
  2. A set time period has passed (millis()-counter<=maxRun)

As you can see in the code, there is another stipulation that this series will only begin if the state change detection detects a change and the input is now high.

I think I am having trouble combining the two functions "If state change detects change and input high" and "While input is HIGH". I am new and would appreciate any help in the right direction.

I've scoured the button without delay examples and millis examples but I have not found any other code that requires the input to be continuously high and continuously keeps checking that.

My sketch;

// These constants won't change:
const int  buttonPin = 10;    // the pin that the pushbutton is attached to
const int maxRun = 2000; // the maximum time the LED will be lit
const int ledPin = 13;       // the pin that the LED is attached to


// These variables will change:
int buttonState = LOW;         // set current state of the button
int lastButtonState = LOW;     // set previous state of the button
unsigned long counter = 0; // the clock that will count how long since button press
int activate = 0; //random variable to transfer results from one function to another

void setup() {
  pinMode(buttonPin, INPUT);
  pinMode(ledPin, OUTPUT);
  digitalWrite(ledPin, LOW);
}


void loop() {
  buttonState = digitalRead(buttonPin); //Read the current state of the button

  // compare the buttonState to its previous state
  if ((buttonState != lastButtonState) && (buttonState == HIGH)) { // if the current state is HIGH then the button went from off to on:
    counter = millis();
  } else {
    digitalWrite(ledPin, LOW);
  }
  while ((buttonState == HIGH) && (millis() - counter <= maxRun)) {
    digitalWrite(ledPin, HIGH);
  }
  lastButtonState = buttonState;   // save the current state as the last state, for next time through the loop
}

consider the following pseudo code:

unsigned long time_stamp = 0;
const long INTERVAL = 5000; //5 seconds

void loop()
{
   buttonState=digitalRead(buttonPin);

   if (buttonState == HIGH) {
      if (time_stamp == 0) {
         time_stamp = millis();
      } else {

         //INTERVAL time has lapsed

      }
   }
   else {
   }

}

arduino_new:
consider the following pseudo code:

I dont think I follow on this one.

I added some more to your example to try to understand it but I think it would reset "time_stamp=millis()" every time it loops?

I'm also not sure about when to set "time_stamp=0" without it looping continuously equal to 0

I'm new to programming so it could be a simple solution staring me in the face and I dont see it yet.

void loop() {
  buttonState = digitalRead(buttonPin);

  if (buttonState == HIGH) {
    if (time_stamp == 0) {
      time_stamp = millis();
      digitalWrite(ledPin, HIGH);
    }
    else {
      digitalWrite(ledPin, LOW);
    }
  }
  else {
    digitalWrite(ledPin, LOW);
  }
}

arduino_new:
consider the following pseudo code:

No, do not consider useless (pseudo) code :slight_smile:

Consider this nice guide in the top of the forum instead!

if you use Bounce2 to do the heavy lifting:

#include <Bounce2.h>

const byte LedPin = 13;
const byte InputPin = 5;

const unsigned long MaxRunTime = 5000;

unsigned long startMillis;

Bounce input;


void setup(){
  pinMode(LedPin, OUTPUT);
  input.attach(InputPin, INPUT_PULLUP);
}

void loop(){
  input.update();
  
  if(input.rose()){
    startMillis = millis();
    digitalWrite(LedPin, HIGH);
  }
  else if(input.fell() || millis() - startMillis >= MaxRunTime){
    digitalWrite(LedPin, LOW);
  }
}

Only note, the write to low ma be executed multiple times. Not a problem for digitalWrite() but might be for other stuff you place there.

septillion:
if you use Bounce2 to do the heavy lifting:

Unfortunately I am not at the level yet to be using libraries (I think thats what "#include <Bounce2.h>" means) and the rest of the code is hard to follow for a beginner. I appreciate the response though and will look into it to help understand it. I believe I found the mistake on my original code and will post it below

Danois90:
Consider this nice guide in the top of the forum instead!

I have already looked at that before and thought I understood it, but it did help to go back and see it again.

I think I was just missing the callout to set "currentMillis = millis()" and "buttonState=digitalRead(buttonPin)" at the end of my "While" loop.

It appears to be working as expected after adding those. I'll add the code below for anyone seeing this in the future.

Now I just need to figure out how to swap the input button with an NPN proximity switch! I will do some research.

// These constants won't change:
const int  buttonPin = 10;    // the pin that the pushbutton is attached to
const int maxRun = 2000; // the maximum time the LED will be lit
const int ledPin = 13;       // the pin that the LED is attached to

// These variables will change:
int buttonState = LOW;         // set current state of the button
int lastButtonState = LOW;     // set previous state of the button
unsigned long timeStamp = 0; // the clock that will count how long since button press
unsigned long currentMillis;

// Setup the functions of the pins we will use:
void setup() {
  // initialize the button pin as an input:
  pinMode(buttonPin, INPUT);
  // initialize the LED as an output:
  pinMode(ledPin, OUTPUT);
  digitalWrite(ledPin, LOW);
}

void loop() {

  // read the pushbutton input pin:
  buttonState = digitalRead(buttonPin); //Read the current state of the button

  // compare the buttonState to its previous state
  if ((buttonState != lastButtonState) && (buttonState == HIGH)) { // if the current state is HIGH then the button went from off to on:
    delay(10); // delay a little to debounce
    timeStamp = millis();
    currentMillis = millis();

    while ((buttonState == HIGH) && (currentMillis - timeStamp <= maxRun)) {
      digitalWrite(ledPin, HIGH);

      currentMillis = millis();
      buttonState = digitalRead(buttonPin); //Read the current state of the button
    }
  }
  else {
    digitalWrite(ledPin, LOW);
  }

  lastButtonState = buttonState;   // save the current state as the last state, for next time through the loop
  delay(10); // delay a little to avoid bouncing
}

trebor46:
Unfortunately I am not at the level yet to be using libraries

That is absolute nonsense :wink: You already are! Serial, digitalWrite() and heck, even loop() is already from libraries. That's what makes Arduino easy. Only difference, this is a non-standard library. But just go to Sketch => Include Library => Manage Libraries and search for Bounce2, done!

Libraries are there to make life easy, not hard. Although some pore written libraries can be better left alone, Bounce2 is a library that makes life easy :slight_smile: