M5Paper wakeup cause

  • Hello,

    I'm playing around with the M5Paper RTC and I'm stuck on differentiating between a restart caused by pressing the reset button, and a restart caused by a shutdown() with a RTC IRQ wakeup.

    I'm writing a simple clock application that updates once a minute with the following properties:

    • On boot I paint a decorative frame (I actually pull it by http), connect to ntp and setup the RTC clock. Finally I draw the time, and do a shutdown(60) to wake up in a minute.
    • After a minute I want to wake up, draw the time, and go back to sleep.

    So I did all the initialization in setup() and initialized the RTC, setup the font cache, and then went to sleep for 60s. But when I wake up after 60s I need to know whether the RTC has already been initialized, and whether I have already painted the clock frame. Right now I do all the setup once a minute.

    The ESP itself has a wake up "reason". But how would I access it on the M5Paper? And does it work in the context of the BM8563 RTC?


  • Hello @dov

    the RTC clock has a timer flag which when set tells you that the RTC timer has woken M5Paper; if not set then it was a regular restart. I've implemented that for M5CoreInk (which has a similar architecture) here.

    BTW: The wake up reason of the ESP32 doesn't help you here. As far as the ESP32 is concerned it's a regular start in both cases as the shutdown kills the power to the ESP32 completely. (Only when the ESP32 stays powered and goes into deep sleep or light sleep you can use the ESP32 wake up reason.)


  • You could use the EEPROM to store the state in - e.g. last time the device went to sleep, last time NTP sync happened, etc. - and use that to decide which path of logic you need to follow.

    For example, this could be the full flow:


    1. Get EEPROM, extract last NTP sync (last_ntp_sync), last boot time (last_boot), and last requested sleep length (sleep_duration)
    2. Get RTC time (rtc_time)
    3. If last_ntp_sync is empty, go to first_boot()
    4. If last_boot is empty, go to first_boot()
    5. If rtc_time - last_boot < sleep_duration (maybe add some wiggle room here, 1-2s should be fine), go to manual_wakeup()
    6. Otherwise, go to rtc_wakeup()


    1. Connect to WiFi
    2. Request date and time from NTP = new_rtc_time
    3. Update RTC with new_rtc_time
    4. Update EEPROM's last_ntp_sync and last_boot_time
    5. Proceed to draw_clock()


    1. Check if last_ntp_sync is not too old (e.g. you'd probably want to sync with NTP daily)
    2. If last_ntp_sync is too old, go to a method that syncs RTC time
    3. Update EEPROM's last_boot_time
    4. Proceed to draw_clock()


    1. Do the whole NTP check dance again (probably worth organising into a separate method)
    2. Do whatever you want to do if the device wakeup happened due to the button press
    3. Proceed to draw_clock()

    Obviously extend it to your liking, but by storing these values, you can compare the last stored date with the RTC time, and act accordingly. It's not as elegant as e.g. having a proper boot reason, but it works.

  • @dov I'm very new to the M5Paper, but I'm wondering if you couldn't use the esp_deep_sleep_start() instead of shutdown because this will keep the RTC going and shutdown everything else.

    In theory, you might be able to call esp_err_tesp_sleep_enable_timer_wakeup() with an appropriate duration and then simply continue. According to the documentation the Wifi connection data is kept as well.

    I'm currently trying to work on something like this as well.