delay seems not to work.

I have a sketch that accepts an interrupt from a PIR sensor.
When INT0 is LOW motion has been detected.
When INT0 is HIGH idle state no motion detected.
Between interrupts, the micro is put to sleep.

When I receive an interrupt I:

  1. Read the battery Voltage
  2. Send a message via a wireless modem

When a message is sent, I need to delay the sketch for about 5 seconds while the RF modem sends the message. No ack is required.

In void Loop() the interrupts call either function void sendOFF() / or void sendON().
In the void sendOFF() / void sendON() functions I have the "delay(5000);

My Sketch:

#include <Sleep_n0m1.h>
#include <Vcc.h>

const float VccMin   = 2.0;           // Minimum expected Vcc level, in Volts.
const float VccMax   = 3.6;           // Maximum expected Vcc level, in Volts.
const float VccCorrection = 1.0 / 1.0; // Measured Vcc by multimeter divided by reported Vcc
Vcc vcc(VccCorrection);
int myVolts;

Sleep sleep;

#define pirPin 2

int pirState = 1;
boolean sending = false;


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

void loop()
{
  delay(100); ////delays are just for serial print, without serial they can be removed
  Serial.println("execute your code here");
  //*********************************************************
  pirState = digitalRead(pirPin);

  Serial.print("PIR State: ");
  Serial.println(pirState);

  if ((pirState == 1) && (!sending)) {
    sending = true;
    Serial.println("PIR State: No Detect");
    readBattery();
    Serial.print("Battery: ");
    Serial.println(myVolts);
    sendOFF();
  }
  if ((pirState == 0) && (!sending))  {
    sending = true;
    Serial.println("PIR State: Got Detect");
    readBattery();
    Serial.print("Battery: ");
    Serial.println(myVolts);
    sendON();
  }

  Serial.println("********************************************");
  Serial.println("Sleeping Till Interrupt");

  delay(100); //delay to allow serial to fully print before sleep

  sleep.pwrDownMode(); //set sleep mode

  //Sleep till interrupt pin equals a particular state.
  sleep.sleepPinInterrupt(pirPin, CHANGE); //(interrupt Pin Number, interrupt State)
}

void sendON() {
  Serial.println("Send ON");
  Serial.println("Delay 5 seconds Start");
//  delay(5000);
  Serial.println("Delay End");
  sending = false;
}

void sendOFF() {
  Serial.println("Send OFF");
  Serial.println("Delay 5 seconds Start");
//  delay(5000);
  Serial.println("Delay End");
  sending = false;
}

void readBattery()
{
  float v = vcc.Read_Volts();
  myVolts = v * 10;
}

When “delay(5000);” is commented out, the sketch runs fine and the Serial Monitor outputs:

execute your code here
PIR State: 1
PIR State: No Detect
Battery: 33
Send OFF
Delay 5 seconds Start
Delay End
********************************************
Sleeping Till Interrupt
execute your code here
PIR State: 0
PIR State: Got Detect
Battery: 33
Send ON
Delay 5 seconds Start
Delay End
********************************************
Sleeping Till Interrupt
execute your code here
PIR State: 1
PIR State: No Detect
Battery: 33
Send OFF
Delay 5 seconds Start
Delay End
********************************************
Sleeping Till Interrupt

However, if “delay(5000);” is not commented out, the sketch seems to be stuck in a loop with “PIR State: 0”.
Serial Monitor outputs:

execute your code here
PIR State: 1
PIR State: No Detect
Battery: 33
Send OFF
Delay 5 seconds Start
Delay End
********************************************
Sleeping Till Interrupt
execute your code here
PIR State: 0
PIR State: Got Detect
Battery: 33
Send ON
Delay 5 seconds Start
Delay End
********************************************
Sleeping Till Interrupt
execute your code here
PIR State: 0
PIR State: Got Detect
Battery: 33
Send ON
Delay 5 seconds Start
Delay End
********************************************
Sleeping Till Interrupt
execute your code here
PIR State: 0
PIR State: Got Detect
Battery: 33
Send ON
Delay 5 seconds Start
Delay End
********************************************
Sleeping Till Interrupt
execute your code here
PIR State: 0
PIR State: Got Detect
Battery: 33
Send ON
Delay 5 seconds Start

delay() depends on interrupts being enabled
Interrupts are disabled when in an ISR

Could that be a problem do you think ?

I was not aware of that.
I am sure that could be the problem.
Any idea as to how I can overcome that?
I have tried with a millis timer in the void sendOFF() / void sendON() functions but had the same problem as running the delay(5000).

UKHeliBob:
delay() depends on interrupts being enabled
Interrupts are disabled when in an ISR

I thought of that too. But, the ISR is within the library OP included. By the time control returns from the 'sleep.sleepPinInterrupt()' call, the interrupt has been serviced and the ISR exited.

This is evidenced by the Serial.print calls working.

Thanks,
Any idea how to overcome this.

I'd try to get it working first without the sleep / interrupt stuff. Just simulate 'sleeping' by polling for PIR change in a 'while' loop.

gfvalvo:
This is evidenced by the Serial.print calls working.

Serial.print() works with interrupts disabled. The characters are put in the buffer until the buffer is full. Then, if interrupts are disabled, the Serial.write() function will poll the UART status register to see if the interrupt flag is set. If so, it calls the ISR to take a byte from the buffer and put it in the output register. This makes room to put one character into the buffer. Repeat until Serial.print() stops calling Serial.write().

johnwasser:
Serial.print() works with interrupts disabled.

Be that as it may, I believe the first part of my post is correct. By the time control in OP's code returns from the call to 'sleep.sleepPinInterrupt()' , it is no longer in interrupt context.

Declan:
Thanks,
Any idea how to overcome this.

Footnote 3 on the ATmega328P list of sleep modes says "For INT1 and INT0, only level interrupt.". I think that means that only the "LOW" interrupt mode is available when sleeping deeper than 'Idle'. If you need RISING, FALLING, or CHANGE you will have to use a Pin Change Interrupt (different from the two External Interrupt pins).