Hello, I am using an Autonomo board (similar to Arduino Zero) and I am encountering some behaviour I am unable to understand.
I am trying to make an application that is extremely low power, so I am using the deep sleep function of the SAMD21 to make the microprocessor sleep.
To wakeup my board I am using a few interrupts (internal and external). These interrupts each set a flag that I check for in my main loop.
These flags make sure my program does something in my main loop, one of which is detach the interrupts.
Here is the code I am currently using:
#include <DHT.h>
#include <Sodaq_RN2483.h>
#include <RTCZero.h>
#define DeurPIN 0
#define DHTpin 4
#define PirPin 10
#define LedGroen 13
RTCZero rtc;
bool led = false;
bool deurGeopend = false;
bool deurDetectie = false;
bool bewegingPIR = false;
bool pirDetectie = false;
uint8_t PIRCount = 0;
unsigned long msNieuwDeur = 0;
unsigned long msOudDeur = 0;
void setup()
{
//Definieer pin 0, 4 en 10 als input, LED pin als output
pinMode(DeurPIN, INPUT);
pinMode(PirPin, INPUT);
pinMode(DHTpin, INPUT);
pinMode(LedGroen, OUTPUT);
attachInterrupt(DeurPIN, ISRdeur, FALLING); //activeer ISR wanneer de deur opent
attachInterrupt(PirPin, ISRbeweging, RISING); //activeer ISR wanneer er beweging wordt gedetecteert
//activeer ISR eens per minuut
rtc.begin();
rtc.setAlarmSeconds(10);
rtc.enableAlarm(RTCZero::MATCH_SS); // alarm eens per minuut
rtc.attachInterrupt(ISR60min); // attach een interrupt aan het RTC alarm
//Set sleep mode
SCB->SCR |= SCB_SCR_SLEEPDEEP_Msk;
// 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;
//Start delay of 5s to allow for new upload after reset
delay(5000);
}
/* ******************************
* *
Interrupts
* *
* ******************************/
void ISRdeur()
{
msOudDeur = millis();
deurDetectie = true;
digitalWrite(13, HIGH);
delayMicroseconds(100000);
digitalWrite(13, LOW);
}
void ISRbeweging()
{
pirDetectie = true;
PIRCount ++;
SerialUSB.println("PIRCount =" + PIRCount);
digitalWrite(13, HIGH);
delayMicroseconds(100000);
digitalWrite(13, LOW);
}
void ISR60min()
{
led = true;
DHTmeting = true;
}
/* ******************************
* *
main programma
* *
* ******************************/
void loop()
{
msNieuwDeur = millis();
/* ******************************
Deurdetectie
* ******************************/
if ((deurDetectie) and ((unsigned long)(msNieuwDeur - msOudDeur) >= 1000))
{
deurDetectie = false;
digitalWrite(13, HIGH);
delayMicroseconds(2000000);
digitalWrite(13, LOW);
if (not digitalRead(DeurPIN))
{
detachInterrupt(DeurPIN);
SerialUSB.println("Deur geopend");
deurGeopend = true;
}
}
/* ******************************
Bewegingdetectie
* ******************************/
if (PIRCount >= 5)
{
PIRCount = 0;
digitalWrite(13, HIGH);
delayMicroseconds(2000000);
digitalWrite(13, LOW);
detachInterrupt(PirPin);
SerialUSB.println("Beweging gedetecteerd");
bewegingPIR = true;
}
if (led == true)
{
led = false;
attachInterrupt(DeurPIN, ISRdeur, FALLING);
attachInterrupt(PirPin, ISRbeweging, RISING);
//Blink the LED for 0,5s
digitalWrite(13, HIGH);
delayMicroseconds(500000);
digitalWrite(13, LOW);
}
if (not deurDetectie)
{
//Disable USB
USB->DEVICE.CTRLA.reg &= ~USB_CTRLA_ENABLE;
//Enter sleep mode
__WFI();
//...Sleep
//Enable USB
USB->DEVICE.CTRLA.reg |= USB_CTRLA_ENABLE;
}
}
Currently I am using a 60 second alarm to periodically wakeup my board and reattach my interrupts. The behaviour I am currently encountering is that even if the board executes the printline “Beweging gedetecteerd” (So I assume it also executed the detach interrupt) it will still print the line “PIRCount = [pircount]” whenever the other external interrupt is handled.
How is that possible?