Problem with M5.shutdown and deep sleep - M5.shutdown example does not run anymore



  • Hi all,
    after I received the m5Paper a few days ago, I was very disappointed with its power consumption. With a small test program that should simply display the actual time updated every minute, the battery was low after a few hours using only EPD.Sleep(). I found several posts describing the power and battery management of the M5Paper as very poor from design. While searching this forum i came across the two ways how to save power consumption.

    1. M5.shutdown which only works if the M5Paper is not connected to USB Power Supply
    2. esp_deep_sleep_start() with esp_sleep_enable_timer_wakeup and gpio_hold_en((gpio_num_t)M5EPD_MAIN_PWR_PIN) before.

    Because I wanted to compare these two ways in there ability to save power better I first tested the M5.shutdown example from m5-docs.

    #include <M5EPD.h>

    M5EPD_Canvas canvas(&M5.EPD);

    void setup()
    {
    M5.begin();
    M5.EPD.SetRotation(90);
    M5.TP.SetRotation(90);
    M5.EPD.Clear(true);
    M5.RTC.begin();
    canvas.createCanvas(540, 960);
    canvas.setTextSize(3);
    canvas.drawString("Press PWR Btn for sleep!", 45, 350);
    canvas.drawString("after 5 sec wakeup!", 70, 450);
    canvas.pushCanvas(0,0,UPDATE_MODE_DU4);
    }

    void loop()
    {
    if(M5.BtnP.wasPressed()){
    canvas.drawString("I'm going to sleep.zzzZZZ~", 45, 550);
    canvas.pushCanvas(0,0,UPDATE_MODE_DU4);
    delay(1000);
    M5.shutdown(5);
    }
    M5.update();
    delay(100);
    }

    After that was successful, i did several tests with the esp_deep_sleep_start() function.

    Since these did not lead to the goal, I wanted to expand the M5.shutdown example more to my requirements.
    Now I had to realize that this simple example no longer runs on my M5Paper.
    After pressing the button, the message "I'm going to slepp.zzzZZZ" appears in the display, but nothing happens.
    It makes no difference whether the M5paper is connected to the USB or not.

    Is it possible that the previous tests with gpio_hold_en((gpio_num_t)M5EPD_MAIN_PWR_PIN) set something permanently,
    which is now interfering with the execution of m5.shutdown and its waking up?

    Any hints for solving this problem?

    Thx



  • Hello @herb

    no, the gpio_hold_en() is not permanent. That said, having called gpio_hold_en() in the previously flashed code and with the M5Paper never fully powered off, then yes, even with new code, not calling the gpio_hold_en() function anymore, the M5Paper will be kept from shutting down programmatically.

    To get rid of it you need to fully power off M5Paper by pressing the power off button in the back while running from battery.

    However if you still call the gpio_hold_en() function in the code your M5Paper is running, then yes, it will prevent a shutdown (even when running from battery).

    If for whatever reason you need gpio_hold_en() in your code then you can call the opposite function gpio_hold_dis() just before going into shutdown.

    Thanks
    Felix



  • Hello Felix,
    thanks for your support.

    I tried your hints, but unfortunately without success. Due to the lack of documentation, it's not clear to me how long I have to press the button on the back.
    Whether I press briefly or long, nothing changes in the behavior. The device will not reboot.
    The text on the display is only updated when I connect it to the USB again, i.e. the program restarts again.

    In the serial monitor I can observe sometimes the following:
    Brownout detector was triggered
    M5EPD initializing...OK

    Taking your other hint into account, I replaced the loop part of the program as follows to disable GPIO_hold

    void loop()
    {
    if(M5.BtnP.wasPressed()){
    canvas.drawString("I'm going to sleep.zzzZZZ~", 45, 550);
    canvas.pushCanvas(0,0,UPDATE_MODE_DU4);
    gpio_hold_dis((gpio_num_t)M5EPD_MAIN_PWR_PIN);
    delay(1000);
    M5.shutdown(5);
    }
    M5.update();
    delay(100);
    }

    That doesn't change the behavior either. No programatic wakeup is possible :-(
    Only if I connect the device back to usb it will restart again.

    Is it possible to reset the whole ESP device with all of its components and registers incl. RTC to factory defaults?

    Thank you for any advice.

    Herb



  • Hello @herb

    I think your battery might not be charged enough. It sounds like the shutdown works, but then it fails to reboot due to a too weak battery. (The brownout detector triggered would suggest that as well.) I suggest you let it charge from USB for a couple of hours and then try again.

    The button in the back has two functions: is a reset when running from USB and a power off when running from battery. When running from USB press it until M5Paper reboots.
    When running from battery pressing it for about 2 seconds should power off M5Paper. (It does nothing if M5Paper is already powered off.)

    BTW: To know better about whether M5Paper is running or not I've attached an LED to one of the Groove connectors GND and 5 V pins as an indicator.

    AFAIK there is no such thing as a whole ESP reset. If you want to get rid of whatever program is in flash you could use M5Burners Erase function.

    Thanks
    Felix



  • Thank you Felix,
    long-pressing the button on the back in battery mode doesn't change anything.

    I'm really frustrated with this device. The whole behavior is no longer understandable - not only with the shutdown function.

    After switching back to my real application, an adtl. problem occurs that I can't explain.

    This is a snippet of my code:

    ...
    
    M5.RTC.getTime(&RTCtime);
    M5.RTC.getDate(&RTCDate);
    
    sprintf(timeStrbuff,"%02d.%02d.%d --- %02d:%02d",
                        RTCDate.day,RTCDate.mon,RTCDate.year,
                        RTCtime.hour,RTCtime.min);
    
    status_oben.drawString(timeStrbuff, 150, 17);
    Serial.print("Zeit/Datum im RTC: ");
    Serial.println (timeStrbuff);
    
    uint32_t vol = M5.getBatteryVoltage();
    float vol_f = vol / 1000.0f;
    
    status_oben.drawFloat(vol_f,2,630,17);
    
    status_unten.drawNumber(bootCount,630,17);
    status_oben.pushCanvas(130,27,UPDATE_MODE_GC16);   
    
    status_unten.drawString("Ich gehe gleich schlafen", 150, 17);
    status_unten.pushCanvas(130,457,UPDATE_MODE_GC16);
    
    // until this point all is ok
    
    sleep(1000);
    Serial.println("Boot number: " + String(bootCount));
    sleep(10000);
    
    
    
      if (bootCount > 1) {
        status_unten.drawString("Ich gehe schlafen", 150, 17);
        status_unten.pushCanvas(130,457,UPDATE_MODE_GC16);
        preferences.putUInt("Boot",1);
        Serial.println("Ich gehe schlafen");
        delay(5000);
        M5.shutdown(30);
      }
    }
    
    void loop()
    {  
      status_unten.drawString("In der Schleife", 150, 17);
      status_unten.pushCanvas(130,457,UPDATE_MODE_GC16);
      if (M5.BtnP.wasPressed()) {
        delay(1000);
        M5.shutdown(60); // shut donw now and wake up after 60 seconds
      }
    
    M5.update();
    delay(100);
    }
    

    Within the very first run with bootCount=0 it should go until the loop, so I can initiate the first shutdown manually after disconnecting from usb.
    bootCount is stored as a preference, so it would not be deleted after the next reboot and will incremented at the beginning of every restart.

    After this initial restart the program should never reach the loop, because the condition should be met.
    But since the shutdown() doesn't work bootCount was incremented every time. I can see on the display that the bootCount keeps increasing.
    So I realized that the code within the if condition was never processed.

    Because I did not understand why, I went backwards within my code and placed some debugging lines in it.
    The string "Ich gehe gleich schlafen" is still being written to the display. If the device is still connected to the PC the next line after the sleep should also be executed.
    But that doesn't happen. I really can't understand why...

    BTW: the brownout message also occurs when the device has been charged for several hours.

    Thanks
    Herb



  • Hello @herb

    I think to properly write a preference you'll need to call begin() first, write your pref, then finally call end(). Eg.

    preferences.begin("MyBootPref", false); // open with read / write access
    preferences.putUInt("MyBootCount",1); // write pref
    preferences.end(); // close prefrences space
    

    Please see full reference here.

    It might be useful to check the return value of preferences.putUInt() to see if it there was an error.

    BTW: how do you observe the Serial.println() statements when running from battery?

    Thanks
    Felix



  • Hello Felix, I found the reason why the program has always stopped after "// until this point all is ok" . :-)
    It was the "sleep" before and after

    Serial.println("Boot number: " + String(bootCount));
    

    It should only be a delay for better debugging and watching on the serial monitor.
    Changing it to delay() all works fine including the shutdown and reboot. Hooray.

    BTW.
    Your mentioned preferences.begin was already in the code at the beginning. The preferences.end() I placed at the end.
    Thanks for this advice.

    The serial.println's were only for debugging to find the reason why the program stops before the shutdown.
    Because the shutdown statement was never reached, it didn't matter if it was plugged into the usb or not.

    Now I'm happy. Regards Herb



  • Hello @herb

    great, I am happy to read you figured it out. Thank you for letting me know.

    Thanks
    Felix