Feather M0: Deepsleep and Interrupt from a Reedsensor

Hi guys,

I´ve got the following project:
I wan´t to measure the time of door openings. I use an adafruit feather m0 with a battery, a rtc for getting the right timestamp and a reedsensor to detect the doors status (closed door: open reedsensor/ no energy consumption). To expand the runtime I put the feather in deepsleep mode and wake it with an Interrupt (CHANGE).
When the door is opened a timestamp is set and when the door is closed again a second timestamp is set and the opening time is written to a sd card.

Problems:
The main problem is that the feather sometimes missmatches the two states (opened/closed). I thought about having two interrupts (rising edge = open, falling edge= closed)…

The second problem is that it stops the code at a certain point so that I have to open the serial monitor to continue.

This is my code:

///// RTC /////
// Date and time functions using a DS3231 RTC connected via I2C and Wire lib
#include "RTClib.h"
RTC_DS3231 rtc;
char daysOfTheWeek[7][12] = {"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"};

///// SD /////
#include <SPI.h>
#include <SD.h>

const int chipSelect = 4;

bool startstatus = false;
int starttime = 0;
int endtime = 0;


///// SLEEP / INTERRUPT /////
#define interruptPin 6
volatile bool SLEEP_FLAG;

void EIC_ISR(void) {
  SLEEP_FLAG ^= true;  // toggle SLEEP_FLAG by XORing it against true / ^ exklusiv oder
}

void setup() {
  ///// RTC /////
  #ifndef ESP8266
    while (!Serial); // for Leonardo/Micro/Zero
  #endif

  Serial.begin(9600);
  delay(3000); // wait for console opening

  ///// RTC /////
  if (! rtc.begin()) {
    Serial.println("Couldn't find RTC");                                                                                                    
    while (1);
  }

  if (rtc.lostPower()) {
    Serial.println("RTC lost power, lets set the time!");                                                                                   
    // If the RTC have lost power it will sets the RTC to the date & time this sketch was compiled in the following line
    rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));
  }

  ///// SD CARD ///// only for maintenance purpose
  Serial.print("Initializing SD card...");                                                                                                  

  // see if the card is present and can be initialized:
  if (!SD.begin(chipSelect)) {
    Serial.println("Card failed, or not present");                                                                                          
    // don't do anything more:
    while (1);
  }
  Serial.println("card initialized.");                                                                                                      

  ///// DEEP-SLEEPY INTERUPT /////
  attachInterrupt(digitalPinToInterrupt(interruptPin), EIC_ISR, FALLING);  // Attach interrupt to pin 6 with an ISR and when the pin state CHANGEs

  // Configure the external crystal
  SYSCTRL->XOSC32K.reg |=  (SYSCTRL_XOSC32K_RUNSTDBY | SYSCTRL_XOSC32K_ONDEMAND); // set external 32k oscillator to run when idle or sleep mode is chosen
  REG_GCLK_CLKCTRL  |= GCLK_CLKCTRL_ID(GCM_EIC) |  // generic clock multiplexer id for the external interrupt controller
                       GCLK_CLKCTRL_GEN_GCLK1 |  // generic clock 1 which is xosc32k
                       GCLK_CLKCTRL_CLKEN;       // enable it
  while (GCLK->STATUS.bit.SYNCBUSY);              // write protected, wait for sync

  EIC->WAKEUP.reg |= EIC_WAKEUP_WAKEUPEN4;        // Set External Interrupt Controller to use channel 4 (pin 6)


  PM->SLEEP.reg |= PM_SLEEP_IDLE_CPU;  // Enable Idle0 mode - sleep CPU clock only
  //PM->SLEEP.reg |= PM_SLEEP_IDLE_AHB; // Idle1 - sleep CPU and AHB clocks
  //PM->SLEEP.reg |= PM_SLEEP_IDLE_APB; // Idle2 - sleep CPU, AHB, and APB clocks

  // It is either Idle mode or Standby mode, not both.
  SCB->SCR |= SCB_SCR_SLEEPDEEP_Msk;   // Enable Standby or "deep sleep" mode

  SLEEP_FLAG = false; // begin awake

  // Built-in LED set to output and high
  PORT->Group[g_APinDescription[LED_BUILTIN].ulPort].DIRSET.reg = (uint32_t)(1<<g_APinDescription[LED_BUILTIN].ulPin);  // set pin direction to output
  PORT->Group[g_APinDescription[LED_BUILTIN].ulPort].OUTSET.reg = (uint32_t)(1<<g_APinDescription[LED_BUILTIN].ulPin); // set pin mode to high

}

void loop() {
  DateTime now = rtc.now();
  ///// SLEEP / INTERRUPT /////
  if (SLEEP_FLAG == true) {
    PORT->Group[g_APinDescription[LED_BUILTIN].ulPort].OUTCLR.reg = (uint32_t)(1<<g_APinDescription[LED_BUILTIN].ulPin); // set pin mode to low
    Serial.println("I'm going to sleep now.");                                                                                                //

    ///// SD /////
    startstatus = true;
    endtime = now.unixtime();
    String dataString = "Start: " + String(starttime) + "Endtime: " + String(endtime) + "Opentime: " + String(endtime-starttime);
    File dataFile = SD.open("I1_S1.csv", FILE_WRITE);

    // if the file is available, write to it:
    if (dataFile) {
      dataFile.println(dataString);
      dataFile.close();
      // print to the serial port too:
      Serial.println(dataString);                                                                                                             //
    }
    // if the file isn't open, pop up an error:
     else {                                                                                                                                    //
       Serial.println("error opening csv-File");
     }

      __WFI();  // wake from interrupt
     SLEEP_FLAG = false;
     Serial.println("Ok, I'm awake");                                                                                                           //
     Serial.println();
  }

  ///// RTC /////
  if (startstatus == true) {
    starttime = now.unixtime();
    startstatus = false;
  }

  PORT->Group[g_APinDescription[LED_BUILTIN].ulPort].OUTTGL.reg = (uint32_t)(1<<g_APinDescription[LED_BUILTIN].ulPin);  // toggle output of built-in LED pin
  delay(1000);

}

Thanks!

1 Like