Autonomo / LoRaONE external interrupt and watchdog functionality

Hi All,

I am struggling with external interrupts on my Autonomo.

The goal of my project is to put the Autonomo in power saving mode and only do something at a change of an input and return to low power mode again.

I have the following minimal sketch made:

#define INT1 4

void setup()
{
	delay(10000);
	//Wait until the serial monitor is ready/open
	while (!SerialUSB);
	SerialUSB.println("Starting");

	pinMode(13, OUTPUT);
	digitalWrite(13, LOW);

   	pinMode(INT1, INPUT_PULLUP);
	//Attach the interrupt to RISING event
//	attachInterrupt(INT1, ISR, HIGH);
	attachInterrupt(INT1, ISR, CHANGE);

	EIC->WAKEUP.reg |= (1 << digitalPinToInterrupt(INT1));

	//Set sleep mode
	SCB->SCR |= SCB_SCR_SLEEPDEEP_Msk;

	// Disable USB
	USBDevice.detach();
}

void ISR()
{
	delayMicroseconds(50000);
	digitalWrite(13, LOW);
	delayMicroseconds(50000);
	digitalWrite(13, HIGH);
	delayMicroseconds(50000);
	digitalWrite(13, LOW);
	delayMicroseconds(50000);
	digitalWrite(13, HIGH);
	delayMicroseconds(50000);
	digitalWrite(13, LOW);
}


void loop()
{
	delayMicroseconds(1500000);
	digitalWrite(13, LOW);
	delayMicroseconds(1500000);
	digitalWrite(13, HIGH);


	// SAMD sleep
	__WFI();

	delayMicroseconds(1500000);
	digitalWrite(13, LOW);
	delayMicroseconds(1500000);
	digitalWrite(13, HIGH);

}

I have the following results:

With: attachInterrupt(INT1, ISR, HIGH);

Led flashing fast as long as input is HIGH

Loop wakes up and goes to sleep again.

With: attachInterrupt(INT1, ISR, CHANGE); however, nothing happens: No fast flashing during change of input state, no slow flash on wakeup.

Do I miss something?

Axel

Hi Axel,

There is a small complication when using external interrupts when in sleep mode. In order for the EIC module to detect change events (RISING, FALLING, CHANGE) it requires an active clock signal. In the current setup, the clock source is being shut down when entering sleep mode. Without an active clock source you will only be able to detect HIGH or LOW.

I believe the current clock setup is something like this:
DFLL48M -> GCLK0 -> GCLK_EIC

In order to enable change interrupts, the whole chain of components have to be configured to run in standby. I believe the easiest way to do this would be to configure another GCLK to use the XOSC32K source. Set both the GCLK and the XOSC32K to run in standby and then configure the EIC to source from that new GCLK.

Hi Gabriel,

Thanks for your reply. I understand the problem, however, the solution goes beyond my knowledge.

There is currently no urgent need for this (during the demo the battery will last), but in the future this is a must have.

If there is anybody having a complete sketch, that would be fantastic.

Kind regards,

Axel

Hi again,

In the mean time I bought the LoRaONE and are still facing the same problem which I think is quite common:

I want to put the device in low power mode and wakeup on a change of an I/O port and also wakeup once a day as a kind of watchdog.

This seems to me as a very common use of the Autonomo and LoRaONE, however I can nowhere find a complete working sketch with this functionality.

Who can help me?

Kind regards,

Axel

There is an example here for the Autonomo which will wake the board on a external interrupt:

Note: The modification of the EIC register is no longer required as it is now done in the call to attachInterrupt(), make sure you have the latest core.

For a daily wake up interrupt, I would recommend using the RTC Alarm. You will need to set the hours, minutes and seconds of the alarm. You will also need to use the correct match mask.

A good starting point is this example:

Hello Gabriel,

Thanks for your prompt reply.

I used the sleep interrupt before however, it has the above problem that I can only use the HIGH or LOW event status. This means that it is possible (and in my case that is the actual situation), that the event is HIGH for 24 hours and during that time the interrupt routine is called all the time.

I tried to work around this by using:

detachInterrupt(TEST_PIN);

in my IRQ routine, but the next call in the loop() to:

attachInterrupt(TEST_PIN, ISR, digitalRead(TEST_PIN) ? false : true);

to activate the event on the other level does not work: as long as the level is the same, the same IRQ is received and the IRQ function remains being called all the time until the level changes.

Using the RTC for the watchdog is a good idea. No doubt that will work.

But how to handle the external event as long as RISING, FALLING, CHANGE cannot be used without hacking with the clock?

Axel

To enable level change interrupts, add the following code to your sketch. This code must be added after the first call to attachInterrupt().

// Set the XOSC32K to run in standby
SYSCTRL->XOSC32K.bit.RUNSTDBY = 1;

// Configure EIC to use GCLK1 which uses XOSC32K 
// This has to be done after the first call to attachInterrupt()
GCLK->CLKCTRL.reg = GCLK_CLKCTRL_ID(GCM_EIC) | 
                    GCLK_CLKCTRL_GEN_GCLK1 | 
                    GCLK_CLKCTRL_CLKEN;

This configures the EIC to use the XOSC32K from GCLK1. GCLK1 is configured by the Arduino core to source from XOSC32K with a divider of 1. The XOSC32K source is also configured to stay active when in sleep / standby mode.

I have added an example here:

Hi Gabriel,

IT WORKS!

First try. Great.

Now trying to combine with the RTC event.

Thanks!

Axel