Duff's Snooze Library - Setup Questions

Status
Not open for further replies.
I notice in the _all_wakeups.ino examples, the RTC alarm is used but the RTC is never set with the date and time. I assume it's able to do relative time keeping, such as "wake up in 10s" even if it doesn't know what the current date/time is?

The issue I had using the RTC to wake up is that it would correctly wake up in 15s when I set it for 15s, but then it doesn't process the passage of time while asleep. It'd only move the clock forward by the few seconds when the system was awake. So for example if it spent 9 out of every 10s asleep, the clock would only move forward by 1s for every 10s of real time.

RTC is listed as "Full Functionality" across all sleep modes in the datasheet (table 7.2) so that shouldn't happen in any of the three modes, correct?
 
I notice in the _all_wakeups.ino examples, the RTC alarm is used but the RTC is never set with the date and time. I assume it's able to do relative time keeping, such as "wake up in 10s" even if it doesn't know what the current date/time is?
It uses whatever the RTC hardware time is set to. So even if the time is "wrong" it will still work for waking up.

The issue I had using the RTC to wake up is that it would correctly wake up in 15s when I set it for 15s, but then it doesn't process the passage of time while asleep. It'd only move the clock forward by the few seconds when the system was awake. So for example if it spent 9 out of every 10s asleep, the clock would only move forward by 1s for every 10s of real time.
Yes, if your using the time library you need to resync the time.

RTC is listed as "Full Functionality" across all sleep modes in the datasheet (table 7.2) so that shouldn't happen in any of the three modes, correct?
Yes it works on all power modes.
 
It uses whatever the RTC hardware time is set to. So even if the time is "wrong" it will still work for waking up.


Yes, if your using the time library you need to resync the time.


Yes it works on all power modes.

So you're saying that the RTC will always keep an accurate second-to-second count in all power modes, however it will lose it's state and need to retrieve the actual date/time? The datasheet is misleading because I would have thought that "Full Functionality" in all modes means that it keeps the date/time.
 
So you're saying that the RTC will always keep an accurate second-to-second count in all power modes, however it will lose it's state and need to retrieve the actual date/time? The datasheet is misleading because I would have thought that "Full Functionality" in all modes means that it keeps the date/time.
I'm talking about if you use the Time Library with the Snooze library. Then you have to resync the Time Library to get the correct time when you wakeup, the RTC will work in all power modes and keep the correct time its just the Time library needs to be resynced.
 
I'm talking about if you use the Time Library with the Snooze library. Then you have to resync the Time Library to get the correct time when you wakeup, the RTC will work in all power modes and keep the correct time its just the Time library needs to be resynced.

Ooohhh thank you. This is really helpful. I didn't know I needed to call setSyncProvider(getTeensy3Time); upon wakeup.
 
Hello,
i tried the example "deepsleep-->button_hold_wakeup",i measured 5ma current consumption with the multimeter.
I have nothing connected in this,it's just the teensy board.
Normally consumption should not be less?I use the teensy 3.6.

Code:
#include <Snooze.h>
#include <Bounce.h>

// Load drivers
SnoozeDigital digital;// this is the pin wakeup driver
// configures the lc's 5v data buffer (OUTPUT, LOW) for low power
Snoozelc5vBuffer lc5vBuffer;

// use bounce for pin 13, debounce of 5ms
Bounce button = Bounce(13, 5);

// install driver into SnoozeBlock
#if defined(__MK66FX1M0__) || defined(__MK64FX512__) || defined(__MK20DX256__)
SnoozeBlock config_teensy3x(digital);
#elif defined(__MKL26Z64__)
SnoozeBlock config_teensyLC(digital, lc5vBuffer);
#endif

void setup() {
    // Configure pin 2 for bounce library
    pinMode(13, INPUT_PULLUP);
    // debug led
    pinMode(LED_BUILTIN, OUTPUT);
    while (!Serial);
    delay(100);
    Serial.println("start...");
    delay(20);
    //pin, mode, type
    digital.pinMode(13, INPUT_PULLUP, FALLING);
}

void loop() {
    // if not held for 3 sec go back here to sleep.
SLEEP:
    // you need to update before sleeping.
    button.update();
    
    // returns module that woke processor after waking from low power mode.
#if defined(__MK66FX1M0__) || defined(__MK64FX512__) || defined(__MK20DX256__)
    Snooze.deepSleep( config_teensy3x );
#elif defined(__MKL26Z64__)
    Snooze.deepSleep( config_teensyLC );
#endif
    
    // indicate the button woke it up, hold led high for as long as the button
    // is held down.
    digitalWrite(LED_BUILTIN, HIGH);
    
    elapsedMillis timeout = 0;
    // bounce needs to call update longer than the debounce time = 5ms,
    // which is set in constructor.
    while (timeout < 6) button.update();
    
    // now check for 3 second button hold
    bool awake = threeSecondHold();
    
    // if not held for 3 seconds go back to sleep
    if (!awake) goto SLEEP;
    
    // the button was held for at least 3 seconds if
    // you get here do some stuff for 7 seconds then
    // go to sleep.
    elapsedMillis time = 0;
    
    while (1) {
        unsigned int t = time;
        Serial.printf("doin stuff for: %i milliseconds\n", t);
        
        // back to sleep after 7 seconds
        if (time > 7000) {
            Serial.println("sleeping now :)");
            
            // little delay so serial can finish sending
            delay(5);
            
            goto SLEEP;
        }
        digitalWrite(LED_BUILTIN, HIGH);
        delay(50);
        digitalWrite(LED_BUILTIN, LOW);
        delay(50);
    }
}

bool threeSecondHold() {
    // this is the 3 sec button press check
    while (button.duration() < 3000) {
        
        // get the current pin state, must have this!
        button.update();
        
        // check the pin 2 state, if button not
        // pressed before 3 seconds go back to
        // sleep. We read 0 since pin 2 is
        // configured as INPUT_PULLUP.
        if (button.read() != 0) {
            digitalWrite(LED_BUILTIN, LOW);
            // let go of button before 3 sec up
            return false;
        }
    }
    digitalWrite(LED_BUILTIN, LOW);
    
    // button was held for 3 seconds so now we are awake
    return true;
}
 
Last edited:
Pin 13 is the Teensy’s LED pin. Thus, if you configure this pin as input pull-up, constant parasitic current will flow through the internal pull-up resistor and the LED. Just try any other pin.
 
Does anyone know the mapping between the various low power modes in the Snooze (sleep, deepsleep, hibernate) and the various low power modes (wait mode, very low power run mode, very low power wait mode, stop mode, very low power stop mode, low leakage stop mode, very low leakage stop mode 3, 2, and 1)?

In other words, which modes are utilized by the snooze library?
 
Hello, I'm using the Teensy 3.6 to build an IMU (MPU-9250) data logger and would like it to save power at night by going to sleep. I am using the provided Snooze examples to enter sleep mode based and then want it to wake on the RTC alarm but I am not able to get it to wake again after it goes to sleep. I have the Teensy setup with a coin battery to keep the RTC powered even when my main battery is disconnected and am running the system at 4 MHz to save battery. Do I need to reinitialize the IMU and SD card after sleep mode to make it all work again? In my current code I am testing Snooze by having it sleep when the RTC seconds are >= 30 then hopefully, having it wake again 30 seconds later via the alarm and continue logging. Eventually, I will have it sleep at say 10 pm and then wake 8 hours later. Here is my code for reference:

Code:
/*Teensy 3.6 MPU-9250 Datalogger*/

#include "MPU9250BF.h" //Bolder Flight 9250 Library
#include <TimeLib.h>
#include <SD.h>
#include <SPI.h>
#include <Snooze.h>

// an MPU9250 object with the MPU-9250 sensor on I2C bus 0 with address 0x68
MPU9250BF IMU(Wire,0x68);
int status;

//SnoozeBlock config_teensy36(alarm);
SnoozeAlarm  alarm;
SnoozeBlock config_teensy36(alarm);

// Setup SD Logging parameters
// Chip Select Pin on Teensy 3.6 is Built-in
const int chipSelect = BUILTIN_SDCARD;
char logFileName[11]; //Active logging file
String logFileBuffer; //Buffer to store data before writing to SD card
int SD_MAX_FILE_SIZE = 5000000; // 5MB max file size, increment to next file before surpassing
unsigned int SD_LOG_WRITE_BUFFER_SIZE = 4096; // buffer size to store data before writing to SD card
int LOG_FILE_INDEX_MAX = 9999; //maximum number of log files

void setup()  {

  Serial.begin(115200);
  pinMode(LED_BUILTIN, OUTPUT);
  /********************************************************
  Set RTC alarm wake up in (hours, minutes, seconds).
  ********************************************************/
  alarm.setRtcTimer(0, 0, 30);// hour, min, sec

  // start communication with IMU 
  status = IMU.begin();
  if (status < 0) {
    //Serial.println("IMU initialization unsuccessful");
    //Serial.println("Check IMU wiring or try cycling power");
    //Serial.print("Status: ");
    //Serial.println(status);
    while(1) {}
  }
  // setting the accelerometer full scale range to +/-8G 
  IMU.setAccelRange(MPU9250BF::ACCEL_RANGE_16G);
  // setting the gyroscope full scale range to +/-500 deg/s
  IMU.setGyroRange(MPU9250BF::GYRO_RANGE_2000DPS);
  // setting DLPF bandwidth to 20 Hz
  IMU.setDlpfBandwidth(MPU9250BF::DLPF_BANDWIDTH_20HZ);
  // setting SRD to 19 for a 50 Hz update rate
  IMU.setSrd(19);
  
  // set the Time library to use Teensy 3.0's RTC to keep time
  setSyncProvider(getTeensy3Time);
  if (Serial.available()) {
    time_t t = processSyncMessage();
    if (t != 0) {
      Teensy3Clock.set(t); // set the RTC
      setTime(t);
    }
  }
  
  //Initialize SDCard
  //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:
    return;
  }
  else{
    //Serial.println("card initialized.");
    nextLogFile(logFileName); //initialize new log file after reboot or power cycle
  }
  
}

void loop() {
  
  SensorData(); //check IMU and log data
  //delay(19);

  if (second() >= 30){
    Snooze.sleep(config_teensy36);//Go to Sleep
  }
}

void SensorData(void){

  String Data = "";

  Data += String(hour());
  Data += printDigits(minute());
  Data += printDigits(second());
  Data += String(" ");
  Data += String(day());
  Data += String(" ");
  Data += String(month());
  Data += String(" ");
  Data += String(year()); 
  Data += String(" ");

  IMU.readSensor();
  
  Data += String(IMU.getAccelX_mss(),6) + String(" ");
  Data += String(IMU.getAccelY_mss(),6) + String(" ");
  Data += String(IMU.getAccelZ_mss(),6) + String(" ");
  Data += String(IMU.getGyroX_rads(),6) + String(" ");
  Data += String(IMU.getGyroY_rads(),6) + String(" ");
  Data += String(IMU.getGyroZ_rads(),6);
  Data += "\r\n"; // Add a new line

  // If adding this log line will put us over the buffer length:
  if (Data.length() + logFileBuffer.length() >= SD_LOG_WRITE_BUFFER_SIZE){
    sdLogString(logFileBuffer); // Log SD buffer
    logFileBuffer = ""; // Clear SD log buffer 
    //blinkLED(); // Blink LED every time a new buffer is logged to SD
  }
  // Add new line to SD log buffer
  logFileBuffer += Data;
 // Serial.println(Data);
 // Serial.println(logFileBuffer.size());
}

time_t getTeensy3Time()
{
  return Teensy3Clock.get();
}

/*  code to process time sync messages from the serial port for RTC  */
#define TIME_HEADER  "T"   // Header tag for serial time sync message

unsigned long processSyncMessage() {
  unsigned long pctime = 0L;
  const unsigned long DEFAULT_TIME = 1357041600; // Jan 1 2013 

  if(Serial.find(TIME_HEADER)) {
     pctime = Serial.parseInt();
     return pctime;
     if( pctime < DEFAULT_TIME) { // check the value is a valid time (greater than Jan 1 2013)
       pctime = 0L; // return 0 to indicate that the time is not valid
     }
  }
  return pctime;
}

// Zero Pad the time for minutes and hours < 10
String printDigits(int digits){
  String DigitsOut = "";
  // utility function for digital clock display: prints preceding colon and leading 0
  DigitsOut += ":";
  if(digits<10)
    DigitsOut += "0";
    
  DigitsOut += String(digits);

   return DigitsOut;
}

// Log a string to the SD card
void sdLogString(String toLog)
{
  // Open the current file name:
  File logFile = SD.open(logFileName, FILE_WRITE);
  
  // If the file will get too big with this new string, create
  // a new one, and open it.
  if (logFile.size() > (SD_MAX_FILE_SIZE - toLog.length()))
  {
    nextLogFile(logFileName);
    logFile = SD.open(logFileName, FILE_WRITE);
  }

  // If the log file opened properly, add the string to it.
  if (logFile)
  {
    logFile.print(toLog);
    logFile.close();
  }
}

// Find the next available log file. Or return a null string
// if we've reached the maximum file limit.
void nextLogFile(char logFileName[11])
{
  //char filename[];
  //int logIndex = 0;

  for (int i = 0; i < LOG_FILE_INDEX_MAX; i++){
    sprintf(logFileName, "log%03d.txt", i);
    //Serial.println(logFileName);
    // If the file name doesn't exist, return it
    if (!SD.exists(logFileName))
    {
      break;
      //return filename;
    }
    // Otherwise increment the index, and try again
  }

}
 
Hello, I'm using the Teensy 3.6 to build an IMU (MPU-9250) data logger and would like it to save power at night by going to sleep. I am using the provided Snooze examples to enter sleep mode based and then want it to wake on the RTC alarm but I am not able to get it to wake again after it goes to sleep.
Did you try the examples to see if they worked? Also I have newer version here if you didn't download it already.
 
Duff, thank you for your quick reply!

I didn't try the examples on their own, just took the parts from the examples and integrated them into my code. In any case, I finally got it to work. I had to call 'setSyncProvider(getTeensy3Time);' in my if loop just after the command to sleep (Snooze.sleep(config_teensy36);) as suggested in an earlier post. If the time sync was not called after the sleep command it would try to wake as indicated by the onboard LED that set to blink constantly when awake would only blink once then stay off. I was able to do an overnight test and it worked perfectly; stopped logging at 10 pm and woke promptly at 6 am and started logging again. We'll see how long the battery lasts now given the low power mode overnight.

Thank you for the awesome library!
 
RTC snooze at time

Duff, thank you for your quick reply!

I didn't try the examples on their own, just took the parts from the examples and integrated them into my code. In any case, I finally got it to work. I had to call 'setSyncProvider(getTeensy3Time);' in my if loop just after the command to sleep (Snooze.sleep(config_teensy36);) as suggested in an earlier post. If the time sync was not called after the sleep command it would try to wake as indicated by the onboard LED that set to blink constantly when awake would only blink once then stay off. I was able to do an overnight test and it worked perfectly; stopped logging at 10 pm and woke promptly at 6 am and started logging again. We'll see how long the battery lasts now given the low power mode overnight.

Thank you for the awesome library!

Hello Coreman4,
Can you please explain where in your code is that wake at 6am and go to sleep at 10pm.
Thanks.

Duff's, thanks for share your really nice library.
I have a question/request, in the past you suggest to add some more feature to the RTC snooze, did you ever implement it?
It would be great that I could wake the system at a defined time hh:mm:ss or even at a defined date and time would be very helpful.
Is it possible to configure the next alarm in the loop, or do I have to use always the setup and keep that one?
Thanks.

Tim
 
Tim,

Here is the code as I had it when I finished the project. It's been a while since I worked on it but hopefully, this gives you something to work with.

Code:
#include "MPU9250BF.h" //Bolder Flight 9250 Library
#include <TimeLib.h>
#include <SD.h>
#include <SPI.h>
#include <Snooze.h>

// an MPU9250 object with the MPU-9250 sensor on I2C bus 0 with address 0x68
MPU9250BF IMUW(Wire,0x68);
MPU9250BF IMU(Wire1,0x68);
int status;
unsigned int StartTime = 0;

//Configure Snooze class
SnoozeDigital digital;
SnoozeBlock config_teensy36(digital);

// Setup SD Logging parameters
// Chip Select Pin on Teensy 3.6 is Built-in
const int chipSelect = BUILTIN_SDCARD;
char logFileName[11]; //Active logging file
String logFileBuffer; //Buffer to store data before writing to SD card
int SD_MAX_FILE_SIZE = 10000000; // 5MB max file size, increment to next file before surpassing
unsigned int SD_LOG_WRITE_BUFFER_SIZE = 4096; // buffer size to store data before writing to SD card
int LOG_FILE_INDEX_MAX = 9999; //maximum number of log files

void setup()  {

  Serial.begin(115200);

  // enabling wake on motion low power mode with a threshold of 400 mg and
  // an accelerometer data rate of 15.63 Hz. 
  //IMUW.enableWakeOnMotion(400,MPU9250BF::LP_ACCEL_ODR_15_63HZ);
  
  /********************************************************
  Set RTC alarm wake up in (hours, minutes, seconds).
  ********************************************************/
  //alarm.setRtcTimer(8, 0, 0);// hour, min, sec
  //timer.setTimer(10000);
  digital.pinMode(10, INPUT, CHANGE);

  // start communication with IMU 
  status = IMU.begin();
  if (status < 0) {
    Serial.println("IMU initialization unsuccessful");
    Serial.println("Check IMU wiring or try cycling power");
    Serial.print("Status: ");
    Serial.println(status);
    while(1) {}
  }
  // setting the accelerometer full scale range to +/-8G 
  IMU.setAccelRange(MPU9250BF::ACCEL_RANGE_16G);
  // setting the gyroscope full scale range to +/-500 deg/s
  IMU.setGyroRange(MPU9250BF::GYRO_RANGE_2000DPS);
  // setting DLPF bandwidth to 20 Hz
  IMU.setDlpfBandwidth(MPU9250BF::DLPF_BANDWIDTH_20HZ);
  // setting SRD to 19 for a 50 Hz update rate
  IMU.setSrd(17);
  
  // set the Time library to use Teensy 3.0's RTC to keep time
  setSyncProvider(getTeensy3Time);
  if (Serial.available()) {
    time_t t = processSyncMessage();
    if (t != 0) {
      Teensy3Clock.set(t); // set the RTC
      setTime(t);
    }
  }
  
  //Initialize SDCard
  //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:
    return;
  }
  else{
    //Serial.println("card initialized.");
    nextLogFile(logFileName); //initialize new log file after reboot or power cycle
  }
  
}

void loop() {
  
  SensorData(); //check IMU and log data
  //delay(5);

  //if (hour() >= 22){
    //Snooze.hibernate(config_teensy36);//Go to Sleep
    //setSyncProvider(getTeensy3Time);
  //}
}

void wakeUp(void){
  
  Serial.println("Awake!");
  //setSyncProvider(getTeensy3Time);
}

void SensorData(void){

  String Data = "";

  Data += printDigits(day());
  Data += String("-");
  Data += printDigits(month());
  Data += String("-");
  Data += String(year());
  Data += String(",");
  Data += printDigits(hour());
  Data += String(":");
  Data += printDigits(minute());
  Data += String(":");
  Data += printDigits(second());
  Data += String(" ");

  IMU.readSensor();

  if (abs(IMU.getGyroX_rads()) >= 0.5){
    StartTime = millis();
    //Serial.println(StartTime);
  }
  else if (millis() > StartTime+10000){       
    Serial.println("Sleep");
    Snooze.hibernate(config_teensy36);//Go to Sleep
    setSyncProvider(getTeensy3Time);
    Serial.println("Wake!");
  }
  else{
    //Serial.println(StartTime);
  }
  
  Data += String(IMU.getAccelX_mss(),6) + String(" ");
  Data += String(IMU.getAccelY_mss(),6) + String(" ");
  Data += String(IMU.getAccelZ_mss(),6) + String(" ");
  Data += String(IMU.getGyroX_rads(),6) + String(" ");
  Data += String(IMU.getGyroY_rads(),6) + String(" ");
  Data += String(IMU.getGyroZ_rads(),6);
  Data += "\r\n"; // Add a new line

  // If adding this log line will put us over the buffer length:
  if (Data.length() + logFileBuffer.length() >= SD_LOG_WRITE_BUFFER_SIZE){
    sdLogString(logFileBuffer); // Log SD buffer
    logFileBuffer = ""; // Clear SD log buffer 
    //blinkLED(); // Blink LED every time a new buffer is logged to SD
  }
  // Add new line to SD log buffer
  logFileBuffer += Data;
  Serial.println(Data);
 // Serial.println(logFileBuffer.size());
}

time_t getTeensy3Time()
{
  return Teensy3Clock.get();
}

/*  code to process time sync messages from the serial port for RTC  */
#define TIME_HEADER  "T"   // Header tag for serial time sync message

unsigned long processSyncMessage() {
  unsigned long pctime = 0L;
  const unsigned long DEFAULT_TIME = 1357041600; // Jan 1 2013 

  if(Serial.find(TIME_HEADER)) {
     pctime = Serial.parseInt();
     return pctime;
     if( pctime < DEFAULT_TIME) { // check the value is a valid time (greater than Jan 1 2013)
       pctime = 0L; // return 0 to indicate that the time is not valid
     }
  }
  return pctime;
}

// Zero Pad the time for minutes and hours < 10
String printDigits(int digits){
  String DigitsOut = "";
  // utility function for digital clock display: prints preceding colon and leading 0
  //DigitsOut += ":";
  if(digits<10)
    DigitsOut += "0";
    
  DigitsOut += String(digits);

   return DigitsOut;
}

// Log a string to the SD card
void sdLogString(String toLog)
{
  // Open the current file name:
  File logFile = SD.open(logFileName, FILE_WRITE);
  
  // If the file will get too big with this new string, create
  // a new one, and open it.
  if (logFile.size() > (SD_MAX_FILE_SIZE - toLog.length()))
  {
    nextLogFile(logFileName);
    logFile = SD.open(logFileName, FILE_WRITE);
  }

  // If the log file opened properly, add the string to it.
  if (logFile)
  {
    logFile.print(toLog);
    logFile.close();
  }
}

// Find the next available log file. Or return a null string
// if we've reached the maximum file limit.
void nextLogFile(char logFileName[11])
{
  //char filename[];
  //int logIndex = 0;

  for (int i = 0; i < LOG_FILE_INDEX_MAX; i++){
    sprintf(logFileName, "log%03d.txt", i);
    //Serial.println(logFileName);
    // If the file name doesn't exist, return it
    if (!SD.exists(logFileName))
    {
      break;
      //return filename;
    }
    // Otherwise increment the index, and try again
  }

}
 
Hi coreman4,

Thanks for share your code.
Sorry but I still did not understand how did you implement the aquisition window as most of your code is commented :(
Can you give me some tips?
Thanks.

Tim
 
Tim,

It's been a while since I played with this code so I think this is correct but don't hold me to that:

To set the wake time I used this in the setup():
Code:
alarm.setRtcTimer(8, 0, 0);// hour, min, sec

To put it to sleep I had this in the loop():

Code:
if (hour() >= 22){
    Snooze.hibernate(config_teensy36);//Go to Sleep
    setSyncProvider(getTeensy3Time);
  }

Hopefully, that makes it a little clearer. Let me know if you have any more questions.
 
Status
Not open for further replies.
Back
Top