ESP32 timed Light sleep + momentary wake up with button

Hi, I am trying to add some power saving features to a program running on a Lilygo T-Watch 2021 (ESP32 based).
I have a loop where the controller perform some actions based on a timer, but most of the time it has nothing to do, so I would like it to go into light sleep (I ruled out deep sleep for the moment), and I am telling it to keep the display backlight always off except for 10 seconds intervals when I push a button if I want to check the screen.
However I am having trouble writing the code that puts the processor to sleep with a timed wakeup, and embedding a momentary 10 sec wakeup if I push a button, without "losing" the timed wakeup.

This is the part of my code where the problem is:
pin 21 is the display backlight
pin 34 is the button I want to use for 10 sec wakeup
go_buzz 1 is the variable that stores the time when the first action has to happen.

/* set start time for first time (only once)  */ 
  if (!already_set_start_time)
  {
    start_time = millis();
    already_set_start_time = true;
  }
  /* updated at every loop */ 
  timer = millis() - start_time;

  /* all the next ifs are checked at every loop and the program stays some loops in each of them based on timer */ 
  if (timer < go_buzz_1 && !already_slept_1) 
  {
    Serial.println("sleep1");
    digitalWrite(21, LOW);
    esp_sleep_enable_timer_wakeup(go_buzz_1*1000);
    esp_sleep_enable_ext0_wakeup(GPIO_NUM_34, LOW); // 21 AGO
    esp_light_sleep_start();
    if (ESP_SLEEP_WAKEUP_EXT0) 
    {
      digitalWrite(21, HIGH);
      Serial.println("Waken up from first sleep");
      delay(10000);
      Serial.println("Going back to first sleep");
      digitalWrite(21, LOW); 
      esp_light_sleep_start();
    } 
    already_slept_1 = true; 
    digitalWrite(21, HIGH);
    Serial.println("slept1");
  }

What I get from my serial monitor is the following, without me pressing any button:
sleep1
Waken up from first sleep
Going back to first sleep
slept1

Any idea of where the problem could be?
Thanks in advance
Angelo

Most likely the problem is outside that part of the code that you have posted.

Please post the complete sketch. From the very first to the very last line of code. In 80% of all cases the bug is outside the suspected part of the code.
Additional for a real analysis of your code all the variable declarations etc. are nescessary. This is the reason why you should post your complete sketch.
It doesn't matter if your sketch is 3000 lines long. Just post the entire sketch.

best regards Stefan

1 Like

Ok got it, here is the complete code. There are other parts that don't seem to work, probably all related:

  • the buzzer never goes off
  • also the second light sleep doesn't work: it enters it and then exits if I push the button to see the screen.
    I suspect part of the issue is that when I press the button to show the display, instead of going back to the timed sleep after the 10second delay, it doesn't remember the timer because that instruction was given before...
#include <lvgl.h>
#include "ui.h"
#include <Wire.h> 
#include "pcf8563.h" 

PCF8563_Class rtc; 

#include <Arduino_GFX_Library.h>

/************************************************************************************************************************************
 * GFX setting
 ************************************************************************************************************************************/

#define GFX_BL 21 // default backlight pin, you may replace DF_GFX_BL to actual backlight pin

/* More dev device declaration: https://github.com/moononournation/Arduino_GFX/wiki/Dev-Device-Declaration */
#if defined(DISPLAY_DEV_KIT)
Arduino_GFX *gfx = create_default_Arduino_GFX();
#else /* !defined(DISPLAY_DEV_KIT) */

/* More data bus class: https://github.com/moononournation/Arduino_GFX/wiki/Data-Bus-Class */
Arduino_DataBus *bus = new Arduino_ESP32SPI(19 /* DC */, 15 /* CS */, 14 /* SCK */, 13 /* MOSI */, GFX_NOT_DEFINED /* MISO */);

/* More display class: https://github.com/moononournation/Arduino_GFX/wiki/Display-Class */
Arduino_GFX *gfx = new Arduino_GC9A01(bus, 27 /* RST */, 0 /* rotation */, true /* IPS */);

#endif /* !defined(DISPLAY_DEV_KIT) */

/* Change to your screen resolution */
static uint32_t screenWidth;
static uint32_t screenHeight;
static lv_disp_draw_buf_t draw_buf;
static lv_color_t *disp_draw_buf;
static lv_disp_drv_t disp_drv;

/* Display flushing */
void my_disp_flush(lv_disp_drv_t *disp, const lv_area_t *area, lv_color_t *color_p)
{
  uint32_t w = (area->x2 - area->x1 + 1);
  uint32_t h = (area->y2 - area->y1 + 1);

#if (LV_COLOR_16_SWAP != 0)
  gfx->draw16bitBeRGBBitmap(area->x1, area->y1, (uint16_t *)&color_p->full, w, h);
#else
  gfx->draw16bitRGBBitmap(area->x1, area->y1, (uint16_t *)&color_p->full, w, h);
#endif

  lv_disp_flush_ready(disp);
}

/************************************************************************************************************************************
 * End GFX
 ************************************************************************************************************************************/

/* Define variable for buzzer timer  */ 
long go_buzz_1;  
long end_buzz_1; 
long go_buzz_2;  
long end_buzz_2; 
long go_buzz_3;  
long end_buzz_3; 
long go_buzz_4;  
long end_buzz_4; 
long delta;      
long start_time; 
long timer;       

/* convert time into seconds  */
int32_t secondsFromHoursMinutes(const char* from) {
return (atoi(from) * 60L + atoi(from + 3)) * 60;
}

/*  FLAGS  */
bool already_synced = false; 
bool already_set_start_time = false; 
bool already_slept_1 = false;
bool already_slept_2 = false;

void setup()
{
  Serial.begin(115200);
  
  /*********************************** BEGIN GFX (?) STUFF in SETUP **********************************************/ 

#ifdef GFX_EXTRA_PRE_INIT
  GFX_EXTRA_PRE_INIT();
#endif

  // Init Display
  if (!gfx->begin())
  {
    Serial.println("gfx->begin() failed!");
  }
  gfx->fillScreen(BLACK);

#ifdef GFX_BL
  pinMode(GFX_BL, OUTPUT);
  digitalWrite(GFX_BL, HIGH);
#endif

  lv_init();

  screenWidth = gfx->width();
  screenHeight = gfx->height();
#ifdef ESP32
  disp_draw_buf = (lv_color_t *)heap_caps_malloc(sizeof(lv_color_t) * screenWidth * 40, MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT);
#else
  disp_draw_buf = (lv_color_t *)malloc(sizeof(lv_color_t) * screenWidth * 40);
#endif
  if (!disp_draw_buf)
  {
    Serial.println("LVGL disp_draw_buf allocate failed!");
  }
  else
  {
    lv_disp_draw_buf_init(&draw_buf, disp_draw_buf, NULL, screenWidth * 40);

    /* Initialize the display */
    lv_disp_drv_init(&disp_drv);
    /* Change the following line to your display resolution */
    disp_drv.hor_res = screenWidth;
    disp_drv.ver_res = screenHeight;
    disp_drv.flush_cb = my_disp_flush;
    disp_drv.draw_buf = &draw_buf;
    lv_disp_drv_register(&disp_drv);

    /* Initialize the (dummy) input device driver */
    static lv_indev_drv_t indev_drv;
    lv_indev_drv_init(&indev_drv);
    indev_drv.type = LV_INDEV_TYPE_POINTER;
    lv_indev_drv_register(&indev_drv);

  }
  /* *************************************** END GFX (?) STUFF in SETUP *******************************************/

  /* initialize Squareline Studio UI */
  ui_init();

  Serial.println("Setup done");
  
  /* INITIALIZE RTC */
  Wire.begin(26, 25);   
  rtc.begin();  
  // rtc.setDateTime(2023, 8, 17, 02, 33, 00);  // commented out to hold time
  
  /* Sets motot pin as output and btn2 and 3 as input */
  pinMode(4, OUTPUT);
  pinMode(34, INPUT_PULLUP); // if commented out, input always low (not sure why, but tested)
  pinMode(35, INPUT_PULLUP); // if commented out, input always low (not sure why, but tested)
    
  /* SETS RANDOM TIMER */ 
  randomSeed(analogRead(17));  // DA PINOUT IL 17 SEMBRA NON USATO
  go_buzz_1 = random(1000, 836000); // 900.000ms - (4.000ms buzz cycle + 60.000ms wait for input) 
  end_buzz_1 = go_buzz_1 + 500;
  go_buzz_2 = go_buzz_1 + 1500;
  end_buzz_2 = go_buzz_1 + 2000;
  go_buzz_3 = go_buzz_1 + 2500;
  end_buzz_3 = go_buzz_1 + 3000;
  go_buzz_4 = go_buzz_1 + 3500;
  end_buzz_4 = go_buzz_1 + 4000;

  delta = 900000 - (end_buzz_4 + 60000); // wait 60sec for input after end of buzzes

  /* start_time = millis();  // definisce start time come il tempo attuale - no qui perché all'inizio del loop c'è un ritardo, 
  quindi se ad esempio parte alle 2010, start time sarà uguale ai millis delle 2010, poi però aspetta 5' per arrivare alle 2015, 
  quando parte il loop setta timer = millis - start time che è non quello presente ma quello di cinque minuti prima, quindi timer è 
  come se partisse alle 2010 e non alle 2015. Come se non avesse fatto il delay*/

  /*  PRINTS TO MONITOR CODE  */ 
  Serial.println("go_buzz_1:");
  Serial.println(go_buzz_1);
  Serial.println("rtc:");
  Serial.println(rtc.formatDateTime(PCF_TIMEFORMAT_HM));
  Serial.println("atoi:");
  Serial.println(atoi(rtc.formatDateTime(PCF_TIMEFORMAT_HM))); // TO CHECK TIME CONVERSION TO SEC
  Serial.println("atoi+3:");
  Serial.println(atoi(rtc.formatDateTime(PCF_TIMEFORMAT_HM) +3)); // TO CHECK TIME CONVERSION TO SEC
  // Serial.println(time_seconds);  // TO CHECK TIME CONVERSION TO SEC non si può mettere qui perche dichiarato dopo e se la fai global crash

  /* DISPLAY ALWAYS OFF EXCEPT WHEN BUTTON PRESSED - 21 AGO*/ 
  digitalWrite(21, LOW); // 21 AGO 
}

void loop()
{
  
  lv_timer_handler(); /* let the GUI do its work */
  delay(5);

  /* PRINTS TIME ON CENTRAL LABEL  */
  lv_label_set_text(ui_Label14, rtc.formatDateTime(PCF_TIMEFORMAT_HM));
  

  /* TURN ON SCREEN WITH BUTTON */ 
  if (digitalRead(34) == LOW)  
  { 
    digitalWrite(21, HIGH);
    Serial.println("Screen on from button (not sleeping)");
    delay(10000); // VERIFY THAT DELAY DOESN'T MESS UP COUNTERS...
    digitalWrite(21, LOW); 
  }

  /* POINTER TO LVGL ARC WIDGET */ 
  lv_obj_t * *ui_Arc_pointer;  

  /* Define variable to convert RTC time in seconds iot compare and assign 15' window
  needs to be defined in loop because value changes continuously with passing of time, as 
  shown by pointer to arc changing   */ 
  uint32_t time_seconds = secondsFromHoursMinutes(rtc.formatDateTime(PCF_TIMEFORMAT_HM)); 
  

   /* define time to wait iot sync to whole quarter  */ 
  int wait_to_sync (900 - (time_seconds % 900)); // seconds remaining to first whole quarter hour - sempre multipli di 60 perché secondsfromhourminutes parte da HM
  
  /* syncing to whole quarter. Only once every program run (flag) */ 
  if (!already_synced) 
  {
    Serial.println("time_seconds:");
    Serial.println(time_seconds);
    Serial.println("waiting:");
    Serial.println(wait_to_sync);
    delay(wait_to_sync*1000);
    Serial.println("synced to whole quarter");
    already_synced = true;
  }

  /* compare time_seconds and associate pointer to lvgl arc - to be done continuously */ 

  if (time_seconds >= 12*60*60) time_seconds = (time_seconds-12*60*60); // convert time to 12h
  if (time_seconds < 15*60) ui_Arc_pointer=&ui_Arc2; // store ui_Arc2 address into pointer
  else if (time_seconds < 30*60) ui_Arc_pointer=&ui_Arc1;  
  else if (time_seconds < 45*60) ui_Arc_pointer=&ui_Arc3;
  else if (time_seconds < 60*60) ui_Arc_pointer=&ui_Arc4;
  else if (time_seconds < 75*60) ui_Arc_pointer=&ui_Arc5;
  else if (time_seconds < 90*60) ui_Arc_pointer=&ui_Arc6;
  else if (time_seconds < 105*60) ui_Arc_pointer=&ui_Arc7;
  else if (time_seconds < 120*60) ui_Arc_pointer=&ui_Arc8;
  else if (time_seconds < 135*60) ui_Arc_pointer=&ui_Arc9;
  else if (time_seconds < 150*60) ui_Arc_pointer=&ui_Arc10;
  else if (time_seconds < 165*60) ui_Arc_pointer=&ui_Arc11;
  else if (time_seconds < 180*60) ui_Arc_pointer=&ui_Arc12;
  else if (time_seconds < 195*60) ui_Arc_pointer=&ui_Arc13;
  else if (time_seconds < 210*60) ui_Arc_pointer=&ui_Arc14;
  else if (time_seconds < 225*60) ui_Arc_pointer=&ui_Arc15;
  else if (time_seconds < 240*60) ui_Arc_pointer=&ui_Arc16;
  else if (time_seconds < 255*60) ui_Arc_pointer=&ui_Arc17;
  else if (time_seconds < 270*60) ui_Arc_pointer=&ui_Arc18;
  else if (time_seconds < 285*60) ui_Arc_pointer=&ui_Arc19;
  else if (time_seconds < 300*60) ui_Arc_pointer=&ui_Arc20;
  else if (time_seconds < 315*60) ui_Arc_pointer=&ui_Arc21;
  else if (time_seconds < 330*60) ui_Arc_pointer=&ui_Arc22;
  else if (time_seconds < 345*60) ui_Arc_pointer=&ui_Arc23;
  else if (time_seconds < 360*60) ui_Arc_pointer=&ui_Arc24;
  else if (time_seconds < 375*60) ui_Arc_pointer=&ui_Arc25;
  else if (time_seconds < 390*60) ui_Arc_pointer=&ui_Arc26;
  else if (time_seconds < 405*60) ui_Arc_pointer=&ui_Arc27;
  else if (time_seconds < 405*60) ui_Arc_pointer=&ui_Arc27;
  else if (time_seconds < 420*60) ui_Arc_pointer=&ui_Arc28;
  else if (time_seconds < 435*60) ui_Arc_pointer=&ui_Arc29;
  else if (time_seconds < 450*60) ui_Arc_pointer=&ui_Arc30;
  else if (time_seconds < 465*60) ui_Arc_pointer=&ui_Arc31;
  else if (time_seconds < 480*60) ui_Arc_pointer=&ui_Arc32;
  else if (time_seconds < 495*60) ui_Arc_pointer=&ui_Arc33;
  else if (time_seconds < 510*60) ui_Arc_pointer=&ui_Arc34;
  else if (time_seconds < 525*60) ui_Arc_pointer=&ui_Arc35;
  else if (time_seconds < 540*60) ui_Arc_pointer=&ui_Arc36;
  else if (time_seconds < 555*60) ui_Arc_pointer=&ui_Arc37;
  else if (time_seconds < 570*60) ui_Arc_pointer=&ui_Arc38;
  else if (time_seconds < 585*60) ui_Arc_pointer=&ui_Arc39;
  else if (time_seconds < 600*60) ui_Arc_pointer=&ui_Arc40;
  else if (time_seconds < 615*60) ui_Arc_pointer=&ui_Arc41;
  else if (time_seconds < 630*60) ui_Arc_pointer=&ui_Arc42;
  else if (time_seconds < 645*60) ui_Arc_pointer=&ui_Arc43;
  else if (time_seconds < 660*60) ui_Arc_pointer=&ui_Arc44;
  else if (time_seconds < 675*60) ui_Arc_pointer=&ui_Arc45;
  else if (time_seconds < 690*60) ui_Arc_pointer=&ui_Arc46;
  else if (time_seconds < 705*60) ui_Arc_pointer=&ui_Arc47;
  else if (time_seconds < 720*60) ui_Arc_pointer=&ui_Arc48;

  /* set start time for first time (only once)  */ 
  if (!already_set_start_time)
  {
    start_time = millis();
    already_set_start_time = true;
  }
  /* updated at every loop */ 
  timer = millis() - start_time;

  /* all the next ifs are checked at every loop and the program stays some loops in each of them based on timer */ 
  if (timer < go_buzz_1 && !already_slept_1) 
  {
    Serial.println("sleep1");
    digitalWrite(21, LOW);
    esp_sleep_enable_timer_wakeup(go_buzz_1*1000);
    esp_sleep_enable_ext0_wakeup(GPIO_NUM_34, LOW); // 21 AGO
    esp_light_sleep_start();
    if (ESP_SLEEP_WAKEUP_EXT0) 
    {
      digitalWrite(21, HIGH);
      Serial.println("Waken up from first sleep");
      delay(10000);
      Serial.println("Going back to first sleep");
      digitalWrite(21, LOW); 
      esp_light_sleep_start();
    } 
    already_slept_1 = true; 
    digitalWrite(21, HIGH);
    Serial.println("slept1");
  } 
  if (timer >= go_buzz_1 && timer < end_buzz_1) 
  { 
   digitalWrite(4, HIGH);
   // Serial.println("buzz on 1"); 

  }
  else if (timer >= end_buzz_1 && timer < go_buzz_2) 
  { 
   digitalWrite(4, LOW);
   // Serial.println("buzz off 1"); 

  }
  else if (timer >= go_buzz_2 && timer < end_buzz_2) 
  { 
   digitalWrite(4, HIGH);
   // Serial.println("buzz on 2"); 

  }
  else if (timer >= end_buzz_2 && timer < go_buzz_3) 
  { 
   digitalWrite(4, LOW);
   // Serial.println("buzz off 2"); 

  }
  else if (timer >= go_buzz_3 && timer < end_buzz_3) 
  { 
   digitalWrite(4, HIGH);
   // Serial.println("buzz on 3"); 

  }
  else if (timer >= end_buzz_3 && timer < go_buzz_4) 
  { 
   digitalWrite(4, LOW);
   // Serial.println("buzz off 3"); 

  }
  else if (timer >= go_buzz_4 && timer < end_buzz_4) 
  { 
   digitalWrite(4, HIGH);
   // Serial.println("buzz on 4"); 

  }
  else if (timer >= end_buzz_4 && timer < end_buzz_4 + 60000) 
  { 
   digitalWrite(4, LOW);
   // Serial.println("buzz off 2"); 
   if (digitalRead(35) == LOW)  // tolto && !already_printed - if button pressed once set the arc color to green (still need to add the case of button pressed twice)
   { 
    lv_obj_set_style_arc_color(*ui_Arc_pointer, lv_color_hex(0x40FF4B), LV_PART_MAIN);
   }
   if (digitalRead(34) == LOW)  
   { 
    lv_obj_set_style_arc_color(*ui_Arc_pointer, lv_color_hex(0xFF4048), LV_PART_MAIN);
   }
    
  }

  else if (timer >= end_buzz_4 + 60000 && timer < end_buzz_4 + 900000 && !already_slept_2) 
  {
    Serial.println("sleep2");
    digitalWrite(21, LOW);
    esp_sleep_enable_timer_wakeup(delta*1000);
    esp_sleep_enable_ext0_wakeup(GPIO_NUM_34, LOW); // 21 AGO
    esp_light_sleep_start();
    if (ESP_SLEEP_WAKEUP_EXT0) 
    {
      digitalWrite(21, HIGH);
      Serial.println("Waken up from second sleep");
      delay(10000);
      Serial.println("Going back to second sleep");
      digitalWrite(21, LOW); 
      esp_light_sleep_start();
    } 
    already_slept_2 = true; 
    // digitalWrite(21, HIGH); 21AGO
    Serial.println("slept2");
  }

  else if (timer >= 900000)  // after 15 minutes reset and restart - does this only once, because at next loop timer = millis - start time
  {
    start_time = millis();
    end_buzz_1 = go_buzz_1 + 500;
    go_buzz_2 = go_buzz_1 + 1500;
    end_buzz_2 = go_buzz_1 + 2000;
    go_buzz_3 = go_buzz_1 + 2500;
    end_buzz_3 = go_buzz_1 + 3000;
    go_buzz_4 = go_buzz_1 + 3500;
    end_buzz_4 = go_buzz_1 + 4000;
    delta = 900000 - (end_buzz_4 + 60000); // wait 60sec for input after end of buzzes
    Serial.println("go_buzz_1:");
    Serial.println(go_buzz_1);
    already_slept_1 = false;
    already_slept_2 = false;

  }

}

Variables that hold their value even over a deepsleep must have the
RTC_DATA_ATTR attribute

RTC_DATA_ATTR int bootCount = 0;

these variables are stored inside the RTC-RAM which is kept alive through the sleeping.

All your millis-timing variables should be unsigned long as this is the datatype that millis() returns.

You are using a watch that runs over weeks. After 24 days the long-variables will turn their value to negative and then the calculations don't fit anymore.

You have defined some variables as non-global inside function loop
example

  uint32_t time_seconds = secondsFromHoursMinutes(rtc.formatDateTime(PCF_TIMEFORMAT_HM));

each time the code starts new these variables are deleted and freshly initialised.

For a deeper analysis what is going on in your code add serial printing.
Me personal I use macros for this which have more comfort than a simple serial.print()
Here is your code with this debug-macros and additional serial prinnting

// MACRO-START * MACRO-START * MACRO-START * MACRO-START * MACRO-START * MACRO-START *
// a detailed explanation how these macros work is given in this tutorial
// https://forum.arduino.cc/t/comfortable-serial-debug-output-short-to-write-fixed-text-name-and-content-of-any-variable-code-example/888298

#define dbg(myFixedText, variableName) \
  Serial.print( F(#myFixedText " "  #variableName"=") ); \
  Serial.println(variableName);

#define dbgi(myFixedText, variableName,timeInterval) \
  { \
    static unsigned long intervalStartTime; \
    if ( millis() - intervalStartTime >= timeInterval ){ \
      intervalStartTime = millis(); \
      Serial.print( F(#myFixedText " "  #variableName"=") ); \
      Serial.println(variableName); \
    } \
  }

#define dbgc(myFixedText, variableName) \
  { \
    static long lastState; \
    if ( lastState != variableName ){ \
      Serial.print( F(#myFixedText " "  #variableName" changed from ") ); \
      Serial.print(lastState); \
      Serial.print( F(" to ") ); \
      Serial.println(variableName); \
      lastState = variableName; \
    } \
  }

#define dbgcf(myFixedText, variableName) \
  { \
    static float lastState; \
    if ( lastState != variableName ){ \
      Serial.print( F(#myFixedText " "  #variableName" changed from ") ); \
      Serial.print(lastState); \
      Serial.print( F(" to ") ); \
      Serial.println(variableName); \
      lastState = variableName; \
    } \
  }
// MACRO-END * MACRO-END * MACRO-END * MACRO-END * MACRO-END * MACRO-END * MACRO-END *


#include <lvgl.h>
#include "ui.h"
#include <Wire.h>
#include "pcf8563.h"

PCF8563_Class rtc;

#include <Arduino_GFX_Library.h>

/************************************************************************************************************************************
   GFX setting
 ************************************************************************************************************************************/

#define GFX_BL 21 // default backlight pin, you may replace DF_GFX_BL to actual backlight pin

/* More dev device declaration: https://github.com/moononournation/Arduino_GFX/wiki/Dev-Device-Declaration */
#if defined(DISPLAY_DEV_KIT)
Arduino_GFX *gfx = create_default_Arduino_GFX();
#else /* !defined(DISPLAY_DEV_KIT) */

/* More data bus class: https://github.com/moononournation/Arduino_GFX/wiki/Data-Bus-Class */
Arduino_DataBus *bus = new Arduino_ESP32SPI(19 /* DC */, 15 /* CS */, 14 /* SCK */, 13 /* MOSI */, GFX_NOT_DEFINED /* MISO */);

/* More display class: https://github.com/moononournation/Arduino_GFX/wiki/Display-Class */
Arduino_GFX *gfx = new Arduino_GC9A01(bus, 27 /* RST */, 0 /* rotation */, true /* IPS */);

#endif /* !defined(DISPLAY_DEV_KIT) */

/* Change to your screen resolution */
static uint32_t screenWidth;
static uint32_t screenHeight;
static lv_disp_draw_buf_t draw_buf;
static lv_color_t *disp_draw_buf;
static lv_disp_drv_t disp_drv;

/* Display flushing */
void my_disp_flush(lv_disp_drv_t *disp, const lv_area_t *area, lv_color_t *color_p)
{
  uint32_t w = (area->x2 - area->x1 + 1);
  uint32_t h = (area->y2 - area->y1 + 1);

#if (LV_COLOR_16_SWAP != 0)
  gfx->draw16bitBeRGBBitmap(area->x1, area->y1, (uint16_t *)&color_p->full, w, h);
#else
  gfx->draw16bitRGBBitmap(area->x1, area->y1, (uint16_t *)&color_p->full, w, h);
#endif

  lv_disp_flush_ready(disp);
}

/************************************************************************************************************************************
   End GFX
 ************************************************************************************************************************************/

/* Define variable for buzzer timer  */
unsigned long go_buzz_1;
unsigned long end_buzz_1;
unsigned long go_buzz_2;
unsigned long end_buzz_2;
unsigned long go_buzz_3;
unsigned long end_buzz_3;
unsigned long go_buzz_4;
unsigned long end_buzz_4;
unsigned long delta;
unsigned long start_time;
unsigned long timer;

/* convert time into seconds  */
int32_t secondsFromHoursMinutes(const char* from) {
  return (atoi(from) * 60L + atoi(from + 3)) * 60;
}

/*  FLAGS  */
bool already_synced = false;
bool already_set_start_time = false;
bool already_slept_1 = false;
bool already_slept_2 = false;

void setup() {
  Serial.begin(115200);
  while (!Serial); // wait for serial interface to be ready
  Serial.println("Setup-Start");
  /*********************************** BEGIN GFX (?) STUFF in SETUP **********************************************/

#ifdef GFX_EXTRA_PRE_INIT
  GFX_EXTRA_PRE_INIT();
#endif

  // Init Display
  if (!gfx->begin())
  {
    Serial.println("gfx->begin() failed!");
  }
  gfx->fillScreen(BLACK);

#ifdef GFX_BL
  pinMode(GFX_BL, OUTPUT);
  digitalWrite(GFX_BL, HIGH);
#endif

  lv_init();

  screenWidth = gfx->width();
  screenHeight = gfx->height();
#ifdef ESP32
  disp_draw_buf = (lv_color_t *)heap_caps_malloc(sizeof(lv_color_t) * screenWidth * 40, MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT);
#else
  disp_draw_buf = (lv_color_t *)malloc(sizeof(lv_color_t) * screenWidth * 40);
#endif
  if (!disp_draw_buf)
  {
    Serial.println("LVGL disp_draw_buf allocate failed!");
  }
  else
  {
    lv_disp_draw_buf_init(&draw_buf, disp_draw_buf, NULL, screenWidth * 40);

    /* Initialize the display */
    lv_disp_drv_init(&disp_drv);
    /* Change the following line to your display resolution */
    disp_drv.hor_res = screenWidth;
    disp_drv.ver_res = screenHeight;
    disp_drv.flush_cb = my_disp_flush;
    disp_drv.draw_buf = &draw_buf;
    lv_disp_drv_register(&disp_drv);

    /* Initialize the (dummy) input device driver */
    static lv_indev_drv_t indev_drv;
    lv_indev_drv_init(&indev_drv);
    indev_drv.type = LV_INDEV_TYPE_POINTER;
    lv_indev_drv_register(&indev_drv);

  }
  /* *************************************** END GFX (?) STUFF in SETUP *******************************************/

  /* initialize Squareline Studio UI */
  ui_init();

  Serial.println("Setup done");

  /* INITIALIZE RTC */
  Wire.begin(26, 25);
  rtc.begin();
  // rtc.setDateTime(2023, 8, 17, 02, 33, 00);  // commented out to hold time

  /* Sets motot pin as output and btn2 and 3 as input */
  pinMode(4, OUTPUT);
  pinMode(34, INPUT_PULLUP); // if commented out, input always low (not sure why, but tested)
  pinMode(35, INPUT_PULLUP); // if commented out, input always low (not sure why, but tested)

  /* SETS RANDOM TIMER */
  randomSeed(analogRead(17));  // DA PINOUT IL 17 SEMBRA NON USATO
  go_buzz_1 = random(1000, 836000); // 900.000ms - (4.000ms buzz cycle + 60.000ms wait for input)
  end_buzz_1 = go_buzz_1 + 500;
  go_buzz_2 = go_buzz_1 + 1500;
  end_buzz_2 = go_buzz_1 + 2000;
  go_buzz_3 = go_buzz_1 + 2500;
  end_buzz_3 = go_buzz_1 + 3000;
  go_buzz_4 = go_buzz_1 + 3500;
  end_buzz_4 = go_buzz_1 + 4000;

  delta = 900000 - (end_buzz_4 + 60000); // wait 60sec for input after end of buzzes

  /* start_time = millis();  // definisce start time come il tempo attuale - no qui perché all'inizio del loop c'è un ritardo,
    quindi se ad esempio parte alle 2010, start time sarà uguale ai millis delle 2010, poi però aspetta 5' per arrivare alle 2015,
    quando parte il loop setta timer = millis - start time che è non quello presente ma quello di cinque minuti prima, quindi timer è
    come se partisse alle 2010 e non alle 2015. Come se non avesse fatto il delay*/

  /*  PRINTS TO MONITOR CODE  */
  Serial.println("go_buzz_1:");
  Serial.println(go_buzz_1);
  Serial.println("rtc:");
  Serial.println(rtc.formatDateTime(PCF_TIMEFORMAT_HM));
  Serial.println("atoi:");
  Serial.println(atoi(rtc.formatDateTime(PCF_TIMEFORMAT_HM))); // TO CHECK TIME CONVERSION TO SEC
  Serial.println("atoi+3:");
  Serial.println(atoi(rtc.formatDateTime(PCF_TIMEFORMAT_HM) + 3)); // TO CHECK TIME CONVERSION TO SEC
  // Serial.println(time_seconds);  // TO CHECK TIME CONVERSION TO SEC non si può mettere qui perche dichiarato dopo e se la fai global crash

  /* DISPLAY ALWAYS OFF EXCEPT WHEN BUTTON PRESSED - 21 AGO*/
  digitalWrite(21, LOW); // 21 AGO
}

void loop() {

  lv_timer_handler(); /* let the GUI do its work */
  delay(5);

  /* PRINTS TIME ON CENTRAL LABEL  */
  lv_label_set_text(ui_Label14, rtc.formatDateTime(PCF_TIMEFORMAT_HM));


  /* TURN ON SCREEN WITH BUTTON */
  if (digitalRead(34) == LOW)
  {
    digitalWrite(21, HIGH);
    Serial.println("Screen on from button (not sleeping)");
    delay(10000); // VERIFY THAT DELAY DOESN'T MESS UP COUNTERS...
    digitalWrite(21, LOW);
  }

  /* POINTER TO LVGL ARC WIDGET */
  lv_obj_t * *ui_Arc_pointer;

  /* Define variable to convert RTC time in seconds iot compare and assign 15' window
    needs to be defined in loop because value changes continuously with passing of time, as
    shown by pointer to arc changing   */
  uint32_t time_seconds = secondsFromHoursMinutes(rtc.formatDateTime(PCF_TIMEFORMAT_HM));
  // only if value of variable "time_seconds"
  // has CHANGED print once
  dbgc("L1", time_seconds);

  /* define time to wait iot sync to whole quarter  */
  int wait_to_sync (900 - (time_seconds % 900)); // seconds remaining to first whole quarter hour - sempre multipli di 60 perché secondsfromhourminutes parte da HM
  dbgc("L2", wait_to_sync);

  /* syncing to whole quarter. Only once every program run (flag) */
  if (!already_synced)
  {
    Serial.println("time_seconds:");
    Serial.println(time_seconds);
    Serial.println("waiting:");
    Serial.println(wait_to_sync);
    delay(wait_to_sync * 1000);
    Serial.println("synced to whole quarter");
    already_synced = true;
  }

  /* compare time_seconds and associate pointer to lvgl arc - to be done continuously */

  if (time_seconds >= 12 * 60 * 60) time_seconds = (time_seconds - 12 * 60 * 60); // convert time to 12h
  dbgc("L3", time_seconds);

  if (time_seconds < 15 * 60) ui_Arc_pointer = &ui_Arc2; // store ui_Arc2 address into pointer
  else if (time_seconds < 30 * 60) ui_Arc_pointer = &ui_Arc1;
  else if (time_seconds < 45 * 60) ui_Arc_pointer = &ui_Arc3;
  else if (time_seconds < 60 * 60) ui_Arc_pointer = &ui_Arc4;
  else if (time_seconds < 75 * 60) ui_Arc_pointer = &ui_Arc5;
  else if (time_seconds < 90 * 60) ui_Arc_pointer = &ui_Arc6;
  else if (time_seconds < 105 * 60) ui_Arc_pointer = &ui_Arc7;
  else if (time_seconds < 120 * 60) ui_Arc_pointer = &ui_Arc8;
  else if (time_seconds < 135 * 60) ui_Arc_pointer = &ui_Arc9;
  else if (time_seconds < 150 * 60) ui_Arc_pointer = &ui_Arc10;
  else if (time_seconds < 165 * 60) ui_Arc_pointer = &ui_Arc11;
  else if (time_seconds < 180 * 60) ui_Arc_pointer = &ui_Arc12;
  else if (time_seconds < 195 * 60) ui_Arc_pointer = &ui_Arc13;
  else if (time_seconds < 210 * 60) ui_Arc_pointer = &ui_Arc14;
  else if (time_seconds < 225 * 60) ui_Arc_pointer = &ui_Arc15;
  else if (time_seconds < 240 * 60) ui_Arc_pointer = &ui_Arc16;
  else if (time_seconds < 255 * 60) ui_Arc_pointer = &ui_Arc17;
  else if (time_seconds < 270 * 60) ui_Arc_pointer = &ui_Arc18;
  else if (time_seconds < 285 * 60) ui_Arc_pointer = &ui_Arc19;
  else if (time_seconds < 300 * 60) ui_Arc_pointer = &ui_Arc20;
  else if (time_seconds < 315 * 60) ui_Arc_pointer = &ui_Arc21;
  else if (time_seconds < 330 * 60) ui_Arc_pointer = &ui_Arc22;
  else if (time_seconds < 345 * 60) ui_Arc_pointer = &ui_Arc23;
  else if (time_seconds < 360 * 60) ui_Arc_pointer = &ui_Arc24;
  else if (time_seconds < 375 * 60) ui_Arc_pointer = &ui_Arc25;
  else if (time_seconds < 390 * 60) ui_Arc_pointer = &ui_Arc26;
  else if (time_seconds < 405 * 60) ui_Arc_pointer = &ui_Arc27;
  else if (time_seconds < 405 * 60) ui_Arc_pointer = &ui_Arc27;
  else if (time_seconds < 420 * 60) ui_Arc_pointer = &ui_Arc28;
  else if (time_seconds < 435 * 60) ui_Arc_pointer = &ui_Arc29;
  else if (time_seconds < 450 * 60) ui_Arc_pointer = &ui_Arc30;
  else if (time_seconds < 465 * 60) ui_Arc_pointer = &ui_Arc31;
  else if (time_seconds < 480 * 60) ui_Arc_pointer = &ui_Arc32;
  else if (time_seconds < 495 * 60) ui_Arc_pointer = &ui_Arc33;
  else if (time_seconds < 510 * 60) ui_Arc_pointer = &ui_Arc34;
  else if (time_seconds < 525 * 60) ui_Arc_pointer = &ui_Arc35;
  else if (time_seconds < 540 * 60) ui_Arc_pointer = &ui_Arc36;
  else if (time_seconds < 555 * 60) ui_Arc_pointer = &ui_Arc37;
  else if (time_seconds < 570 * 60) ui_Arc_pointer = &ui_Arc38;
  else if (time_seconds < 585 * 60) ui_Arc_pointer = &ui_Arc39;
  else if (time_seconds < 600 * 60) ui_Arc_pointer = &ui_Arc40;
  else if (time_seconds < 615 * 60) ui_Arc_pointer = &ui_Arc41;
  else if (time_seconds < 630 * 60) ui_Arc_pointer = &ui_Arc42;
  else if (time_seconds < 645 * 60) ui_Arc_pointer = &ui_Arc43;
  else if (time_seconds < 660 * 60) ui_Arc_pointer = &ui_Arc44;
  else if (time_seconds < 675 * 60) ui_Arc_pointer = &ui_Arc45;
  else if (time_seconds < 690 * 60) ui_Arc_pointer = &ui_Arc46;
  else if (time_seconds < 705 * 60) ui_Arc_pointer = &ui_Arc47;
  else if (time_seconds < 720 * 60) ui_Arc_pointer = &ui_Arc48;

  /* set start time for first time (only once)  */
  if (!already_set_start_time)
  {
    start_time = millis();//xxy
    already_set_start_time = true;
  }
  dbgc("L4", start_time);

  /* updated at every loop */
  timer = millis() - start_time;

  /* all the next ifs are checked at every loop and the program stays some loops in each of them based on timer */
  if (timer < go_buzz_1 && !already_slept_1)
  {
    Serial.println("sleep1");
    digitalWrite(21, LOW);
    esp_sleep_enable_timer_wakeup(go_buzz_1 * 1000);
    esp_sleep_enable_ext0_wakeup(GPIO_NUM_34, LOW); // 21 AGO
    esp_light_sleep_start();
    if (ESP_SLEEP_WAKEUP_EXT0)
    {
      digitalWrite(21, HIGH);
      Serial.println("Waken up from first sleep");
      delay(10000);
      Serial.println("Going back to first sleep");
      digitalWrite(21, LOW);
      esp_light_sleep_start();
    }
    already_slept_1 = true;
    digitalWrite(21, HIGH);
    Serial.println("slept1");
  }

  if (timer >= go_buzz_1 && timer < end_buzz_1)
  {
    digitalWrite(4, HIGH);
    // Serial.println("buzz on 1");

  }
  else if (timer >= end_buzz_1 && timer < go_buzz_2)
  {
    digitalWrite(4, LOW);
    // Serial.println("buzz off 1");

  }
  else if (timer >= go_buzz_2 && timer < end_buzz_2)
  {
    digitalWrite(4, HIGH);
    // Serial.println("buzz on 2");

  }
  else if (timer >= end_buzz_2 && timer < go_buzz_3)
  {
    digitalWrite(4, LOW);
    // Serial.println("buzz off 2");

  }
  else if (timer >= go_buzz_3 && timer < end_buzz_3)
  {
    digitalWrite(4, HIGH);
    // Serial.println("buzz on 3");

  }
  else if (timer >= end_buzz_3 && timer < go_buzz_4)
  {
    digitalWrite(4, LOW);
    // Serial.println("buzz off 3");

  }
  else if (timer >= go_buzz_4 && timer < end_buzz_4)
  {
    digitalWrite(4, HIGH);
    // Serial.println("buzz on 4");

  }
  else if (timer >= end_buzz_4 && timer < end_buzz_4 + 60000)
  {
    digitalWrite(4, LOW);
    // Serial.println("buzz off 2");
    if (digitalRead(35) == LOW)  // tolto && !already_printed - if button pressed once set the arc color to green (still need to add the case of button pressed twice)
    {
      lv_obj_set_style_arc_color(*ui_Arc_pointer, lv_color_hex(0x40FF4B), LV_PART_MAIN);
    }
    if (digitalRead(34) == LOW)
    {
      lv_obj_set_style_arc_color(*ui_Arc_pointer, lv_color_hex(0xFF4048), LV_PART_MAIN);
    }

  }

  else if (timer >= end_buzz_4 + 60000 && timer < end_buzz_4 + 900000 && !already_slept_2)
  {
    Serial.println("sleep2");
    digitalWrite(21, LOW);
    dbgc("L5", delta * 1000);

    esp_sleep_enable_timer_wakeup(delta * 1000);
    esp_sleep_enable_ext0_wakeup(GPIO_NUM_34, LOW); // 21 AGO
    esp_light_sleep_start();
    if (ESP_SLEEP_WAKEUP_EXT0)
    {
      digitalWrite(21, HIGH);
      Serial.println("Waken up from second sleep");
      delay(10000);
      Serial.println("Going back to second sleep");
      digitalWrite(21, LOW);
      esp_light_sleep_start();
    }
    already_slept_2 = true;
    // digitalWrite(21, HIGH); 21AGO
    Serial.println("slept2");
  }

  else if (timer >= 900000)  // after 15 minutes reset and restart - does this only once, because at next loop timer = millis - start time
  {
    start_time = millis();
    end_buzz_1 = go_buzz_1 + 500;
    go_buzz_2 = go_buzz_1 + 1500;
    end_buzz_2 = go_buzz_1 + 2000;
    go_buzz_3 = go_buzz_1 + 2500;
    end_buzz_3 = go_buzz_1 + 3000;
    go_buzz_4 = go_buzz_1 + 3500;
    end_buzz_4 = go_buzz_1 + 4000;
    delta = 900000 - (end_buzz_4 + 60000); // wait 60sec for input after end of buzzes
    dbgc("L6", delta);
    Serial.println("go_buzz_1:");
    Serial.println(go_buzz_1);
    already_slept_1 = false;
    already_slept_2 = false;
  }
}

best regards Stefan

1 Like

@StefanL38, thank you so much for your suggestions! I will need to look better into the macros.
For the moment I can offer the following comments:

"Variables that hold their value even over a deepsleep must have the
RTC_DATA_ATTR attribute": I haven't used any of those and gave up deep sleep for the moment because I understand that can be done only with global variables, and I have some variables that I have only been able to make as local.

"All your millis-timing variables should be unsigned long as this is the datatype that millis() returns": will do that right away.

"You have defined some variables as non-global inside function loop
example uint32_t time_seconds": when I tried to make this specific variable global, I could compile but the code crashed right at startup. I didn't investigate further the register dump though... I just kept it local and it seemed to be happy with that...

Thanks again!
Angelo

I don't believe that the real cause for the crash is making the variable global.
Sure if you say the code crashes the code crashes. But I suspect that there is something else wrong with the code which when the variable is defined local has not the effect of crashing. One possible cause could be some kind of memory-corruption that happens on different places depending on the variable beeing declared global or local.

It would be very interesting to know at exact what line of code the code crashes.
This can easily be done by adding serial prints to the code.
best regards Stefan

I have run the crash dump into the Exception Decoder and I attach the screenshot of the translation:


The only reference to the main code file is line 87, which is exactly the new line at the beginning of the program where I moved the definition of the variable that used to be inside the loop:

uint time_seconds = secondsFromHoursMinutes(rtc.formatDateTime(PCF_TIMEFORMAT_HM));

I am afraid for my level of knowledge it's too hard to understand where the issue is and how to fix it, but maybe you can :slight_smile:

Regarding the MACROs, I tried to implement them (I am not sure I did it right: I only replaced 'variableName' with 'time_seconds'), the code compiles but then it keeps crashing and reloading as it did before and it doesn't seem like the macros are printing anything...

To make it easy to analyse you should do two things:

  1. posting exactly that complete sketch that crashed
  2. posting the complete decoder-output NOT as a screenshot
    but
    as
    a code-section

How should somebody else be really sure what line 87 really is if she/he has to choose from multiple sketches in the thread??

This does not really explain what happened. It is partial information.

For analysing where exactly the crash is happening you should add a lot of serial prints
If the crash occures "very early" in the sence a few lines below
void setup()

best regards Stefan

Sometimes analysing is not guessing but just work
here is your code with added serial printing really after each single line of code in setup
where the line of code below is just quoted. This will make it easy to identify the line of code that causes the crash

#include <lvgl.h>
#include "ui.h"
#include <Wire.h>
#include "pcf8563.h"

PCF8563_Class rtc;

#include <Arduino_GFX_Library.h>

/************************************************************************************************************************************
   GFX setting
 ************************************************************************************************************************************/

#define GFX_BL 21 // default backlight pin, you may replace DF_GFX_BL to actual backlight pin

/* More dev device declaration: https://github.com/moononournation/Arduino_GFX/wiki/Dev-Device-Declaration */
#if defined(DISPLAY_DEV_KIT)
Arduino_GFX *gfx = create_default_Arduino_GFX();
#else /* !defined(DISPLAY_DEV_KIT) */

/* More data bus class: https://github.com/moononournation/Arduino_GFX/wiki/Data-Bus-Class */
Arduino_DataBus *bus = new Arduino_ESP32SPI(19 /* DC */, 15 /* CS */, 14 /* SCK */, 13 /* MOSI */, GFX_NOT_DEFINED /* MISO */);

/* More display class: https://github.com/moononournation/Arduino_GFX/wiki/Display-Class */
Arduino_GFX *gfx = new Arduino_GC9A01(bus, 27 /* RST */, 0 /* rotation */, true /* IPS */);

#endif /* !defined(DISPLAY_DEV_KIT) */

/* Change to your screen resolution */
static uint32_t screenWidth;
static uint32_t screenHeight;
static lv_disp_draw_buf_t draw_buf;
static lv_color_t *disp_draw_buf;
static lv_disp_drv_t disp_drv;

/* Display flushing */
void my_disp_flush(lv_disp_drv_t *disp, const lv_area_t *area, lv_color_t *color_p)
{
  uint32_t w = (area->x2 - area->x1 + 1);
  uint32_t h = (area->y2 - area->y1 + 1);

#if (LV_COLOR_16_SWAP != 0)
  gfx->draw16bitBeRGBBitmap(area->x1, area->y1, (uint16_t *)&color_p->full, w, h);
#else
  gfx->draw16bitRGBBitmap(area->x1, area->y1, (uint16_t *)&color_p->full, w, h);
#endif

  lv_disp_flush_ready(disp);
}

/************************************************************************************************************************************
   End GFX
 ************************************************************************************************************************************/

/* Define variable for buzzer timer  */
long go_buzz_1;
long end_buzz_1;
long go_buzz_2;
long end_buzz_2;
long go_buzz_3;
long end_buzz_3;
long go_buzz_4;
long end_buzz_4;
long delta;
long start_time;
long timer;

/* convert time into seconds  */
int32_t secondsFromHoursMinutes(const char* from) {
  return (atoi(from) * 60L + atoi(from + 3)) * 60;
}

/*  FLAGS  */
bool already_synced = false;
bool already_set_start_time = false;
bool already_slept_1 = false;
bool already_slept_2 = false;

void setup()
{
  Serial.begin(115200);
  Serial.begin("Setup-Start");
  /*********************************** BEGIN GFX (?) STUFF in SETUP **********************************************/

#ifdef GFX_EXTRA_PRE_INIT
  Serial.begin("right before GFX_EXTRA_PRE_INIT();");
  GFX_EXTRA_PRE_INIT();
#endif

  Serial.begin("right before if (!gfx->begin())");
  // Init Display
  if (!gfx->begin())
  {
    Serial.println("gfx->begin() failed!");
  }
  Serial.begin("right before gfx->fillScreen(BLACK)");
  gfx->fillScreen(BLACK);

#ifdef GFX_BL
  Serial.begin("right before pinMode(GFX_BL, OUTPUT);");
  pinMode(GFX_BL, OUTPUT);
  Serial.begin("right before digitalWrite(GFX_BL, HIGH);");
  digitalWrite(GFX_BL, HIGH);
#endif

  Serial.begin("right before lv_init();");
  lv_init();

  Serial.begin("right before screenWidth = gfx->width();");
  screenWidth = gfx->width();
  Serial.begin("right before screenHeight = gfx->height();");
  screenHeight = gfx->height();
#ifdef ESP32
  Serial.begin("#ifdef ESP32 right before disp_draw_buf = (lv_color_t *)heap_caps_malloc(sizeof(lv_color_t...");
  disp_draw_buf = (lv_color_t *)heap_caps_malloc(sizeof(lv_color_t) * screenWidth * 40, MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT);
#else
  Serial.begin("#else right before disp_draw_buf = (lv_color_t *)malloc(sizeof(lv_color_t) * screenWidth * 40);");
  disp_draw_buf = (lv_color_t *)malloc(sizeof(lv_color_t) * screenWidth * 40);
#endif
  Serial.begin("right before if (!disp_draw_buf)");
  if (!disp_draw_buf)
  {
    Serial.println("LVGL disp_draw_buf allocate failed!");
  }
  else //xx1
  {
    Serial.begin("xx1 right before lv_disp_draw_buf_init(&draw_buf, disp_draw_buf, NULL, screenWidth * 40);");
    lv_disp_draw_buf_init(&draw_buf, disp_draw_buf, NULL, screenWidth * 40);

    /* Initialize the display */
    Serial.begin("right before lv_disp_drv_init(&disp_drv);");
    lv_disp_drv_init(&disp_drv);
    /* Change the following line to your display resolution */
    Serial.begin("right before disp_drv.hor_res = screenWidth;");
    disp_drv.hor_res = screenWidth;

    Serial.begin("right before disp_drv.hor_res = screenWidth;");
    disp_drv.ver_res = screenHeight;

    Serial.begin("right before disp_drv.flush_cb = my_disp_flush;");
    disp_drv.flush_cb = my_disp_flush;

    Serial.begin("right before disp_drv.draw_buf = &draw_buf;");
    disp_drv.draw_buf = &draw_buf;

    Serial.begin("right before lv_disp_drv_register(&disp_drv);");
    lv_disp_drv_register(&disp_drv);

    /* Initialize the (dummy) input device driver */
    static lv_indev_drv_t indev_drv;
    lv_indev_drv_init(&indev_drv);
    indev_drv.type = LV_INDEV_TYPE_POINTER;

    Serial.begin("right before lv_indev_drv_register(&indev_drv);");
    lv_indev_drv_register(&indev_drv);

  }
  /* *************************************** END GFX (?) STUFF in SETUP *******************************************/

  /* initialize Squareline Studio UI */
  Serial.begin("right before ui_init();");
  ui_init();

  Serial.println("ui_init(); Setup done");

  /* INITIALIZE RTC */
  Serial.begin("right before Wire.begin(26, 25);");
  Wire.begin(26, 25);

  Serial.begin("right before rtc.begin();");
  rtc.begin();
  // rtc.setDateTime(2023, 8, 17, 02, 33, 00);  // commented out to hold time

  /* Sets motot pin as output and btn2 and 3 as input */
  pinMode(4, OUTPUT);
  pinMode(34, INPUT_PULLUP); // if commented out, input always low (not sure why, but tested)
  pinMode(35, INPUT_PULLUP); // if commented out, input always low (not sure why, but tested)

  /* SETS RANDOM TIMER */
  randomSeed(analogRead(17));  // DA PINOUT IL 17 SEMBRA NON USATO
  go_buzz_1 = random(1000, 836000); // 900.000ms - (4.000ms buzz cycle + 60.000ms wait for input)
  end_buzz_1 = go_buzz_1 + 500;
  go_buzz_2 = go_buzz_1 + 1500;
  end_buzz_2 = go_buzz_1 + 2000;
  go_buzz_3 = go_buzz_1 + 2500;
  end_buzz_3 = go_buzz_1 + 3000;
  go_buzz_4 = go_buzz_1 + 3500;
  end_buzz_4 = go_buzz_1 + 4000;

  delta = 900000 - (end_buzz_4 + 60000); // wait 60sec for input after end of buzzes

  /* start_time = millis();  // definisce start time come il tempo attuale - no qui perché all'inizio del loop c'è un ritardo,
    quindi se ad esempio parte alle 2010, start time sarà uguale ai millis delle 2010, poi però aspetta 5' per arrivare alle 2015,
    quando parte il loop setta timer = millis - start time che è non quello presente ma quello di cinque minuti prima, quindi timer è
    come se partisse alle 2010 e non alle 2015. Come se non avesse fatto il delay*/

  /*  PRINTS TO MONITOR CODE  */
  Serial.println("go_buzz_1:");
  Serial.println(go_buzz_1);
  Serial.println("rtc:");
  Serial.println(rtc.formatDateTime(PCF_TIMEFORMAT_HM));
  Serial.println("atoi:");
  Serial.println(atoi(rtc.formatDateTime(PCF_TIMEFORMAT_HM))); // TO CHECK TIME CONVERSION TO SEC
  Serial.println("atoi+3:");
  Serial.println(atoi(rtc.formatDateTime(PCF_TIMEFORMAT_HM) + 3)); // TO CHECK TIME CONVERSION TO SEC
  // Serial.println(time_seconds);  // TO CHECK TIME CONVERSION TO SEC non si può mettere qui perche dichiarato dopo e se la fai global crash

  /* DISPLAY ALWAYS OFF EXCEPT WHEN BUTTON PRESSED - 21 AGO*/
  digitalWrite(21, LOW); // 21 AGO
}

void loop()
{

  lv_timer_handler(); /* let the GUI do its work */
  delay(5);

  /* PRINTS TIME ON CENTRAL LABEL  */
  lv_label_set_text(ui_Label14, rtc.formatDateTime(PCF_TIMEFORMAT_HM));


  /* TURN ON SCREEN WITH BUTTON */
  if (digitalRead(34) == LOW)
  {
    digitalWrite(21, HIGH);
    Serial.println("Screen on from button (not sleeping)");
    delay(10000); // VERIFY THAT DELAY DOESN'T MESS UP COUNTERS...
    digitalWrite(21, LOW);
  }

  /* POINTER TO LVGL ARC WIDGET */
  lv_obj_t * *ui_Arc_pointer;

  /* Define variable to convert RTC time in seconds iot compare and assign 15' window
    needs to be defined in loop because value changes continuously with passing of time, as
    shown by pointer to arc changing   */
  uint32_t time_seconds = secondsFromHoursMinutes(rtc.formatDateTime(PCF_TIMEFORMAT_HM));


  /* define time to wait iot sync to whole quarter  */
  int wait_to_sync (900 - (time_seconds % 900)); // seconds remaining to first whole quarter hour - sempre multipli di 60 perché secondsfromhourminutes parte da HM

  /* syncing to whole quarter. Only once every program run (flag) */
  if (!already_synced)
  {
    Serial.println("time_seconds:");
    Serial.println(time_seconds);
    Serial.println("waiting:");
    Serial.println(wait_to_sync);
    delay(wait_to_sync * 1000);
    Serial.println("synced to whole quarter");
    already_synced = true;
  }

  /* compare time_seconds and associate pointer to lvgl arc - to be done continuously */

  if (time_seconds >= 12 * 60 * 60) time_seconds = (time_seconds - 12 * 60 * 60); // convert time to 12h
  if (time_seconds < 15 * 60) ui_Arc_pointer = &ui_Arc2; // store ui_Arc2 address into pointer
  else if (time_seconds < 30 * 60) ui_Arc_pointer = &ui_Arc1;
  else if (time_seconds < 45 * 60) ui_Arc_pointer = &ui_Arc3;
  else if (time_seconds < 60 * 60) ui_Arc_pointer = &ui_Arc4;
  else if (time_seconds < 75 * 60) ui_Arc_pointer = &ui_Arc5;
  else if (time_seconds < 90 * 60) ui_Arc_pointer = &ui_Arc6;
  else if (time_seconds < 105 * 60) ui_Arc_pointer = &ui_Arc7;
  else if (time_seconds < 120 * 60) ui_Arc_pointer = &ui_Arc8;
  else if (time_seconds < 135 * 60) ui_Arc_pointer = &ui_Arc9;
  else if (time_seconds < 150 * 60) ui_Arc_pointer = &ui_Arc10;
  else if (time_seconds < 165 * 60) ui_Arc_pointer = &ui_Arc11;
  else if (time_seconds < 180 * 60) ui_Arc_pointer = &ui_Arc12;
  else if (time_seconds < 195 * 60) ui_Arc_pointer = &ui_Arc13;
  else if (time_seconds < 210 * 60) ui_Arc_pointer = &ui_Arc14;
  else if (time_seconds < 225 * 60) ui_Arc_pointer = &ui_Arc15;
  else if (time_seconds < 240 * 60) ui_Arc_pointer = &ui_Arc16;
  else if (time_seconds < 255 * 60) ui_Arc_pointer = &ui_Arc17;
  else if (time_seconds < 270 * 60) ui_Arc_pointer = &ui_Arc18;
  else if (time_seconds < 285 * 60) ui_Arc_pointer = &ui_Arc19;
  else if (time_seconds < 300 * 60) ui_Arc_pointer = &ui_Arc20;
  else if (time_seconds < 315 * 60) ui_Arc_pointer = &ui_Arc21;
  else if (time_seconds < 330 * 60) ui_Arc_pointer = &ui_Arc22;
  else if (time_seconds < 345 * 60) ui_Arc_pointer = &ui_Arc23;
  else if (time_seconds < 360 * 60) ui_Arc_pointer = &ui_Arc24;
  else if (time_seconds < 375 * 60) ui_Arc_pointer = &ui_Arc25;
  else if (time_seconds < 390 * 60) ui_Arc_pointer = &ui_Arc26;
  else if (time_seconds < 405 * 60) ui_Arc_pointer = &ui_Arc27;
  else if (time_seconds < 405 * 60) ui_Arc_pointer = &ui_Arc27;
  else if (time_seconds < 420 * 60) ui_Arc_pointer = &ui_Arc28;
  else if (time_seconds < 435 * 60) ui_Arc_pointer = &ui_Arc29;
  else if (time_seconds < 450 * 60) ui_Arc_pointer = &ui_Arc30;
  else if (time_seconds < 465 * 60) ui_Arc_pointer = &ui_Arc31;
  else if (time_seconds < 480 * 60) ui_Arc_pointer = &ui_Arc32;
  else if (time_seconds < 495 * 60) ui_Arc_pointer = &ui_Arc33;
  else if (time_seconds < 510 * 60) ui_Arc_pointer = &ui_Arc34;
  else if (time_seconds < 525 * 60) ui_Arc_pointer = &ui_Arc35;
  else if (time_seconds < 540 * 60) ui_Arc_pointer = &ui_Arc36;
  else if (time_seconds < 555 * 60) ui_Arc_pointer = &ui_Arc37;
  else if (time_seconds < 570 * 60) ui_Arc_pointer = &ui_Arc38;
  else if (time_seconds < 585 * 60) ui_Arc_pointer = &ui_Arc39;
  else if (time_seconds < 600 * 60) ui_Arc_pointer = &ui_Arc40;
  else if (time_seconds < 615 * 60) ui_Arc_pointer = &ui_Arc41;
  else if (time_seconds < 630 * 60) ui_Arc_pointer = &ui_Arc42;
  else if (time_seconds < 645 * 60) ui_Arc_pointer = &ui_Arc43;
  else if (time_seconds < 660 * 60) ui_Arc_pointer = &ui_Arc44;
  else if (time_seconds < 675 * 60) ui_Arc_pointer = &ui_Arc45;
  else if (time_seconds < 690 * 60) ui_Arc_pointer = &ui_Arc46;
  else if (time_seconds < 705 * 60) ui_Arc_pointer = &ui_Arc47;
  else if (time_seconds < 720 * 60) ui_Arc_pointer = &ui_Arc48;

  /* set start time for first time (only once)  */
  if (!already_set_start_time)
  {
    start_time = millis();
    already_set_start_time = true;
  }
  /* updated at every loop */
  timer = millis() - start_time;

  /* all the next ifs are checked at every loop and the program stays some loops in each of them based on timer */
  if (timer < go_buzz_1 && !already_slept_1)
  {
    Serial.println("sleep1");
    digitalWrite(21, LOW);
    esp_sleep_enable_timer_wakeup(go_buzz_1 * 1000);
    esp_sleep_enable_ext0_wakeup(GPIO_NUM_34, LOW); // 21 AGO
    esp_light_sleep_start();
    if (ESP_SLEEP_WAKEUP_EXT0)
    {
      digitalWrite(21, HIGH);
      Serial.println("Waken up from first sleep");
      delay(10000);
      Serial.println("Going back to first sleep");
      digitalWrite(21, LOW);
      esp_light_sleep_start();
    }
    already_slept_1 = true;
    digitalWrite(21, HIGH);
    Serial.println("slept1");
  }
  if (timer >= go_buzz_1 && timer < end_buzz_1)
  {
    digitalWrite(4, HIGH);
    // Serial.println("buzz on 1");

  }
  else if (timer >= end_buzz_1 && timer < go_buzz_2)
  {
    digitalWrite(4, LOW);
    // Serial.println("buzz off 1");

  }
  else if (timer >= go_buzz_2 && timer < end_buzz_2)
  {
    digitalWrite(4, HIGH);
    // Serial.println("buzz on 2");

  }
  else if (timer >= end_buzz_2 && timer < go_buzz_3)
  {
    digitalWrite(4, LOW);
    // Serial.println("buzz off 2");

  }
  else if (timer >= go_buzz_3 && timer < end_buzz_3)
  {
    digitalWrite(4, HIGH);
    // Serial.println("buzz on 3");

  }
  else if (timer >= end_buzz_3 && timer < go_buzz_4)
  {
    digitalWrite(4, LOW);
    // Serial.println("buzz off 3");

  }
  else if (timer >= go_buzz_4 && timer < end_buzz_4)
  {
    digitalWrite(4, HIGH);
    // Serial.println("buzz on 4");

  }
  else if (timer >= end_buzz_4 && timer < end_buzz_4 + 60000)
  {
    digitalWrite(4, LOW);
    // Serial.println("buzz off 2");
    if (digitalRead(35) == LOW)  // tolto && !already_printed - if button pressed once set the arc color to green (still need to add the case of button pressed twice)
    {
      lv_obj_set_style_arc_color(*ui_Arc_pointer, lv_color_hex(0x40FF4B), LV_PART_MAIN);
    }
    if (digitalRead(34) == LOW)
    {
      lv_obj_set_style_arc_color(*ui_Arc_pointer, lv_color_hex(0xFF4048), LV_PART_MAIN);
    }

  }

  else if (timer >= end_buzz_4 + 60000 && timer < end_buzz_4 + 900000 && !already_slept_2)
  {
    Serial.println("sleep2");
    digitalWrite(21, LOW);
    esp_sleep_enable_timer_wakeup(delta * 1000);
    esp_sleep_enable_ext0_wakeup(GPIO_NUM_34, LOW); // 21 AGO
    esp_light_sleep_start();
    if (ESP_SLEEP_WAKEUP_EXT0)
    {
      digitalWrite(21, HIGH);
      Serial.println("Waken up from second sleep");
      delay(10000);
      Serial.println("Going back to second sleep");
      digitalWrite(21, LOW);
      esp_light_sleep_start();
    }
    already_slept_2 = true;
    // digitalWrite(21, HIGH); 21AGO
    Serial.println("slept2");
  }

  else if (timer >= 900000)  // after 15 minutes reset and restart - does this only once, because at next loop timer = millis - start time
  {
    start_time = millis();
    end_buzz_1 = go_buzz_1 + 500;
    go_buzz_2 = go_buzz_1 + 1500;
    end_buzz_2 = go_buzz_1 + 2000;
    go_buzz_3 = go_buzz_1 + 2500;
    end_buzz_3 = go_buzz_1 + 3000;
    go_buzz_4 = go_buzz_1 + 3500;
    end_buzz_4 = go_buzz_1 + 4000;
    delta = 900000 - (end_buzz_4 + 60000); // wait 60sec for input after end of buzzes
    Serial.println("go_buzz_1:");
    Serial.println(go_buzz_1);
    already_slept_1 = false;
    already_slept_2 = false;

  }

}

best regards Stefan

@StefanL38 thank you so much for showing me this.
As a partial feedback, I moved all the variable definitions in the initial part of the code and compiled the code with all the serial prints that you kindly added (I changed all the ‘serial.begin’s into ‘serial.println’, guessed it was a typo).
As soon as the board resets after uploading the serial monitor shows the code crashing and restarting continuously. I unplugged the board to make it stop and read what was printed on the serial monitor: there is none of the prints we inserted. Just the crash. As if it happened before the void.setup() call.
I didn’t have time for more analysis this morning but will look at it better later.

let the code compile again. The mark copy and paste the compiler-log.
Post as a code-section what is in the compiler-log.
It might be a problem of using too much memory.

best regards Stefan

So, here is the compiler output of the crashing code. At the end I am going to paste also the complete code itself.

Sketch uses 620641 bytes (47%) of program storage space. Maximum is 1310720 bytes.
Global variables use 74608 bytes (22%) of dynamic memory, leaving 253072 bytes for local variables. Maximum is 327680 bytes.
esptool.py v4.5.1
Serial port COM3
Connecting....
Chip is ESP32-PICO-V3-02 (revision v3.0)
Features: WiFi, BT, Dual Core, 240MHz, Embedded Flash, Embedded PSRAM, VRef calibration in efuse, Coding Scheme None
Crystal is 40MHz
MAC: ac:0b:fb:6b:dd:04
Uploading stub...
Running stub...
Stub running...
Changing baud rate to 921600
Changed.
Configuring flash size...
Flash will be erased from 0x00001000 to 0x00005fff...
Flash will be erased from 0x00008000 to 0x00008fff...
Flash will be erased from 0x0000e000 to 0x0000ffff...
Flash will be erased from 0x00010000 to 0x000a7fff...
Compressed 18992 bytes to 13109...
Writing at 0x00001000... (100 %)
Wrote 18992 bytes (13109 compressed) at 0x00001000 in 0.5 seconds (effective 310.3 kbit/s)...
Hash of data verified.
Compressed 3072 bytes to 146...
Writing at 0x00008000... (100 %)
Wrote 3072 bytes (146 compressed) at 0x00008000 in 0.1 seconds (effective 338.4 kbit/s)...
Hash of data verified.
Compressed 8192 bytes to 47...
Writing at 0x0000e000... (100 %)
Wrote 8192 bytes (47 compressed) at 0x0000e000 in 0.1 seconds (effective 452.3 kbit/s)...
Hash of data verified.
Compressed 621264 bytes to 360055...
Writing at 0x00010000... (4 %)
Writing at 0x00017790... (9 %)
Writing at 0x00021b26... (13 %)
Writing at 0x0002dbfd... (18 %)
Writing at 0x0003d993... (22 %)
Writing at 0x00042f12... (27 %)
Writing at 0x000486b8... (31 %)
Writing at 0x0004da18... (36 %)
Writing at 0x00052dab... (40 %)
Writing at 0x00058824... (45 %)
Writing at 0x0005daaa... (50 %)
Writing at 0x0006300e... (54 %)
Writing at 0x000682f6... (59 %)
Writing at 0x0006f106... (63 %)
Writing at 0x00074d75... (68 %)
Writing at 0x0007a665... (72 %)
Writing at 0x00080066... (77 %)
Writing at 0x000858de... (81 %)
Writing at 0x0008e867... (86 %)
Writing at 0x00097018... (90 %)
Writing at 0x0009cac9... (95 %)
Writing at 0x000a21a7... (100 %)
Wrote 621264 bytes (360055 compressed) at 0x00010000 in 5.4 seconds (effective 918.5 kbit/s)...
Hash of data verified.

Leaving...
Hard resetting via RTS pin...

And here is the code:

#include <lvgl.h>
#include "ui.h"
#include <Wire.h>
#include "pcf8563.h"

PCF8563_Class rtc;

#include <Arduino_GFX_Library.h>

/************************************************************************************************************************************
   GFX setting
 ************************************************************************************************************************************/

#define GFX_BL 21 // default backlight pin, you may replace DF_GFX_BL to actual backlight pin

/* More dev device declaration: https://github.com/moononournation/Arduino_GFX/wiki/Dev-Device-Declaration */
#if defined(DISPLAY_DEV_KIT)
Arduino_GFX *gfx = create_default_Arduino_GFX();
#else /* !defined(DISPLAY_DEV_KIT) */

/* More data bus class: https://github.com/moononournation/Arduino_GFX/wiki/Data-Bus-Class */
Arduino_DataBus *bus = new Arduino_ESP32SPI(19 /* DC */, 15 /* CS */, 14 /* SCK */, 13 /* MOSI */, GFX_NOT_DEFINED /* MISO */);

/* More display class: https://github.com/moononournation/Arduino_GFX/wiki/Display-Class */
Arduino_GFX *gfx = new Arduino_GC9A01(bus, 27 /* RST */, 0 /* rotation */, true /* IPS */);

#endif /* !defined(DISPLAY_DEV_KIT) */

/* Change to your screen resolution */
static uint32_t screenWidth;
static uint32_t screenHeight;
static lv_disp_draw_buf_t draw_buf;
static lv_color_t *disp_draw_buf;
static lv_disp_drv_t disp_drv;

/* Display flushing */
void my_disp_flush(lv_disp_drv_t *disp, const lv_area_t *area, lv_color_t *color_p)
{
  uint32_t w = (area->x2 - area->x1 + 1);
  uint32_t h = (area->y2 - area->y1 + 1);

#if (LV_COLOR_16_SWAP != 0)
  gfx->draw16bitBeRGBBitmap(area->x1, area->y1, (uint16_t *)&color_p->full, w, h);
#else
  gfx->draw16bitRGBBitmap(area->x1, area->y1, (uint16_t *)&color_p->full, w, h);
#endif

  lv_disp_flush_ready(disp);
}

/************************************************************************************************************************************
   End GFX
 ************************************************************************************************************************************/

/* Define variable for buzzer timer  */
long go_buzz_1;
long end_buzz_1;
long go_buzz_2;
long end_buzz_2;
long go_buzz_3;
long end_buzz_3;
long go_buzz_4;
long end_buzz_4;
long delta;
long start_time;
long timer;

/* convert time into seconds  */
int32_t secondsFromHoursMinutes(const char* from) {
  return (atoi(from) * 60L + atoi(from + 3)) * 60;
}

/* POINTER TO LVGL ARC WIDGET */
lv_obj_t * *ui_Arc_pointer;

/* Define variable to convert RTC time in seconds iot compare and assign 15' window
needs to be defined in loop because value changes continuously with passing of time, as
shown by pointer to arc changing   */
uint32_t time_seconds = secondsFromHoursMinutes(rtc.formatDateTime(PCF_TIMEFORMAT_HM));


/* define time to wait iot sync to whole quarter  */
int wait_to_sync (900 - (time_seconds % 900)); // seconds remaining to first whole quarter hour - sempre multipli di 60 perché secondsfromhourminutes parte da HM


/*  FLAGS  */
bool already_synced = false;
bool already_set_start_time = false;
bool already_slept_1 = false;
bool already_slept_2 = false;

void setup()
{
  Serial.begin(115200);
  Serial.println("Setup-Start");
  /*********************************** BEGIN GFX (?) STUFF in SETUP **********************************************/

#ifdef GFX_EXTRA_PRE_INIT
  Serial.println("right before GFX_EXTRA_PRE_INIT();");
  GFX_EXTRA_PRE_INIT();
#endif

  Serial.println("right before if (!gfx->begin())");
  // Init Display
  if (!gfx->begin())
  {
    Serial.println("gfx->begin() failed!");
  }
  Serial.println("right before gfx->fillScreen(BLACK)");
  gfx->fillScreen(BLACK);

#ifdef GFX_BL
  Serial.println("right before pinMode(GFX_BL, OUTPUT);");
  pinMode(GFX_BL, OUTPUT);
  Serial.println("right before digitalWrite(GFX_BL, HIGH);");
  digitalWrite(GFX_BL, HIGH);
#endif

  Serial.println("right before lv_init();");
  lv_init();

  Serial.println("right before screenWidth = gfx->width();");
  screenWidth = gfx->width();
  Serial.println("right before screenHeight = gfx->height();");
  screenHeight = gfx->height();
#ifdef ESP32
  Serial.println("#ifdef ESP32 right before disp_draw_buf = (lv_color_t *)heap_caps_malloc(sizeof(lv_color_t...");
  disp_draw_buf = (lv_color_t *)heap_caps_malloc(sizeof(lv_color_t) * screenWidth * 40, MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT);
#else
  Serial.println("#else right before disp_draw_buf = (lv_color_t *)malloc(sizeof(lv_color_t) * screenWidth * 40);");
  disp_draw_buf = (lv_color_t *)malloc(sizeof(lv_color_t) * screenWidth * 40);
#endif
  Serial.println("right before if (!disp_draw_buf)");
  if (!disp_draw_buf)
  {
    Serial.println("LVGL disp_draw_buf allocate failed!");
  }
  else //xx1
  {
    Serial.println("xx1 right before lv_disp_draw_buf_init(&draw_buf, disp_draw_buf, NULL, screenWidth * 40);");
    lv_disp_draw_buf_init(&draw_buf, disp_draw_buf, NULL, screenWidth * 40);

    /* Initialize the display */
    Serial.println("right before lv_disp_drv_init(&disp_drv);");
    lv_disp_drv_init(&disp_drv);
    /* Change the following line to your display resolution */
    Serial.println("right before disp_drv.hor_res = screenWidth;");
    disp_drv.hor_res = screenWidth;

    Serial.println("right before disp_drv.hor_res = screenWidth;");
    disp_drv.ver_res = screenHeight;

    Serial.println("right before disp_drv.flush_cb = my_disp_flush;");
    disp_drv.flush_cb = my_disp_flush;

    Serial.println("right before disp_drv.draw_buf = &draw_buf;");
    disp_drv.draw_buf = &draw_buf;

    Serial.println("right before lv_disp_drv_register(&disp_drv);");
    lv_disp_drv_register(&disp_drv);

    /* Initialize the (dummy) input device driver */
    static lv_indev_drv_t indev_drv;
    lv_indev_drv_init(&indev_drv);
    indev_drv.type = LV_INDEV_TYPE_POINTER;

    Serial.println("right before lv_indev_drv_register(&indev_drv);");
    lv_indev_drv_register(&indev_drv);

  }
  /* *************************************** END GFX (?) STUFF in SETUP *******************************************/

  /* initialize Squareline Studio UI */
  Serial.println("right before ui_init();");
  ui_init();

  Serial.println("ui_init(); Setup done");

  /* INITIALIZE RTC */
  Serial.println("right before Wire.begin(26, 25);");
  Wire.begin(26, 25);

  Serial.println("right before rtc.begin();");
  rtc.begin();
  // rtc.setDateTime(2023, 8, 17, 02, 33, 00);  // commented out to hold time

  /* Sets motot pin as output and btn2 and 3 as input */
  pinMode(4, OUTPUT);
  pinMode(34, INPUT_PULLUP); // if commented out, input always low (not sure why, but tested)
  pinMode(35, INPUT_PULLUP); // if commented out, input always low (not sure why, but tested)

  /* SETS RANDOM TIMER */
  randomSeed(analogRead(17));  // DA PINOUT IL 17 SEMBRA NON USATO
  go_buzz_1 = random(1000, 836000); // 900.000ms - (4.000ms buzz cycle + 60.000ms wait for input)
  end_buzz_1 = go_buzz_1 + 500;
  go_buzz_2 = go_buzz_1 + 1500;
  end_buzz_2 = go_buzz_1 + 2000;
  go_buzz_3 = go_buzz_1 + 2500;
  end_buzz_3 = go_buzz_1 + 3000;
  go_buzz_4 = go_buzz_1 + 3500;
  end_buzz_4 = go_buzz_1 + 4000;

  delta = 900000 - (end_buzz_4 + 60000); // wait 60sec for input after end of buzzes

  /* start_time = millis();  // definisce start time come il tempo attuale - no qui perché all'inizio del loop c'è un ritardo,
    quindi se ad esempio parte alle 2010, start time sarà uguale ai millis delle 2010, poi però aspetta 5' per arrivare alle 2015,
    quando parte il loop setta timer = millis - start time che è non quello presente ma quello di cinque minuti prima, quindi timer è
    come se partisse alle 2010 e non alle 2015. Come se non avesse fatto il delay*/

  /*  PRINTS TO MONITOR CODE  */
  Serial.println("go_buzz_1:");
  Serial.println(go_buzz_1);
  Serial.println("rtc:");
  Serial.println(rtc.formatDateTime(PCF_TIMEFORMAT_HM));
  Serial.println("atoi:");
  Serial.println(atoi(rtc.formatDateTime(PCF_TIMEFORMAT_HM))); // TO CHECK TIME CONVERSION TO SEC
  Serial.println("atoi+3:");
  Serial.println(atoi(rtc.formatDateTime(PCF_TIMEFORMAT_HM) + 3)); // TO CHECK TIME CONVERSION TO SEC
  // Serial.println(time_seconds);  // TO CHECK TIME CONVERSION TO SEC non si può mettere qui perche dichiarato dopo e se la fai global crash

  /* DISPLAY ALWAYS OFF EXCEPT WHEN BUTTON PRESSED - 21 AGO*/
  digitalWrite(21, LOW); // 21 AGO
}

void loop()
{

  lv_timer_handler(); /* let the GUI do its work */
  delay(5);

  /* PRINTS TIME ON CENTRAL LABEL  */
  lv_label_set_text(ui_Label14, rtc.formatDateTime(PCF_TIMEFORMAT_HM));


  /* TURN ON SCREEN WITH BUTTON */
  if (digitalRead(34) == LOW)
  {
    digitalWrite(21, HIGH);
    Serial.println("Screen on from button (not sleeping)");
    delay(10000); // VERIFY THAT DELAY DOESN'T MESS UP COUNTERS...
    digitalWrite(21, LOW);
  }

  
  /* syncing to whole quarter. Only once every program run (flag) */
  if (!already_synced)
  {
    Serial.println("time_seconds:");
    Serial.println(time_seconds);
    Serial.println("waiting:");
    Serial.println(wait_to_sync);
    delay(wait_to_sync * 1000);
    Serial.println("synced to whole quarter");
    already_synced = true;
  }

  /* compare time_seconds and associate pointer to lvgl arc - to be done continuously */

  if (time_seconds >= 12 * 60 * 60) time_seconds = (time_seconds - 12 * 60 * 60); // convert time to 12h
  if (time_seconds < 15 * 60) ui_Arc_pointer = &ui_Arc2; // store ui_Arc2 address into pointer
  else if (time_seconds < 30 * 60) ui_Arc_pointer = &ui_Arc1;
  else if (time_seconds < 45 * 60) ui_Arc_pointer = &ui_Arc3;
  else if (time_seconds < 60 * 60) ui_Arc_pointer = &ui_Arc4;
  else if (time_seconds < 75 * 60) ui_Arc_pointer = &ui_Arc5;
  else if (time_seconds < 90 * 60) ui_Arc_pointer = &ui_Arc6;
  else if (time_seconds < 105 * 60) ui_Arc_pointer = &ui_Arc7;
  else if (time_seconds < 120 * 60) ui_Arc_pointer = &ui_Arc8;
  else if (time_seconds < 135 * 60) ui_Arc_pointer = &ui_Arc9;
  else if (time_seconds < 150 * 60) ui_Arc_pointer = &ui_Arc10;
  else if (time_seconds < 165 * 60) ui_Arc_pointer = &ui_Arc11;
  else if (time_seconds < 180 * 60) ui_Arc_pointer = &ui_Arc12;
  else if (time_seconds < 195 * 60) ui_Arc_pointer = &ui_Arc13;
  else if (time_seconds < 210 * 60) ui_Arc_pointer = &ui_Arc14;
  else if (time_seconds < 225 * 60) ui_Arc_pointer = &ui_Arc15;
  else if (time_seconds < 240 * 60) ui_Arc_pointer = &ui_Arc16;
  else if (time_seconds < 255 * 60) ui_Arc_pointer = &ui_Arc17;
  else if (time_seconds < 270 * 60) ui_Arc_pointer = &ui_Arc18;
  else if (time_seconds < 285 * 60) ui_Arc_pointer = &ui_Arc19;
  else if (time_seconds < 300 * 60) ui_Arc_pointer = &ui_Arc20;
  else if (time_seconds < 315 * 60) ui_Arc_pointer = &ui_Arc21;
  else if (time_seconds < 330 * 60) ui_Arc_pointer = &ui_Arc22;
  else if (time_seconds < 345 * 60) ui_Arc_pointer = &ui_Arc23;
  else if (time_seconds < 360 * 60) ui_Arc_pointer = &ui_Arc24;
  else if (time_seconds < 375 * 60) ui_Arc_pointer = &ui_Arc25;
  else if (time_seconds < 390 * 60) ui_Arc_pointer = &ui_Arc26;
  else if (time_seconds < 405 * 60) ui_Arc_pointer = &ui_Arc27;
  else if (time_seconds < 405 * 60) ui_Arc_pointer = &ui_Arc27;
  else if (time_seconds < 420 * 60) ui_Arc_pointer = &ui_Arc28;
  else if (time_seconds < 435 * 60) ui_Arc_pointer = &ui_Arc29;
  else if (time_seconds < 450 * 60) ui_Arc_pointer = &ui_Arc30;
  else if (time_seconds < 465 * 60) ui_Arc_pointer = &ui_Arc31;
  else if (time_seconds < 480 * 60) ui_Arc_pointer = &ui_Arc32;
  else if (time_seconds < 495 * 60) ui_Arc_pointer = &ui_Arc33;
  else if (time_seconds < 510 * 60) ui_Arc_pointer = &ui_Arc34;
  else if (time_seconds < 525 * 60) ui_Arc_pointer = &ui_Arc35;
  else if (time_seconds < 540 * 60) ui_Arc_pointer = &ui_Arc36;
  else if (time_seconds < 555 * 60) ui_Arc_pointer = &ui_Arc37;
  else if (time_seconds < 570 * 60) ui_Arc_pointer = &ui_Arc38;
  else if (time_seconds < 585 * 60) ui_Arc_pointer = &ui_Arc39;
  else if (time_seconds < 600 * 60) ui_Arc_pointer = &ui_Arc40;
  else if (time_seconds < 615 * 60) ui_Arc_pointer = &ui_Arc41;
  else if (time_seconds < 630 * 60) ui_Arc_pointer = &ui_Arc42;
  else if (time_seconds < 645 * 60) ui_Arc_pointer = &ui_Arc43;
  else if (time_seconds < 660 * 60) ui_Arc_pointer = &ui_Arc44;
  else if (time_seconds < 675 * 60) ui_Arc_pointer = &ui_Arc45;
  else if (time_seconds < 690 * 60) ui_Arc_pointer = &ui_Arc46;
  else if (time_seconds < 705 * 60) ui_Arc_pointer = &ui_Arc47;
  else if (time_seconds < 720 * 60) ui_Arc_pointer = &ui_Arc48;

  /* set start time for first time (only once)  */
  if (!already_set_start_time)
  {
    start_time = millis();
    already_set_start_time = true;
  }
  /* updated at every loop */
  timer = millis() - start_time;

  /* all the next ifs are checked at every loop and the program stays some loops in each of them based on timer */
  if (timer < go_buzz_1 && !already_slept_1)
  {
    Serial.println("sleep1");
    digitalWrite(21, LOW);
    esp_sleep_enable_timer_wakeup(go_buzz_1 * 1000);
    esp_sleep_enable_ext0_wakeup(GPIO_NUM_34, LOW); // 21 AGO
    esp_light_sleep_start();
    if (ESP_SLEEP_WAKEUP_EXT0)
    {
      digitalWrite(21, HIGH);
      Serial.println("Waken up from first sleep");
      delay(10000);
      Serial.println("Going back to first sleep");
      digitalWrite(21, LOW);
      esp_light_sleep_start();
    }
    already_slept_1 = true;
    digitalWrite(21, HIGH);
    Serial.println("slept1");
  }
  if (timer >= go_buzz_1 && timer < end_buzz_1)
  {
    digitalWrite(4, HIGH);
    // Serial.println("buzz on 1");

  }
  else if (timer >= end_buzz_1 && timer < go_buzz_2)
  {
    digitalWrite(4, LOW);
    // Serial.println("buzz off 1");

  }
  else if (timer >= go_buzz_2 && timer < end_buzz_2)
  {
    digitalWrite(4, HIGH);
    // Serial.println("buzz on 2");

  }
  else if (timer >= end_buzz_2 && timer < go_buzz_3)
  {
    digitalWrite(4, LOW);
    // Serial.println("buzz off 2");

  }
  else if (timer >= go_buzz_3 && timer < end_buzz_3)
  {
    digitalWrite(4, HIGH);
    // Serial.println("buzz on 3");

  }
  else if (timer >= end_buzz_3 && timer < go_buzz_4)
  {
    digitalWrite(4, LOW);
    // Serial.println("buzz off 3");

  }
  else if (timer >= go_buzz_4 && timer < end_buzz_4)
  {
    digitalWrite(4, HIGH);
    // Serial.println("buzz on 4");

  }
  else if (timer >= end_buzz_4 && timer < end_buzz_4 + 60000)
  {
    digitalWrite(4, LOW);
    // Serial.println("buzz off 2");
    if (digitalRead(35) == LOW)  // tolto && !already_printed - if button pressed once set the arc color to green (still need to add the case of button pressed twice)
    {
      lv_obj_set_style_arc_color(*ui_Arc_pointer, lv_color_hex(0x40FF4B), LV_PART_MAIN);
    }
    if (digitalRead(34) == LOW)
    {
      lv_obj_set_style_arc_color(*ui_Arc_pointer, lv_color_hex(0xFF4048), LV_PART_MAIN);
    }

  }

  else if (timer >= end_buzz_4 + 60000 && timer < end_buzz_4 + 900000 && !already_slept_2)
  {
    Serial.println("sleep2");
    digitalWrite(21, LOW);
    esp_sleep_enable_timer_wakeup(delta * 1000);
    esp_sleep_enable_ext0_wakeup(GPIO_NUM_34, LOW); // 21 AGO
    esp_light_sleep_start();
    if (ESP_SLEEP_WAKEUP_EXT0)
    {
      digitalWrite(21, HIGH);
      Serial.println("Waken up from second sleep");
      delay(10000);
      Serial.println("Going back to second sleep");
      digitalWrite(21, LOW);
      esp_light_sleep_start();
    }
    already_slept_2 = true;
    // digitalWrite(21, HIGH); 21AGO
    Serial.println("slept2");
  }

  else if (timer >= 900000)  // after 15 minutes reset and restart - does this only once, because at next loop timer = millis - start time
  {
    start_time = millis();
    end_buzz_1 = go_buzz_1 + 500;
    go_buzz_2 = go_buzz_1 + 1500;
    end_buzz_2 = go_buzz_1 + 2000;
    go_buzz_3 = go_buzz_1 + 2500;
    end_buzz_3 = go_buzz_1 + 3000;
    go_buzz_4 = go_buzz_1 + 3500;
    end_buzz_4 = go_buzz_1 + 4000;
    delta = 900000 - (end_buzz_4 + 60000); // wait 60sec for input after end of buzzes
    Serial.println("go_buzz_1:");
    Serial.println(go_buzz_1);
    already_slept_1 = false;
    already_slept_2 = false;

  }

}

It is not a memory-problem. On compile-time
You are using a grafic-diplays which requires a lot of RAM at runtime.
This still might be a memory-problem that the initialisation of the grafic-displaybuffer grabs too much RAM.
But this is a wild speculation.

I still can believe that the code is just crashing from declaring a variable as global.

Are you sure that the ESP32 crashes even before
"Setup-Start" is printed to the serial monitor??

The compiler-log says

Chip is ESP32-PICO-V3-02 (revision v3.0)

Features: WiFi, BT, Dual Core, 240MHz, Embedded Flash, 
Embedded PSRAM, VRef calibration in efuse, Coding Scheme None

Are you sure that this is the correct board?
Chip is ESP32- PICO-V3-02 (revision v3.0)
Embedded PSRAM are you sure that his board has " Embedded PSRAM ?

Post a screen-shot what is displayed when you click on Tools.

best regards Stefan

The board is a T-Micro32 Plus ESP32 based on the ESP32 pico, I am pretty sure the board settings are correct. I took them from the Lilygo product GitHub page. I attach a screenshot of the github page instructions and of my arduino tools window.

Leaving aside for the moment the issue of the code crashing if I make some variables global, which I can avoid for now keeping them local, does anybody have an idea of how to create a timed light sleep routine which can be interrupted just for 10 seconds by a button wake-up and then be resumed without resetting the original timer?

No I don't know. Another idea is to store the time when the sleeping starts to store this time in a RTC-RAM-variable which will keep its value even after a reset and then calculate the rest of the sleeping-time new based on the original starttime.

1 Like

Thanks! I thought about something like that as well, but was hoping there could be an easier way. I’ll just have to do the work :slight_smile:

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