Hardware and Software Interrupts

Please could someone point me in the right direction in achieving the following:
Sleep for xx period
This I can do, no problem.
However, I must also have an External Interrupt that will wakeup the UNO when pulled LOW.
I can get both Internal and External Interrupts to work individually.
But, I cannot get them to work in the same sketch.
How can I have two separate ISRs in my sketch - one firing when the software interrupt sleep expires (say 8 seconds) - the other ISR must fire only when the Hardware Interrupt is pulled low.
Is this at all possible?

Can't help with sketch if we don't have the sketch.
Those two interrupts in theory shouldn't be conflicting, by the way.

Here is my code:

#include <LowPower.h>
//#include <power2.h>

const byte SOSpin = 2;
volatile byte state = LOW;
int SOScount;
int sleepCount;

void setup() {
  Serial.begin(9600);
  SOScount = 0;
  pinMode(SOSpin, INPUT_PULLUP);
  attachInterrupt(digitalPinToInterrupt(SOSpin), SOSpressed, LOW);
}

void loop() {
  sleepNow();
  sleepCount++;
  Serial.print("Sleep Count: ");
  Serial.println(sleepCount);
  delay(100);
  Serial.print("SOS Count: ");
  Serial.println(SOScount);
  Serial.println();
  delay(100);
}

void sleepNow() {
  LowPower.powerDown(SLEEP_8S, ADC_OFF, BOD_OFF);
}

void SOSpressed()
{
  static unsigned long last_interrupt_time = 0;
  unsigned long interrupt_time = millis();
  // If interrupts come faster than 200ms, assume it's a bounce and ignore
  if (interrupt_time - last_interrupt_time > 200)
  {
    SOScount++;
  }
  last_interrupt_time = interrupt_time;
}

When I run the above sketch, the Monitor output:

Sleep Count: 1
SOS Count: 0

Sleep Count: 2
SOS Count: 0

<================== PUSHED BUTTON HERE
Sleep Count: 3
SOS Count: 0 <===== SHOULD INCREMENT HERE

Sleep Count: 4
SOS Count: 0 <===== SHOULD INCREMENT HERE

Sleep Count: 5
SOS Count: 0 <===== SHOULD INCREMENT HERE

The WakeUp from sleep is ok and increments the sleepCount.
However, once the Interrupt on INT0 is pushed, the sleepCount increments and not the SOScount.

Check whether your ISR is called at all, by skipping the time check in SOSpressed(). Can it really wake up the controller from the selected sleep mode?

Debouncing should be done in loop(), not in an ISR.

The LOW trigger bothers me. I'm not sure how that works, but maybe it's re-interrupting because it's always low when the button is pressed, and all the interrupts are within 200 ms. You might try FALLING instead. But I agree that trying to check millis() stuff inside an ISR can lead to unpredictable results because millis aren't incrementing while the ISR is running.

ShermanP:
The LOW trigger bothers me. I’m not sure how that works, but maybe it’s re-interrupting because it’s always low when the button is pressed, and all the interrupts are within 200 ms. You might try FALLING instead.

You have to use LOW or HIGH for the interrupt mode because of a limitation in the AVR processor. See footnote 3 on the table “Active Clock Domains and Wake-up Sources in the Different Sleep Modes”:
“For INT1 and INT0, only level interrupt.”

That means you can’t use a RISING, FALLING, or CHANGE interrupt to wake the processor in any sleep mode other than the mildest: Idle.

When the LOW interrupt occurs you can disable the interrupt until you have debounced the button press in software.

johnwasser:
You have to use LOW or HIGH for the interrupt mode because of a limitation in the AVR processor. See footnote 3 on the table "Active Clock Domains and Wake-up Sources in the Different Sleep Modes":
"For INT1 and INT0, only level interrupt."

That means you can't use a RISING, FALLING, or CHANGE interrupt to wake the processor in any sleep mode other than the mildest: Idle.

When the LOW interrupt occurs you can disable the interrupt until you have debounced the button press in software.

I need a better understanding of this. I built a remote control where a keypad press triggers a pin change interrupt on any of D4-D7 in power-down sleep mode, and it wakes up the processor just fine. It's just odd that pin change works on D4-D7, but not on INT0 and INT1. Anyway thanks for pointing this out. I guess I just hadn't run up against it before.

And I agree that disabling the interrupt in the ISR would be the solution if continuing re-interrupts is a problem. But do you know if a low state will continue to generate interrupts? Or is there some kind of lockout after it has interrupted once? It just seems that if you clear the flag, and the pin is still low, it's going to interrupt again.

ShermanP:
I need a better understanding of this. I built a remote control where a keypad press triggers a pin change interrupt on any of D4-D7 in power-down sleep mode, and it wakes up the processor just fine.

That's because Pin Change interrupts are not the external interrupts INT0 or INT1.

ShermanP:
It's just odd that pin change works on D4-D7, but not on INT0 and INT1. Anyway thanks for pointing this out. I guess I just hadn't run up against it before.

Pin Change interrupts will work on Pin 2 and Pin 3 (PCINT18 and PCINT19) to wake the processor... but you can't do RISING, FALLING, or LOW interrupts on a Pin Change interrupt.

NEWS: In contradiction to the table of wake-up sources, the External Interrupts part of the datasheet says "Low level interrupts and the edge interrupt on INT2:0 are detected asynchronously. This implies that these interrupts can be used for waking the part also from sleep modes other than Idle mode." Does "the edge interrupt" mean "Change"?!? But the only use of "edge" in the EICRA description is "The falling/rising edge of INT1 generates an interrupt request.". And there are TWO 'edge' interrupts... Very confusing.

Errata: There is no "HIGH" external interrupt option. Just RISING, FALLING, CHANGE, and LOW. I misspoke.

PCINT is available for every pin, INT0 and INT1 are additionally available.

In sleep modes with oscillators turned off only level interrupts can be used. Level change interrupts require a running clock, even with INT0/INT1.

DrDiettrich:
PCINT is available for every pin, INT0 and INT1 are additionally available.

In sleep modes with oscillators turned off only level interrupts can be used. Level change interrupts require a running clock, even with INT0/INT1.

My IR remote using a Pro Mini wakes from power-down sleep (all oscillators off) on a pin change. So the PCINTs do work with no running clock.

DrDiettrich:

Quote from: DrDiettrichIn sleep modes with oscillators turned off only level interrupts can be used. Level change interrupts require a running clock, even with INT0/INT1.

The datasheet is saying it's "only asynchronously detected interrupts" that can be used to wake the processor from sleep modes deeper than Idle.

Page 79: External Interrupts:

"Pin change interrupts on PCINT23...0 are detected asynchronously. This implies that these interrupts can be used for waking the part also from sleep modes other than Idle mode."

"Low level interrupts and the edge interrupt on INT2:0 are detected asynchronously. This implies that these interrupts can be used for waking the part also from sleep modes other than Idle mode."