Using delay() for polling and delayMicroseconds() for interrupts

On many help sites, including the Arduino reference page, the search results for using delays in polling and interrupts all said that only delayMicroseconds() can be used inside an ISR (Interrupt Service Routine).
However, it was not mentioned whether this would affect all occurrences of delay() in another part of the code were I’ve used polling.
In my code, I’ve used delay() for the polling part of the code, and delayMicroseconds() for the interrupt. I even tried using delayMicroseconds() for all delays in the code, but got the same result:
The ISR seemed to make the Arduino UNO (that’s the board I’m using) ignore ALL delays in the code.

I’ve attached the code to this post. Any help would be much appreciated. Thank you. :smiley:

LFR.ino (11.3 KB)

You can call delayMicroseconds in an ISR, but not for 450 milliseconds worth. That's ridiculous. An ISR should be blazing fast. If you've got 250ms to wait around before you shift those motors again then there's absolutely no reason to have it in an interrupt.

Ok. Thanks. I’ll remember to correct that.
But the polling part of the code is still skipping delays. And those are like delay(230); etc. Why does that happen?

void yjunc()// The Interrupt Service Routine (ISR)
  {
...
    delayMicroseconds(100000);
...
    delayMicroseconds(250000);
...
    delayMicroseconds(100000);
  }

Lol. No.

Don't do delays in an ISR. Don't argue with this.

During an ISR interrupts are turned off. Thus the calculations for millis (and indeed micros) will be seriously out. You can't just hang around for a half a second in an ISR. Well, you can. But don't complain when everything else stops working.

RoboCode:
On many help sites, including the Arduino reference page, ...

The Arduino reference page says:

Generally, an ISR should be as short and fast as possible. If your sketch uses multiple ISRs, only one can run at a time, other interrupts will be ignored (turned off) until the current one is finished. as delay() and millis() both rely on interrupts, they will not work while an ISR is running.

"Short and fast" is not having a 450 mS (half a second) delay in the ISR. Plus it mentions that delay() relies on interrupts. Plus it links to my page about interrupts (http://www.gammon.com.au/interrupts).

My page mentions, right near the top:

  • Keep it short

Also see http://arduino.cc/en/Reference/DelayMicroseconds

Currently, the largest value that will produce an accurate delay is 16383.

So your attempt to delay for 250000 µS is well and truly outside the acceptable range.

Ok. So what if i have a volatile integer which increments during the ISR, and then have a condition in void loop() to execute the long delays, if it detects an increase in the integer value.
That's just a momentary action for the ISR, so it should work right?

Here’s the code with the change in the ISR:

LFR_v2.4_2cm.ino (11.4 KB)

RoboCode:
execute the long delays

I doubt if you should be doing that anyway, be it with delay() or delayMicroseconds(): rather embrace the idea of Blink Without Delay as also explained in (among other places) this video.

@JimboZA
But i want it to pause everything else and run the delay(). That’s why I decided to use interrupts in the first place. Because they interrupt the code. :grinning:

But then you shoot yourself in the foot by the delay() doing exactly that: stopping all other activity. You might get it to work now, but then if you need to enhance the code and get it to do something which is blocked by your delay(), you're exactly that: blocked.

@JimboZA
And if the work that it's doing is very important, then blocking all other activity is also very important. Hence, the delay() is necessary.
BTW: I think you misunderstood the duration of the delay I've mentioned above. It lasts for just 250 milliseconds.

I think you misunderstood the duration of the delay I've mentioned above. It lasts for just 250 milliseconds.

. . . which is about fifteen times longer than the maximum recommended.

Hence, the delay() is necessary.

I think I'll frame that one. ;D

void loop()
{
  sen7val = digitalRead (sen7);
  sen6val = digitalRead (sen6); 
  sen5val = digitalRead (sen5);
  sen4val = digitalRead (sen4); 
  sen3val = digitalRead (sen3);
  sen2val = digitalRead (sen2); 
  sen1val = digitalRead (sen1);

Your code would be a lot shorter and easier to read and maintain if you packed these values into a single variable.

void setup()
{
  attachInterrupt(0, yjunc, LOW);//int0 is initiated. "yjunc" is the ISR.

You want FALLING, not LOW.


    i==x;

What is that achieving?


So what if i have a volatile integer which increments during the ISR, ...

int i = 0;
int x = 0;
...
void yjunc()// The Interrupt Service Routine (ISR)
  {
    x=i+1;
  }

x isn't exactly incrementing, it is "i+1".

Neither x nor i are volatile.

I don't want to look like I am picking on you, but attention to detail is important here.

Explain WHAT you want to achieve and not HOW you think you could do that.

An ISR should only last for as few microseconds as possible and certainly should have nothing like a delay() in it.

Remember that the Arduino system has other background ISRs that you are not aware of and your code should not prevent them from happening.

If your program needs to wait for something to happen you can easily do that using millis(). Look at the demo several things at a time for a longer example of the BWoD technique.

...R

@Nick Gammon
Thanks for telling me about the FALLING. I wasn’t quite sure which one to use, LOW or FALLING or CHANGE.

volatile int i = 0;

void setup()
{
  attachInterrupt(0, yjunc, FALLING);//int0 is initiated. "yjunc" is the ISR.
...

void yjunc()// The Interrupt Service Routine (ISR)
  {
    i=i+1;
  }

As for:

x==i

It was to change x to the value of i, but that’s not necessary now so i excluded it.

The whole code is attached.

LFR.ino (11.4 KB)

It was to change x to the value of i,

. . . but it didn't.

if (i=i+1)

Oops.