Detecting Button Press inside loop with delay

Evening

I’ve got a few things going on in my main loop including a delay which I can’t get rid of. The delay is stopping a temperature sensor from taking a reading too quickly. Inside the loop it is also checking for a button press. The code can’t see the button being pressed if it’s holding in the delay which is making it a pain as you have to time the button presses so that it can see them whilst executing the main code and not stuck in the loop.

Is there a way around this? I played around with PICs years ago and if I remember rightly I’d have used an interrupt to constantly check if the button was being pressed regardless of where it was in the main loop.

Any help in terms of a solution for this? I’m using Arduino uno.

Thanks for your help in advance.
Chris

In the IDE, take a look at File|Examples|Digital|BlinkWithoutDelay. You do not need delay().

1 Like

The solution is to not use delay(), and use millis() for timing. This tutorial explains how it works:

1 Like

Why not try interrupts again? Here is a sample of one type of interrupt where I am running blocking code in a constant loop, and the interrupt can still be triggered as the mcu takes a breath between actions. The ISR only flags the button press. The main (loop()) function checks if that flag is set. This routine is not ready for long presses, as that will trigger two interrupts. Ask if you have questions.

basic non-blocking approach

const byte PinBut    = A2;
const byte PinAnalog = A0;
byte butState;

const unsigned long MsecPeriod = 1000;
      unsigned long msec0;

// -----------------------------------------------------------------------------
void
loop (void)
{
    unsigned long msec = millis ();

    if (msec >=  msec0)  {
        msec0 += MsecPeriod;
        int adc = analogRead (PinAnalog);
        Serial.print   ("adc read ");
        Serial.println (adc);
    }

    byte but = digitalRead (PinBut);
    if (butState != but) {
        butState = but;
        delay (20);         // debounce
        if (LOW == but)
            Serial.println ("but press");
    }
}

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

    pinMode (PinBut, INPUT_PULLUP);
    butState = digitalRead (PinBut);
}

If you use delay(), interrupts are not going to help (much) as no matter an interrupt, delay() will leave your main loop brain dead to the fact for the entirety of that delay period.

By all means learn how to do this without delay, "blink without delay" has been mentioned.

Or learn how it might be done with interrupts for realz.

On the other hand or for now, consider writing your own delay function.

See

and the entire thread. Search these fora for "mydelay", it's not an uncommon hack and even if you become the wizard of blinking without delay or using interrupts, it illustrates a kind of thinking that can come in handy from time to time.

boolean myDelay(unsigned long d) 
{
  while (d > 0) 
  {
    if (digitalRead(buttonPin) != currentState)
      return true;
    delay(1);
    d--;
  }
  return false;
}

You don't even need to rename the calls to delay(), but that's a hacker's hack and gets wild pretty quick, and doing it in public will mark you.

a7

Here's one I didn't forget about, but may have been advised to do:

TBH I have never used it in anything real. I just wondered one day what it might take. Play with it in the simulation that is linked.

a7

@craynerd I think it's time you shared your code, complete, in code tags, in order for the helpers here to give you more focused assistance. Otherwise, it would seem like this thread is dying on it's feet.

lol not too sure how the thread is dying on its feet! I just thought it was a bit too much to post a huge script managing a few button, lcd, temp sensor and IR transmitter and reciever, when essentially I just need to know how to not use a delay function! Thanks for the input though! You were spot on in your first post! Thanks

Brilliant - got this working and it is doing a great job. Thank you so much!

I didn’t know that actually. Like I say I’ve played with Arduino and pics for years but absolutely no expert or even a proficient user! When I was playing with PICs years ago, my understanding was an interrupt was called at a specific time regardless of what was happening in the loop. So for example it would read the main loop function and then at set intervals look at the interrupt code regardless of what was happening in the loop. Obviously my understand was wrong so thanks for clarifying!
Chris

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.