Arduino instantly going out of sleep mode. But only once ?

Hello. I am currently making my own smart watch, which obviously needs to use as little energy as possible. This is my first time implementing a hardware sleep mode, and I am having a bit of trouble.
After hours of wrong pins and and other small issues, I have gotten it to ALMOST work.
Upon starting, the code is supposed to wait for ten seconds (shortened in code below for debugging), then go into sleep mode, until it wakes up when I interrupt it with a button at pin 3.

This works good so far, but then after the next 10 seconds, it shuts down only for an instant, then is on for ten more seconds, and then it turns off, and remains off until next interrupt.

If I had been caught in a loop, I would know how to debug it, but i am perplexed as to how the bug happens ONCE.

To reinstate:
in sleep mode
Interrupt at pin 3
On for 10 seconds
Sleep for maybe 100-200ms
On for another 10 seconds
sleep mode (until next button-press)

/**************************************************************************
Fish watch OS - created by Iver Iscariot Søbakk, 27-9-23

 **************************************************************************/

#include <SPI.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <DS3232RTC.h>      // https://github.com/JChristensen/DS3232RTC
#include "Arduino.h"
#include <avr/sleep.h>

DS3232RTC RTC;

#include "menuSwitchCase.h"

#define SCREEN_WIDTH     128
#define SCREEN_HEIGHT    64
#define OLED_RESET       A2
#define SCREEN_ADDRESS   0x3D 
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);

#define LOGO_HEIGHT   64
#define LOGO_WIDTH    64
static const unsigned char PROGMEM logo_bmp[] =
{ 0x00, 0x00, 0x00, 0x03, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xff, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xff, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x08, 0x0f, 0xff, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x1f, 0xff, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x7f, 0xff, 0xfe, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x01, 0xff, 0xff, 0xff, 0xff, 0x80, 0x00, 0x00, 0x03, 0xff, 0xff, 0xff, 0xff, 0xc0, 0x00, 0x00, 0x03, 0xff, 0xff, 0xff, 0xff, 0xc0, 0x00, 0x00, 0x07, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x00, 0x00, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xf0, 0x00, 0x00, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xf0, 0x00, 0x00, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x00, 0x00, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x00, 0x00, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x00, 0x00, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x00, 0x00, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xe1, 0xff, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x80, 0x7f, 0x00, 0x01, 0xff, 0xff, 0xff, 0xff, 0x00, 0x3f, 0x80, 0x01, 0xff, 0xff, 0xff, 0xff, 0x00, 0x3f, 0x80, 0x01, 0xff, 0xff, 0xff, 0xfe, 0x00, 0x1f, 0x80, 0x03, 0xff, 0xff, 0xff, 0xfe, 0x00, 0x1f, 0xc0, 0x03, 0xff, 0xff, 0xff, 0xfe, 0x00, 0x1f, 0xc0, 0x03, 0xff, 0xff, 0xff, 0xfe, 0x00, 0x1f, 0xc0, 0x07, 0xff, 0xff, 0xff, 0xff, 0x00, 0x3f, 0xe0, 0x07, 0xff, 0xff, 0xff, 0xff, 0x00, 0x3f, 0xe0, 0x07, 0xff, 0xff, 0xff, 0xff, 0x80, 0x7f, 0xe0, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xe1, 0xff, 0xf0, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x3f, 0xff, 0xfe, 0x03, 0xc0, 0x7f, 0xff, 0xfc, 0x3f, 0xfe, 0x00, 0x03, 0xc0, 0x00, 0x7f, 0xfc, 0x3f, 0xe0, 0x00, 0x03, 0xc0, 0x00, 0x07, 0xfc, 0x3f, 0x00, 0x00, 0x03, 0xc0, 0x00, 0x00, 0xfc, 0x1c, 0x00, 0x00, 0x03, 0xc0, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x03, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0xff, 0xff, 0xf8, 0x00, 0x00, 0x00, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x00, 0x07, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x7f, 0xfc, 0x00, 0x03, 0xc0, 0x00, 0x3f, 0xfe, 0x70, 0x00, 0x00, 0x03, 0xc0, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x03, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0xff, 0xff, 0xf8, 0x00, 0x00, 0x00, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x00, 0x07, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x7f, 0xfc, 0x00, 0x03, 0xc0, 0x00, 0x3f, 0xfe, 0x70, 0x00, 0x00, 0x03, 0xc0, 0x00, 0x00, 0x0e
};


#define BATTERY A0
#define BUZZER 5 
#define MOTOR 9 
#define TOP_BUTTON 4
#define MID_BUTTON 3
#define BOT_BUTTON 2
const int SHORT_PRESS_TIME = 20;
const int LONG_PRESS_TIME = 250; 

int topLastState = LOW;
int topCurrentState;   
int midLastState = LOW;  
int midCurrentState;   
int botLastState = LOW; 
int botCurrentState;     
unsigned long pressedTime  = 0;
unsigned long releasedTime = 0;

int menuIndex = 1;

unsigned long sleepTime = 4000;
unsigned long wokeTime = 0;

void beep(){
  analogWrite(BUZZER, 220);
  digitalWrite(MOTOR, HIGH);
  delay(70);
  analogWrite(BUZZER,LOW);
  delay(70);
  digitalWrite(MOTOR, LOW);
}

void eep() {
    // turn display off
    display.ssd1306_command(SSD1306_DISPLAYOFF);

    // Disable the ADC 
    static byte prevADCSRA = ADCSRA;
    ADCSRA = 0;

    /* Set the type of sleep mode we want. Can be one of (in order of power saving): */

    set_sleep_mode (SLEEP_MODE_PWR_DOWN);
    sleep_enable();

    // Turn of Brown Out Detection (low voltage)
    MCUCR = bit (BODS) | bit (BODSE);

    // The BODS bit is automatically cleared after three clock cycles so we better get on with it
    MCUCR = bit (BODS);

    // Ensure we can wake up again by first disabling interupts (temporarily) so
    // the wakeISR does not run before we are asleep and then prevent interrupts,
    // and then defining the ISR (Interrupt Service Routine) 
    noInterrupts();
    attachInterrupt(digitalPinToInterrupt(MID_BUTTON), sleepISR, HIGH);

    // Send a message just to show we are about to sleep
    Serial.println("Good night!");
    Serial.flush();

    // Allow interrupts now
    interrupts();

    // And enter sleep mode as set above
    sleep_cpu();

    // --------------------------------------------------------
    // µController is now asleep until woken up by an interrupt
    // --------------------------------------------------------

    // Wakes up at this point when wakePin is brought LOW - interrupt routine is run first
    Serial.println("I'm awake!");
    // turn display on
    display.ssd1306_command(SSD1306_DISPLAYON);

    // Re-enable ADC if it was previously running
    ADCSRA = prevADCSRA;

    setSyncProvider(RTC.get);
}

void sleepISR() {
  // Prevent sleep mode, so we don't enter it again, except deliberately, by code
  sleep_disable();

  // Detach the interrupt that brought us out of sleep
  detachInterrupt(digitalPinToInterrupt(MID_BUTTON));
}

void setup() {
  Serial.begin(9600);
  analogReference(INTERNAL);

  ////////////////////// Initialize Clock ////////////////////////////
  RTC.begin();
  setSyncProvider(RTC.get);   // the function to get the time from the RTC

  ////////////// initialize screen //////////////////
  if(!display.begin(SSD1306_SWITCHCAPVCC, SCREEN_ADDRESS)) {
    Serial.println(F("SSD1306 allocation failed"));
    for(;;); // Don't proceed, loop forever
  }

  //////////////// Draw splash screen //////////////
  display.clearDisplay();
  display.drawBitmap( 0, (display.height() - LOGO_HEIGHT) / 2, logo_bmp, LOGO_WIDTH, LOGO_HEIGHT, 1);
  display.setTextSize(1); 
  display.setTextColor(SSD1306_WHITE);
  display.setCursor(64, 5);
  display.println("Fishwatch");
  display.setCursor(64, 15);
  display.setTextSize(2);
  display.println("OS");
  display.display();
  delay(1200);
  
  //////////////// assign pins ///////////////
  pinMode(BATTERY,INPUT);
  pinMode(BUZZER,OUTPUT);
  pinMode(MOTOR,OUTPUT);
  pinMode(TOP_BUTTON,INPUT);
  pinMode(MID_BUTTON,INPUT);
  pinMode(BOT_BUTTON,INPUT);

  //////////////// Start sleep timer /////////////
  wokeTime = millis();
}

void loop() {

  ///////////////////// draw the menu, based on the menu-index //////////////////////////
  drawMenu();
  


  ///////////////////// See if screen has been on for more than the sleeptime variable, and sleep ////////////////////////////////
  if (millis() > wokeTime + sleepTime){  // if its awake, and its been sleeptime milliseconds since it woke
    wokeTime = millis();
    eep();
  }


  /////////////////////////////////// read buttons //////////////////////////////////////////////
  topCurrentState = digitalRead(TOP_BUTTON);
  midCurrentState = digitalRead(MID_BUTTON);
  botCurrentState = digitalRead(BOT_BUTTON);


  if(topLastState == LOW && topCurrentState == HIGH) {
    pressedTime = millis();
  }
  else if(topLastState == HIGH && topCurrentState == LOW) { // button is released
    releasedTime = millis();
    Serial.println("Let go of button");
    
    long pressDuration = releasedTime - pressedTime;
    if(pressDuration > LONG_PRESS_TIME ){}
    else if( pressDuration > SHORT_PRESS_TIME ){}
  }

  topLastState = topCurrentState;
  midLastState = midCurrentState;
  botLastState = botCurrentState;


  delay(5);
}

Which Arduino MCU are you using?

This excellent AVR tutorial on sleep modes and power saving is well worth studying.

I am using an Atmega328P AU

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.