Timed response after release

So i want a button to cause an action upon release but only after a set time.

For example

Button pressed - nothing
Button released - wait 5 secs then serial print "action"

However, i want this in a way that if the button is pressed again within those 5 seconds, i would not print "action" until it has been dormant for those 5 seconds.

I have it printing upon release, thats no bother, but i cannot for the life of me get it to account for 5000 millis. Any help would be great!

Keep looking at the button and resetting the timer.

Post your code and it would be easier to see how you are doing it now and give advices.

“dreadlockdaddy”, I’m seeing it, wonder if I am close…

a7

Define "dormant". Do you mean "released"?

Ill upload the code later as im away from my computer, but its not much use as i dont have the bit i need. Ive tried dozens and dozens of things but cant get it to work :joy:

Basically my code so far is

If button high
Do nothing
Else
Print "action"

With the whole buttonState and debounce ect.
I basically need it count down 5 seconds upon release and print "action" only if that button stayed low for 5 seconds

Hello dreadlockdaddy
It seems to be a school assigment, isn´t it?
Post your sketch, well formated, with comments and in so called code tags "</>" and schematic to see how we can help.
Have a nice day and enjoy coding in C++.

Oh god, no its not a school assignment :joy: its code for my mandalorian mercs kits. Basically "button pushed" is a my helmet mic aka me speaking. After ive finished speaking ill have the arduino trigger a radio static sound. But i want to protect it from constant outbursts every time pause between speech, so ill set the time to say 800 millis or so. The example of serial print and 5 secs was purely to simplify the idea and coding for me to alter it.

Basically its the TRooper AMP idea but homemade and inline with my existing mic and amp. Using a sound sensor, nano and df player.

Ive already successfully built an ID10 with sound, light and motion, custom chest LEDs and a short press long press rangefinder on my helmet. Honestly i have no idea why this has me so stumped. Its sad :joy:

The English language has a lot of vague causal constructions. So people often think they've expressed a sequence clearly but it's not. So do you mean like this?

If the time between when the button was last pressed, and now, is greater than 5 seconds, perform an action.

In this case the action will be repeated every 5 seconds unless the button is pushed.

  1. If the time between when the button was last pressed, and now, is greater than 5 seconds, and the button is armed, perform an action and then disarm the button.

  2. If the button is pressed, mark the time and arm it.

Now it will not repeat.

Loop would be blocked by the buttonState change function would it not?

For example,
if button state changed
If button state high
Print high
Current state = prev state

If buttonstate = low
If event time is reached
Perform action
Current state = prev state

If buttonstate was not changed then it would not trigger ?

My reasoning is this.

If change detected
If low, startmillis
If Currentmillis - startmillis >= event
Print action

Obviously thats not code but you fet the idea. Would this work?

Loop will be blocked by any blocking code that you write. So you have to write it as non-blocking code.

I can't read your pseudocode because it has no code blocks {}

Mine would be:

if now - lastPressTime > 5 seconds and armed is true
  {
  perform action
  armed = false
  }
if button is in pressed state
  {
  lastPressTime = now
  armed = true
  }

You don't need any debounce or state change button code with this, it's baked in.

The problem is im focusing on falling signal. I need it for button released not pressed.

Button pressed is basically the signal from a microphone picking up my speech

Once ive finished talking i.e button released/LOW then i need it to wait, to check ive actually stopped talking before it fires off the command, which in this case, is a radio static noise through my speaker.

I now have it successfully serial.printing "action" after 5 seconds but then it will automatically print it after every button relase after that.

I need the timer to start once the button is released, and then stop once "action" has been printed, and tge wait for the button to be pressed abd released again. Really starting to frustrate me.

Please post your code. Or a small working sketch that illustrates the problem.

This is a simple enough matter, but the details will depend on what you are doing, exactly, already. And what else you need to be doing.

As a generalization, when things are happening when they are not supposed to, and vice versa, an inversion of some logic equation or wiring can turn the world upside down, so to speak, and make it therefor right side up.

a7

So i have it printing "rising" when pressed, And it prints the millis when released, but it WILL NOT print action, i had it printing action after 5 seconds before but then it would just print action after each hit past 5 seconds since powering up, rather than 5 seconds after release.

What i need is for it to calulate 5 seconds after the button is released, then print action. But i only want it to do this once, and only if the button stayed off during that 5 second period, if not, the state changed and it starts over.

int soundSensor = 2;
int buttonState = 0;         
int lastButtonState = 0; 
unsigned long actionTrigger = 5000; //serial print action
unsigned long startTimer; // time until action
unsigned long currentMillis;

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

}

void loop() {
currentMillis = millis();
  int buttonState = digitalRead(soundSensor);
  // compare the buttonState to its previous state
  if (buttonState != lastButtonState){ // has the state changed?
    
    if (buttonState == HIGH){ // if high, button pressed

     // if the current state is HIGH then the button went from off to on:
      Serial.println("RISING");
      lastButtonState = buttonState; // Save button state
      }
  }
    
if (buttonState !=lastButtonState){ 

  if(buttonState==LOW ){ // if low, start the timer
    startTimer = currentMillis; // records the millis that the button was released
    Serial.println(startTimer);

    

    // THIS BIT IS WHAT WILL NOT WORK. if time exceeds 5 seconds "actionTrigger
    // and the button remains unchanged, serial print "action"
    
    if(currentMillis - startTimer >= actionTrigger){ 
      if(buttonState == lastButtonState);
      Serial.println ("action");}

      //PLEASE HELP 
    }
  
lastButtonState = buttonState;
  }

    // Delay a little bit to avoid bouncing
    delay(50);
}

Haha, someone will have done by the time I get back to the big rig. At the beach now, dictating, which works surprise well.

a7

Or not.

Take a look at this. As long as you keep pressing/releasing the button, nothing happens.

// https://forum.arduino.cc/t/timed-response-after-release/964154

int soundSensor = 2;

// several tweaks because I use a button not a sound sensor

int buttonState = 1;
int lastButtonState = 0;

unsigned long actionTrigger = 2000; //serial print action 2 seconds for testing - life too short
unsigned long startTimer; // time until action
unsigned long currentMillis;

void setup() {
  Serial.begin(9600);
  Serial.println("\nWake up!\n");

  pinMode (soundSensor, INPUT_PULLUP);  // for proxy pushbutton here
}

void loop() {
  static bool didIt = false;   // not sure we need this, anticipating
  currentMillis = millis();

  int buttonState = !digitalRead(soundSensor);  // button upside down

  // compare the buttonState to its previous state
  if (buttonState != lastButtonState) { // has the state changed?

    if (buttonState == HIGH) { // if high, button pressed

      // if the current state is HIGH then the button went from off to on:
      Serial.println("pressed");
      //      lastButtonState = buttonState; // Save button state <-- move to correct place...

      didIt = false;    // reset do something trigger gaurd - did I need this?

    }
    else {
      Serial.println("released");
    }

    lastButtonState = buttonState; // Save button state
  }

  // when the button is pressed, reset the timer

  if (buttonState == HIGH) {
    startTimer = currentMillis;
    Serial.println("       reset timer");
  }

  if ((currentMillis - startTimer > actionTrigger) && !didIt) {

    Serial.println("                                Do something!");
    didIt = true;
  }

  // Delay a little bit to avoid bouncing
  delay(50);
}

And play with it here. You were making things too complicated! Very usual for any programmer, noobs to pros.

I hop you can figure out how to make it work in the actual circumstances where you need it.

HTH

a7

wow! thanks bud. i hate to swap a few highs and lows to work with my setup but this is working perfectly! thankyou :grin: i have no idea what youve done but ill read over it more thoroughly and do some more research. but looks like its working. cannot thankyou enough!

You have.

I won’t say in print, but it was more of a challenge than I thought it would be, so conceptually straight forward (keep resetting the timer) but tricky.

Do please put your finger on the code and pretend to be the ‘puter as it runs through the loop over and over… I tried to leave some comments as a guide.

The only thing that really came out of a bag of tricks was the didIt thing, which I knew I might need so it wouldn’t keep doing that thing.

a7

theres some areas of arduino here ive yet to look into so gives me plenty to look into and develop further in my own abilities. thanks bud! it is a stupidly stragihtforward task but has me comepletely stumped. this is great!

One more thing - I noticed the delay(50); in the loop, which is a loop killer. Crude though effective debouncing.

I put real debouncing up where the button is examined, now the loop runs free as it is meant to do.

just in case anyone looks closely…

Yes, whatever you are thinking.

a7

Hello dreadlockdaddy
Keep it simple and stupid. :nerd_face:

constexpr byte ButtonPin {A0};      // portPin o---|button|---GND
void setup() {
  Serial.begin(9600);
   pinMode(ButtonPin, INPUT_PULLUP);
}
void loop () {
  delay (20); 
  static int buttonLastState =false; 
  int statusNew=!digitalRead(ButtonPin);
  if (buttonLastState!=statusNew) {
    buttonLastState=statusNew;
    if (!buttonLastState) {
      delay (5000);
      Serial.println(F("ACTION"));
    }
  }
}

Have a nice day and enjoy coding in C++.

I think you made it just a little too stupid.

You threw out the ability for the time out thing to play nice with the other things the OP is attempting to do in his sketch, see #6

a7