0

Delay() doesn't work inside ISR routines, but here I have used it in loop and outside interrupt section still Delay is not working, however there isn't any error coming. What is wrong?

int L = 2;
volatile int done0=0;                                //ISR variables
void recordL();                                              //ISR 1

void setup() {
Serial.begin(9600);
Serial.println("Start");

pinMode(L,INPUT);
}

void loop() {

interrupts(); 
attachInterrupt(0,recordL,RISING);
done0=0;

while(!done0)
{
    Serial.println(millis());
}
noInterrupts();

Serial.println("Detected");
delay(5000);
Serial.println("After Delay");
}

void recordL()
{
  Serial.println("in Interrupt0");
  done0=1;
}
  • 1
    What is it for ? Perhaps you don't need interrupts at all. Please don't use a Serial.println in the while-loop, the serial output buffer will get full. Please don't use Serial.println in the interrupt routine, because the Serial library uses interrupts itself. In most cases the attachInterrupt is done only once in the setup function. – Jot Nov 15 '17 at 7:30
  • Looks like I have made lot of mistakes. I need interrupt because I want to detect sound coming from 2nd IO pin. After attaching interrupt once in Setup, do I need to do interrupts() and nointerrupts() in Loop section? – MeetR Nov 15 '17 at 7:35
  • I prefer to keep the interrupts running and use just variables for interrupt detection. The Arduino Uno can run a small interrupt routine a few thousand times per second. I don't understand the sound signal from a second I/O pin, can you explain that ? – Jot Nov 15 '17 at 7:42
  • Actually I have 3 sound sensors and sound can come at any time at these sensors (If sound is greater than some threshold then 1 else 0), so it can come simultaneously to all 3 with very small difference in time. I want to measure that exact time when sound has reached sensor. So I am using 2 interrupt pin and 1 simple pin which is waiting for sound in loop. – MeetR Nov 15 '17 at 7:47
  • 1
    The trick with interrupts is to do the least possible amount of work. Just raise a flag or change a value and let the loop do the thing. – user31481 Nov 15 '17 at 7:53
0
noInterrupts();

Serial.println("Detected");
delay(5000);

delay() won't work with interrupts turned off.

| improve this answer | |
  • Ok. Is there need to off interrupt ? or detaching it? – MeetR Nov 15 '17 at 7:22
  • If you don't want that interrupt while you are delaying and printing, detach the interrupt. – Nick Gammon Nov 15 '17 at 20:50
1

Do I need interrupts() noInterrupts() in the loop section?

Yes, you do. Always.

The optimal workflow is

  1. In the ISR itself, just raise a flag or directly change some global variable.
  2. In the loop you first copy that flag/variable to a local variable, using interrupts/noInterrupts to prevent the ISR changing the value while you are using/copying it.

Assignment are not atomic in Arduino World. That means that the value you are copying can change while you are doing it, and you end with garbage in your variables. Or, worse, it can change between one statement and the next. Try to debug that.

This is how you do it. In this example, I'm using an interrupt to manage a button (with debouncing). I need to detect state (pressed/not pressed) and timing (how long you pressed it). I can't directly use lastFallingEdge in loop; I copy it first so it won't change while I'm using it.

volatile unsigned long lastFallingEdge = 0; // For debouncing.
volatile boolean bPressed = false;

void buttonInterrupt(void)
{
    lastFallingEdge = millis();
    bPressed = true;
}

void loop()
{

    if(bPressed) {
        noInterrupts();
        bPressed = false;
        unsigned long falling = lastFallingEdge;
        interrupts();
        unsigned long len = millis() - falling;

        // Do something.
    }
}
| improve this answer | |
  • In other answer it is mentioned that Delay won't work after noInterrupts(). How to deal with that? – MeetR Nov 15 '17 at 8:14
  • You put the delay() in loop(). You call the delay() after checking that an interrupt occurs. – user31481 Nov 15 '17 at 8:18
  • There is the timestamp! Well done @LookAlterno. Perhaps the interrupt can stop updating the 'lastFallingEdge' while it has not been processed in the loop (while the flag is still true). Can the flag (byte) be reset after the interrupts are turned on ? (sorry for nitpicking). – Jot Nov 15 '17 at 8:29
  • 1
    Can the flag be ..? No. Look: 1) "loop()" calls "interrupts()", 2) An interrupt arrive, ISR is called, bPressed is set to true; 3) "loop()" execute "bPressed=false;". Now your system is in a inconsisten state (and you missed that button press). Interrupts are tricky; you have to keep it short and simple. – user31481 Nov 15 '17 at 8:40
0

Delay() function works by using timer interrupts internally. If you disable all interrupts using NoInterrupt function , then how will it work. Using that function is not recommended in code, as it causes unexpected misbehaviors.

| improve this answer | |
  • Yes got it. I am facing one more issue here, delay is not working when 2 ISR gets executed at same time (delay is in loop section), is that because there are only 2 interrupts in arduino and delay can't find free interrupt and so can't work? – MeetR Nov 15 '17 at 13:37
  • Delay () in loop () doesn't work cz it comes after nointerrupt() function – Mitu Raj Nov 15 '17 at 13:39
  • This is happening also after removing nointerrupt() (means after keeping interrupt always on). – MeetR Nov 15 '17 at 14:07
  • Only attach interrupt is needed here....not needed in loop() ..only in setup() – Mitu Raj Nov 15 '17 at 14:09

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.