How to use a HIGH or LOW interrupt mode

Hello, I'm trying to figure out how to get my code to awake from external interrupt while in a low power sleep standby state.

It appears that I can trigger interrupts using only a HIGH or LOW trigger mode when waking from sleep. (Does this sound right?)

If I am correct how do people use interrupts that are triggered by a 'HIGH' or 'LOW' state. It seems to me that what ever triggered the state would probably stay HIGH or LOW much longer than the interrupt routine, causing the routine to continually execute until the status changed.

Is it possible to simply call 'detachInterrupt(pin)' from within the Interrupt routine so that the routine can't continue to execute?

well there are many ways to trigger (HIGH only on the due)

  • LOW to trigger the interrupt whenever the pin is low,
  • CHANGE to trigger the interrupt whenever the pin changes value
  • RISING to trigger when the pin goes from low to high,
  • FALLING for when the pin goes from high to low.

if you use LOW interrupt mode, then indeed the interrupt repeatedly triggers as long as you are in the LOW state. Not that an interrupt at a given level can’t be interrupted by an interrupt at the same level so you are sure your interrupt code will execute (unless a higher level interrupt occurs)

if you don’t want this behavior, then trigger the interrupt only on RISING or FALLING or CHANGE.

and make sure you debounce.

you could also of course remember that you already treated that LOW in the ISR and only activate your code if something else in your code has seen the pin go high again.

Mask the interrupt via its interrupt mask bit, or make the external hardware raise the pin again before leaving the ISR. Detaching makes it harder to rearm.

How do I 'mask' the interrupt pin? I think that would work perfectly.

J-M-L Ideally I'd be able to use RISING, FALLING or CHANGE to catch the interrupt. However, I can't seem to get them to work to get the tag to wake up from sleep. Unless I set a standby clock... However, using the standby clock seems to eliminate all of my power savings by going to sleep in the first place (I see about 1.3mA in sleep mode, 6mA with the clock enabled during sleep and 7mA fully powered.

what's your hardware exactly?

also you are correct - other than in active mode the external interrupt pins can only detect a LOW level but not a rising or falling edge. This means that a interrupt is triggered whenever the signal is LOW, e. g. directly after the interrupt is detected and thus you need to

detachInterrupt (0);

Do I detach the interrupt from within the interrupt routine? Or should it be the first line of code after setting the standby mode?

The hardware is an Adalogger M0

fore4runner: How do I 'mask' the interrupt pin? I think that would work perfectly.

What does the datasheet of the processor tell you?

I don't even know which processor you are using.

For ATmega48A/PA/88A/PA/168A/PA/328/P: |500x275

I think I'm starting to follow what your saying. The processor is the SAMD21 and from page 369 of the datasheet it say that " Each interrupt, except NMI, can be individually enabled by setting the corresponding bit in the Interrupt Enable Set register (INTENSET=1), and disabled by setting the corresponding bit in the Interrupt Enable Clear register (INTENCLR=1)."

|500x219

I still have no idea how to set these registers from the Arduino environment, but I think I'm heading in the right direction

When I look at the Low power mode libraries I see a lot of references to functions like:

GCLK->STATUS.reg & GCLK_STATUS_SYNCBUSY

or

SCB->SCR |= SCB_SCR_SLEEPDEEP_Msk;

I recognize the SLEEPDEEP_Msk and SYNCBUSY terms from the data sheet, but I don't know how to track down what command I need to use to do something like: INTENCLR(6) = 1;

Sorry, I don't have any experience with the Zero or similar systems.

Anyway, masking the interrupt after detection seems to me the best way to handle level interrupts.

Thanks though, it definitely seems like you pointed me in the right direction. I might end up posting in the Arduino Zero forum here, as setting register values on the Zero seems a bit off topic from this post's title.