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!