newbie still not getting millis to work with button

Hello!!

Ive found many other threads on millis but any that are similar to my situation are cut short or don't have a clear how they found the solution.. Ive tried for the past couple days and its to the point now Im going backwards with learning.... yes you read that correctly lol forgetting things I thought I knew..
My head literally hurts right now Ill try finding some code I had saved but I started to many to know where I left off at the moment.

What Im trying to do...

When the Button is pressed turn on a relay for 100ms then back off ... the button might be held for half a second or more but only need the relay to come on for 100ms

I have a understanding of State Change Detection. I have a code that does what I need but just cant get the millis function worked into it properly... any help or information where I can look/read more Id greatly appreciate it!!

What I have working without millis..

const int  buttonShift = 4;    // button pin
const int relay = 2;       // relay pin

int buttonState = 0;         // current state of the button
int lastButtonState = 0;     // previous state of the button

void setup() {
  pinMode(buttonShift, INPUT_PULLUP);
  pinMode(relay, OUTPUT);
}

void loop() {
  digitalWrite(relay, LOW);

  buttonState = digitalRead(buttonShift);

  if (buttonState != lastButtonState) {

    if (buttonState == LOW) {

      digitalWrite(relay, HIGH);
    } else {
      digitalWrite(relay, LOW);
    }
    delay(100);
  }


  if (buttonState != lastButtonState)
  { digitalWrite(relay, LOW);

    lastButtonState = buttonState;
  }
}

Basically:

Set up the timer so it's continually reset {timerNow = millis();} as long as a boolean timerFlag is false.

Use the switch-became-pressed state change to set timerFlag true to allow the timer to run.

Now, combine the flag and the timer status to control the relay - that is, if the flag is set *and * the timer hasn't run out, turn the relay on, else relay off.

When the timer reaches preset, set timerFlag back to false. Timer is again reset and the logic waits for the next button press.

Your code could be rewritten as below:

const int  buttonShift = 4;    // button pin
const int relay = 2;       // relay pin

int buttonState = 0;         // current state of the button
int lastButtonState = 0;     // previous state of the button

const unsigned long RELAY_ON_INTERVAL = 100; 
unsigned long previousMillis = 0;

void setup() {
  pinMode(buttonShift, INPUT_PULLUP);
  pinMode(relay, OUTPUT);
  digitalWrite(relay, LOW);
}

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

  if (buttonState != lastButtonState) {
    if (buttonState == LOW) {
      digitalWrite(relay, HIGH); // turn ON relay
      previousMillis = millis(); // save timestamp
    }

    lastButtonState = buttonState;
  }

  if (millis() - previousMillis >= RELAY_ON_INTERVAL) {
    digitalWrite(relay, LOW); // turn OFF relay after 100 milliseconds
  }
}

Compare this code with your code.

The above code uses timstamp instead of delay(). You can learn more about timstamp in BlinkWithoutDelay example

Besides, you SHOULD implement the deboucing function

The below code uses the button library with deboucing function

#include <ezButton.h>
const int  buttonShift = 4;    // button pin
const int relay = 2;       // relay pin
const unsigned long RELAY_ON_INTERVAL = 100; 
unsigned long previousMillis = 0;

ezButton button(buttonShift);

void setup() {
  button.setDebounceTime(50); // set debounce time to 50 milliseconds
  pinMode(relay, OUTPUT);
  digitalWrite(relay, LOW);
}

void loop() {
  button.loop(); // MUST call the loop() function first

  if(button.isPressed()) {
    digitalWrite(relay, HIGH); // turn ON relay
    previousMillis = millis(); // save timestamp
  }

  if (millis() - previousMillis >= RELAY_ON_INTERVAL) {
    digitalWrite(relay, LOW); // turn OFF relay after 100 milliseconds
  }
}

IoT_hobbyist:
Your code should could be rewrite as below

You seem a big fan of the word "should": there's usually more than one way to do things....

Thanks for the replies!

hobbyist I feel like I was so close with some of my attemps!

I know Ive wrote this very same code and just had it in the wrong area!!
I don't know why millis is giving me such a tough time understanding.. Think I might me to focused on my project.. Thanks I greatly appreciate it, Im going to try some other time based code so I can fully grasp the function..

if (millis() - previousMillis >= RELAY_ON_INTERVAL) {
digitalWrite(relay, LOW); // turn OFF relay after 100 milliseconds
}

I will study this button library

I try to use this forum as a last resort but I was really running out of ideas and just bumming my self out!
Thanks again!

12Stepper:
You seem a big fan of the word "should": there's usually more than one way to do things....

Thank you @12Stepper for correcting my grammar mistake.

@race2win, Good luck!

I'm going to try some other time based code so I can fully grasp the function..

if (millis() - previousMillis >= RELAY_ON_INTERVAL) {

digitalWrite(relay, LOW); // turn OFF relay after 100 milliseconds



}

It might help your understanding if you used the words "startTime" or "pressedTime" for the time stamp value when the button is pressed instead of "previousMillis".

Here's an example of using the boolean timing variable (as described by dougp) to pick up the state change when the button becomes pressed.

unsigned long pressedTime;
unsigned long currentTime;
unsigned long period = 5000;
const byte buttonPin = A1;
byte buttonState = HIGH;
const byte ledPin = 13;
boolean timing = false;

void setup()
{
  Serial.begin(115200);
  pinMode(buttonPin, INPUT_PULLUP);
  pinMode(ledPin, OUTPUT);
  digitalWrite(ledPin, HIGH);
}

void loop()
{
  currentTime = millis();
  buttonState = digitalRead(buttonPin);
  if (buttonState == LOW && !timing)
  {
    pressedTime = currentTime;  
    digitalWrite(ledPin, LOW);
    timing = true;
  }
  if (timing && (currentTime - pressedTime >= period))
  {
    digitalWrite(ledPin, HIGH);
    timing = false;
  }
}

IoT_hobbyist:
Thank you @12Stepper for correcting my grammar mistake.

It wasn't a grammar mistake, but you knew that: you attitude as shown by the continued use of the word "should" as opposed to "could" or "may" is that your way is the only way, and it's not.