How to stop a function during button press, if button is held.then continue loop

So far so good thank you everyone for your help. When a button is pressed, my arduino will light an LED, count the number of times the button has been pressed, take a min, max, and average time of button presses and write them to the eeprom. It will also use a mosfet to energize a solenoid and using PWM significantly reduce the amperage demand of the solenoid when holding. It will also go to sleep after a specific interval and wake upon a new button press. FYI, I do have a modified EEPROM include that allows me to write INT. I can also retrieve my data via serial.

What I’m looking to add to this is a safety feature that if the button is pressed for too long or gets stuck, the mosfet and LED pin no longer write and the loop will not begin again till the button is let go. Thank you, I’ve been trying several variations of things, this being the last and still no go.

/*
* Andy's latch Circuit V4  on a Teensyduino
*/

#include <EEPROM.h>
#include <avr/sleep.h>
#include <avr/power.h>
#include <avr/interrupt.h>

#define buttonPin 5             // Set button pin input on pin 5 INT 0
#define ledPin 11               // Set LED pin as 11 LED on Teensy
#define mosfetPin 10            // Set Mosfet control to pin 10 PWM
#define addr1 0                 // EEPROM write address 0-1 for int buttonActivations
#define addr2 2                 // EEPROM write address 2-3 for int Max
#define addr3 4                 // EEPROM write address 4-5 for int Min
#define addr4 6                 // EEPROM write address 6-7 for int Avg
int val;                        // variable for reading the pin status
int buttonState;                // variable to hold the button state
int buttonActivations = 0;      // how many times the button has been activated i.e number of times latch has been used
int latchUses;                  // written value to the EEPROM for seatpost uses.
unsigned long firstCount;       // First time stamp when button activated
unsigned long endCount;         // End time stamp when button de-activated
int maxTime;                    // Max time that button has been activated
int minTime;                    // Min time that button has been activated
int avgTime;                    // Avg time that button has been activated
int timeOn;                     // The amount of time the button is activated in milliseconds
int newAverage;                 // New Avg time computed by program
int sleepStatus = 0;            // Sets the sleep status
unsigned long startTime;        // First time stamp for sleep
unsigned long endTime;          // Last time stamp for sleep
unsigned long finalTime;        // Check for time elaspsed to enter sleep mode
unsigned long expire;           // Expire time laps setting

void wakeUpNow()
{
}  //End of wakeUpNow



void setup() 
{
   pinMode(buttonPin, INPUT);    // Set the button pin as input
   digitalWrite(buttonPin, HIGH); //Sets the button pin in case of switch failure/disconnection, pushing button grounds pin to activate/wakeup as well
   pinMode(ledPin, OUTPUT);      // Set the LED pin as output
   pinMode(mosfetPin, OUTPUT);   // Set the Mosfet pin as output
   Serial.begin(9600);           // Set up serial communication at 9600bps for test
   Serial.println("Retrieve Data?");
   buttonState = digitalRead(buttonPin);   // read the initial state
   latchUses = EEPROM.readInt(addr1);    // Read EEPROM to check latchUses
   if (buttonActivations < latchUses) buttonActivations = latchUses;
}  // End of Setup


void sleepNow()
{
  attachInterrupt(0, wakeUpNow, LOW);
  delay(100);
  set_sleep_mode(SLEEP_MODE_PWR_DOWN);
  sleep_enable();
  sleep_mode();
  sleep_disable();
  detachInterrupt(0);
} //End sleepNow
  


void loop()
{
   val = digitalRead(buttonPin);        // read input value and store it in val
   maxTime = EEPROM.readInt(addr2);      // Read from EEPROM
   minTime = EEPROM.readInt(addr3);      // Read form EEPROM
   avgTime = EEPROM.readInt(addr4);      // Read from EEPROM   


   if (val != buttonState)               // the button state has changed!
   {          
      if (val == LOW)                    // check if the button has been pressed
      {  
         firstCount = millis();
         digitalWrite(ledPin, HIGH);    // Turn LED On when button in pressed
         analogWrite(mosfetPin, 255);   // PWM to mosfet 100%
         delay(300);                    // Delay 
         analogWrite(mosfetPin, 127);   //PWM to mosfet 50% 
         buttonActivations++;           // increment the buttonActivations variable
         if (buttonActivations > latchUses) EEPROM.writeInt(addr1, buttonActivations);  // Write to EEPROM if new value is higher than old
         
          
         //Serial.print("Seatpost has been used ");      //diagnostic script to check if button presses are reading on serial monitor. will be remarked out later
         //Serial.print(buttonActivations);
         //Serial.println(" times");
        // delay(100);
      }         
      else 
      {
        analogWrite(mosfetPin, 0);
        digitalWrite(ledPin, LOW);    //Turn LED off 
        endCount = millis();
         timeOn = endCount - firstCount;
         if (minTime <= 0){ 
            EEPROM.writeInt(addr3, timeOn);}     // Store first reading if EEPROM empty
         if (timeOn > maxTime){ 
            EEPROM.writeInt(addr2, timeOn);}     // Replace maxTime on EEPROM if exceeded
         if (timeOn < minTime){ 
            EEPROM.writeInt(addr3, timeOn);}     // replace minTime on EEPROM if exceeded
       } 
      newAverage = (  (avgTime * (latchUses - 1) + timeOn)  / latchUses);
       {    
         EEPROM.writeInt(addr4, newAverage);     // Calculate average seatpost time usage
       }
   }
     
      buttonState = val;      // save the new state in our variable
      
   if (digitalRead(buttonPin) == LOW)
   {
     startTime = millis();           // Reads time in order to call sleep after 2min
     expire = millis() + 2000;
     if (millis() >= expire) 
     {
      digitalWrite(mosfetPin, LOW);
      digitalWrite(ledPin, LOW);
     }
   }
   
   if (digitalRead(buttonPin) == HIGH)
   {
     endTime = millis();                    // Calls sleep after 2min of inactivity  13mA normal operation.  .7mA pwr_down
     finalTime = (endTime - startTime);
     if (finalTime >= 120000)
      {
        sleepNow();
      }
   }

   if (Serial.available())   // Allow data to be transfered via serial      
   { 
      char ch = Serial.read();
      if (ch == 'r' || ch == 'R');{
      retrieveData();}
   }
}  // End of Void Loop


void retrieveData()      // retrieve program
{
   latchUses = EEPROM.readInt(addr1);      // Read EEPROM
   int rmaxTime = EEPROM.readInt(addr2);     // Read EEPROM and allow to read as a decimal value
   int rminTime = EEPROM.readInt(addr3);
   int ravgTime = EEPROM.readInt(addr4);
   float maxOn = rmaxTime;
   float minOn = rminTime;
   float avgOn = ravgTime;

   Serial.print("Latch has been used " );
   Serial.print("\t");
   Serial.println(latchUses);
   Serial.print("Latch Max time activated ");
   Serial.print("\t");
   Serial.println(maxOn / 1000);   
   Serial.print("Latch Min time activated ");
   Serial.print("\t");
   Serial.println(minOn / 1000);
   Serial.print("Latch Avg time activatied ");
   Serial.println(avgOn / 1000);
}  // End of retrieveData

There's a lot of code there and I haven't looked at all of it, but I see you have got logic to remember the previous button state and check whether the current state is changing.

If you want to detect when the current state hasn't changed for a long time, then you could add something like this:

if (val != buttonState) 
{
  // your existing code here
}
else
{
  // state hasn't changed
  if (val == LOW) )
  {
    // button is held down
    int buttonDownDuration = millis() - buttonDownTime;
    if(buttonDownDuration > threshold)
    {
      // 'stuck button' logic goes here
    }
  }
}
     expire = millis() + 2000;
     if (millis() >= expire)

That "if" would never become true would it?

@PeterH: How would you define buttonDownTime?

@NickG I think I see what your saying, it's a cat chasing it's tail...with the expire = millis() + 2000; above, it will never catch up.

AndyinUT: @PeterH: How would you define buttonDownTime?

Given that you are trying to detect when the button has been held down 'too long', I thought the obvious way to do that was to record when it was pressed and then later on compare that to the current time to see how much time has elapsed since it was pressed.

In that context, you can probably guess what buttonDownTime was supposed to be.

I'm really tripping up on how the flow of logic goes I'm guessing. expire = buttonDownTime that PeterH suggested. Still no go in either of these attempts (I've just been using the LED as my diagnostic tool, so while holding my button...it's not turning off) I'm guessing where "expire" is in the flow it's not factoring in like I'm expecting it to.

if (val != buttonState)               // the button state has changed!
   {          
      if (val == LOW)                    // check if the button has been pressed
      {  
         firstCount = millis();
         digitalWrite(ledPin, HIGH);    // Turn LED On when button in pressed
         analogWrite(mosfetPin, 255);   // PWM to mosfet 100%
         delay(300);                    // Delay 
         analogWrite(mosfetPin, 127);   //PWM to mosfet 50% 
         buttonActivations++;           // increment the buttonActivations variable
         if (buttonActivations > seatpostUses) EEPROM.writeInt(addr1, buttonActivations);  // Write to EEPROM if new value is higher than old
         expire = millis() - firstCount;
          
         //Serial.print("Seatpost has been used ");      //diagnostic script to check if sensor is reading on serial monitor. will be remarked out later
         //Serial.print(buttonActivations);
         //Serial.println(" times");
        // delay(100);
      }
      else if (expire >= 2500)
      {
      digitalWrite(ledPin, LOW);
      analogWrite(mosfetPin, 0);
      }
 if (val != buttonState)               // the button state has changed!
   {          
      if (val == LOW)                    // check if the button has been pressed
      {  
         firstCount = millis();
         digitalWrite(ledPin, HIGH);    // Turn LED On when button in pressed
         analogWrite(mosfetPin, 255);   // PWM to mosfet 100%
         delay(300);                    // Delay 
         analogWrite(mosfetPin, 127);   //PWM to mosfet 50% 
         buttonActivations++;           // increment the buttonActivations variable
         if (buttonActivations > seatpostUses) EEPROM.writeInt(addr1, buttonActivations);  // Write to EEPROM if new value is higher than old
         expire = millis() - firstCount;
         if (expire >= 2500);
         {
           digitalWrite(ledPin, LOW);
           analogWrite(mosfetPin, 0);

Victory! Outside of my state change loop I have these to set the sleep function. I place the check for expire in there..works like a charm now. Thanks again! Now on to trying to code a "double tap" feature into the button presses.

 if (digitalRead(buttonPin) == LOW)
   {
     startTime = millis();
     expire = millis() - firstCount;
     if (expire >= 2500)
     {
      analogWrite(mosfetPin, 0);
      digitalWrite(ledPin, LOW);
     }
   }
   
   if (digitalRead(buttonPin) == HIGH)
   {
     endTime = millis();
     finalTime = (endTime - startTime);
     if (finalTime >= 120000)
      {
        sleepNow();
      }
   }