sleeping w/ Interrupt and knowing which interrupt tripped

Good afternoon everyone.

Hopefully someone can help me on this. Gammoun has a lot of info already on this and I was using the lowpower library for simplicity but now I want to do things that the library doesn't support.

I would like to be able to sleep and have an external interrupt at the same time. I would also like to be able to know which interrupt tripped to wake up the arduino so I can execute the correct code. Any info or links for me to figure this out would be helpful.

Thanks!

You need an interrupt handler for every interrupt. Which type of external interrupt will you be using?

An accelerometer that has an interrupt built into it.

Arduino has two different types of external interrupts: Int0/1 and pin change. Which type will you be using?

Was going to use pin 2/3 on pin change

Then there is no possibility for confusion. You simply include a function to handle the INT0 or INT1 interrupt, and do whatever needs to be done (as quickly as possible).

#include <HID.h>
#include <Wire.h>
#include <SPI.h>
#include <Adafruit_LIS3DH.h>
#include <Adafruit_Sensor.h>
#include "LowPower.h"
#define LIS3DH_CS 10

Adafruit_LIS3DH lis = Adafruit_LIS3DH();
const int wakeUpPin = 3;
bool wakeUpPresence = false;
#define CLICKTHRESHHOLD 5

void wakeUp(){
 wakeUpPresence = true;
 Serial.println("IRQ trip");
  }

void setup(void) {
    lis.begin(0x19);  
    lis.setRange(LIS3DH_RANGE_2_G);   // 2, 4, 8 or 16 G!
    lis.setDataRate(LIS3DH_DATARATE_50_HZ);
    lis.setClick(1, CLICKTHRESHHOLD);
    
   pinMode(wakeUpPin, INPUT);  
   pinMode(13, OUTPUT);
   digitalWrite(13, LOW);
   attachInterrupt(1, wakeUp, HIGH);
}


void loop()
{
    LowPower.powerDown(SLEEP_8S, ADC_OFF, BOD_OFF); 
    delay(10);
    if(wakeUpPresence == true){
      
    digitalWrite(13, HIGH);
    delay(250);
    digitalWrite(13, LOW);
    delay(250);
  }
   wakeUpPresence = false;
   delay(10);
}

I think I got it now, the function within “wakeUp” happens really quickly and does not listen to “delay” for some reason. Doesn’t really matter for my simulation though.

Thanks!

Serial.println("IRQ trip");

You should never attempt to print or use a delay in an interrupt routine, it can cause the Arduino to freeze. Do the minimum required and exit.

If the interrupt is used to trigger a print or do something else that takes significant time, within the interrupt set a global variable as a flag, then exit.

All global variables used in interrupts must be declared as volatile, for example

volatile int print_flag = 0;
void setup() {
...
}

As above ^

Set a boolean flag and have your main() listen for it.

Yup! I noticed that and now flip a bool and exit. Interesting stuff! :)

So one thing I am having an issue one, I dont want the interrupt function to be called unless the interrupt function is tripped.

Here is an example:

#include <HID.h>
#include <Wire.h>
#include <SPI.h>
#include <Adafruit_LIS3DH.h>
#include <Adafruit_Sensor.h>
#include "LowPower.h"
#define LIS3DH_CS 10

Adafruit_LIS3DH lis = Adafruit_LIS3DH();
const int wakeUpPin = 3;
bool wakeUpPresence = false;
#define CLICKTHRESHHOLD 5

void wakeUp(){
 wakeUpPresence = true;
  }

void setup(void) {
    lis.begin(0x19);  
    lis.setRange(LIS3DH_RANGE_2_G);   // 2, 4, 8 or 16 G!
    lis.setDataRate(LIS3DH_DATARATE_50_HZ);
    lis.setClick(1, CLICKTHRESHHOLD);
    
   pinMode(wakeUpPin, INPUT);  
   pinMode(13, OUTPUT);
   pinMode(10, OUTPUT);
   digitalWrite(13, LOW);
     digitalWrite(10, LOW);  
}


void loop()
{
     attachInterrupt(1, wakeUp, HIGH); 
    LowPower.powerDown(SLEEP_4S, ADC_OFF, BOD_OFF); 
    delay(10);
   // detachInterrupt(1);
    digitalWrite(10, HIGH);
    delay(250);
    digitalWrite(10, LOW);
    delay(250);
    
    if(wakeUpPresence == true){
      
    digitalWrite(13, HIGH);
    delay(250);
    digitalWrite(13, LOW);
    delay(250);
    wakeUpPresence = false;
  }
   delay(10);
}

If I put the attachInterrupt in the loop, then it calls the function wakeUp and wakeUpPresence is true; I would like to attach the interrupt and de-attach it without always flipping that bit. Any ideals?

To be more specific, when you trip the interrupt once, it blinks both leds. Good. When it goes through the loop one more time, it blinks both colors AGAIN even though it has not been tripped. Then it blinks only 1 color through the loop like it should.

Diagnosing this, it seems the issue happens only when detachInterrupt(1); is in the code. Any way to detach and attach an Interrupt without it firing?

brolly759:
Diagnosing this, it seems the issue happens only when detachInterrupt(1); is in the code. Any way to detach and attach an Interrupt without it firing?

Which arduino are you using? Ensure you are using the correct pins.

Your code does not make full sense either…

You have the arduino attaching an interrupt, then sleeping for 4s and then detaching the interrupt (why?).

I think you need to figure what you want to do, then on paper, write the steps logically before trying to write the code.

Because I want to sleep and have an external interrupt... To save power. I have an Atemga 328P 8Mhz.

I am testing code right now. Ultimately what I want to do is sleep for a total of 30 seconds. During that time, I only want the interrupt to trip once or twice. Not as many times as it trips, then after 30 seconds, it resets the interrupt and go again. This is to keep the current usage as low as possible.

The arduino is a custom board I made using D3 and an interrupt.

D3 is pin 3. Why are you trying to disable the interrupt on pin 1? Pin 1 is the Serial Tx pin...not an interrupt pin.

|500x235

The code for attaching and detaching an interrupt on INT0 would be:

attachInterrupt(digitalPinToInterrupt(2), blink, HIGH);
detachInterrupt(digitalPinToInterrupt(2));

PS, why are there just random delay()s?

You code should essentially resemble:

main(){
while (!interrupt){ sleep()}  // While the boolean flag is false...keep going back to sleep.
interrupt = false;               // If the flag has been made true...flip it back to flase...
...do stuff...                      // Now do the stuff you want to do...then the main() repeats.

Sorry for multiposting.

If you want, you could increment a byte (a number) on each interrupt.

if (number_of_interruptions > 1){
number_of_interruptions = 0;
sleep(30seconds);
}

attachInterrupt(interrupt, ISR, mode);

1 means interrupt 1 which is pin 3. Interrupt 0 is pin 2. Nothing wrong with the numbering. The problem is that for some reason when the interrupt is tripped and I want to disable and re-enable the interrupt, it runs the function I pass into it once.