Xinyuan-LilyGO / TTGO_TWatch_Library

MIT License
881 stars 283 forks source link

Speed up starting time #92

Open destroyedlolo opened 3 years ago

destroyedlolo commented 3 years ago

Hello,

I'm trying to improve the battery lifetime of my TWatch2020 by playing with deepsleep/Hybernate mode. The problem is ttgo->begin(); tooks about llllooonnnggggg 2s to run, and I'm looking a way to improve.

Before reinventing the wheel, I would like to know if you'd worked on that ? Do you know which part is taking so long ?

My idea is : if this delay is due to peripheral initialization, why not doing it asynchronously on the 2nd core ? So in short :

  1. fast display and RTC initialization on the 1st core to display current time as soon as possible and provide reduced capabilities (no touch screen for example).
  2. in parallel, doing long initialization on the 2nd core.
  3. And then, after those 2s, all capabilities will be available

Do you think it is smart enough or I'm going on the wrong way ?

Thanks

destroyedlolo commented 3 years ago

Hi,

I traced startup procedure : 13:47:26.355 -> starting Domo watch v 0.010100 13:47:26.355 -> Configure watchdog to 30s: 0 13:47:26.355 -> Init watch ... 13:47:26.355 -> I2C : ok 13:47:26.355 -> BL : ok 13:47:26.355 -> BMA : ok 13:47:26.355 -> AXP : ok 13:47:26.355 -> Hwd : ok 13:47:26.355 -> Pwr : ok 13:47:26.918 -> TFT : ok 13:47:26.918 -> Touch : ok 13:47:28.445 -> Sens : ok 13:47:28.445 -> Bl : ok 13:47:28.445 -> Init LVGL ... 13:47:28.445 -> Setting up interrupts ... 13:47:28.777 -> Setting clock to 13:47:23 13:47:28.777 -> Starting up GUI ... 13:47:28.777 -> TimeDate created 13:47:28.777 -> Total heap: 313312 13:47:28.777 -> Free heap: 285232 13:47:28.777 -> Total PSRAM: 4192564 13:47:28.777 -> Free PSRAM: 4187740 13:47:28.777 -> Initialisation completed`

As we can see, the longuest part is : sensor for 1.5 seconds. Is it mandatory to only access the RTC and display something ?

lewisxhe commented 3 years ago

BMA423 needs to send the initial sequence, it takes up most of the startup time, and no sensor is needed to buy shares, please disable it in the source code.

destroyedlolo commented 3 years ago

I'm finishing to fight against LVGL and then try to test with deep sleep. If it's implying some library changes, I'll send you a patch request.

By the way, the BMA will be still powered during deep-sleep, if not explicitly un-powered, right ?

lewisxhe commented 3 years ago

Yes, BMA and esp32 belong to the same power supply

Fusseldieb commented 3 years ago

@destroyedlolo Did you progress?

mfarabee commented 3 years ago

Great work by @destroyedlolo for identifying the startup latency!

I also would like to speed up the startup process. I do not need any sensors in my current application. How can I disable the sensors?

If I did need sensors, could I initialize the watch (start a display), then initialize the sensors as a separate step?

I would appreciate any help in learning where or how to do this. Thanks,

mfarabee commented 3 years ago

Never mind, I figured it out. After digging into the code more, I realized there is an easy way to disable the sensor (BMA432). All that I had to do was undefine the BMA423 in my configuration code and it would bypass the sensor. This sped up the start time considerably.

---- config.h -----

define LILYGO_WATCH_2020_V1 // Use T-Watch2020

undef LILYGO_WATCH_HAS_BMA423 // Disable Accelerometer to improve startup time

include //https://github.com/Xinyuan-LilyGO/TTGO_TWatch_Library

Again, BIG THANKS to @destroyedlolo for identifying the startup latency times!

destroyedlolo commented 3 years ago

Hello, Sorry, I'm busy by other subjects and didn't checked my messages :(

No, unfortunately, I didn't work on that : I'll fight first against hanging / crashes when the Twatch is waken-up. About this latency, as the ESP32 is multi-core, I'm thinking to initialize the BMA on the 2nd one, asynchronously.

Bye

Laurent

Altron-2k20 commented 3 years ago

Why I should initialize the BMA everytime when the CPU wakes up from the deep sleep (of course the boot sequence must reconize that it was a wake up from deep sleep and not a power on) ? The ESP32 and the BMA are powered by the same line so the BMA should stay in that state independently from the CPU. Plus it could be useful to wake up the CPU from deep sleep also by an interrupt from the BMA. Am I missing something ?

mfarabee commented 3 years ago

Since I am not using the BMA in this application, it was easy to just disable it and gain the benefit of improved start time. After doing a lot of research I, think I found something interesting.

I was reading the AXP202 documentation from X-Powers.com and found that there may be a programmable start time delay built into the power management chip. On page 37, it states that: REG 36H: PEK key Parameters Setting Bits 7-6 | Startup time stetting | 00:128ms; 01:3s; 10:1s; 11: 2s | default 01

It looks like if we could set those bits to "00", there would only be a 128ms delay instead of the 3 second delay that is default. In looking at my watch during startup, the delay is pretty close to 3 seconds, which tells me this may be the issue.

There is a function AXP20X_Class::setStartupTime(uint8_t param); that is defined in the axp20x.ccp file. I will have to test this out when I get time to get back to this project.

If this is correct and there is no adverse impact by changing this startup time, this could be the best improvement for startup. I do not know enough about why this startup exists and what the implications are for changing this value. Do you have any insight?

Although there is latency in the BMA initialization, if the power management setting can actually be changes to 128ms, this may be such an improvement that doing anything to the BMA, may not be worth the effort, especially if the BMA is needed for the application.

destroyedlolo commented 3 years ago

The ESP32 and the BMA are powered by the same line so the BMA should stay in that state independently from the CPU.

It's exactly what I'm thinking also. The problem is TTGO initialisation function that does only handle cold (no segregation b/w power-up and deep sleep) and full (including BMA) startup. My thinking is :

It will provide more freedom to manage startup duration. As example, I'm thinking to check first if the BMA is in a valid state. And if not, then only initialize it on the 2nd core.

destroyedlolo commented 3 years ago

I was reading the AXP202 documentation from X-Powers.com and found that there may be a programmable start time delay built into the power management chip. On page 37, it states that: REG 36H: PEK key Parameters Setting Bits 7-6 | Startup time stetting | 00:128ms; 01:3s; 10:1s; 11: 2s | default 01

It isn't the delay to segregate b/w small PEK push and a long one (triggering a power off) ?

Altron-2k20 commented 3 years ago

As far as I understood the Startup time is the time to signal the AXP to power on the system (i.e. you have to keep pressed 3s the bezel button to power on). The same register keep the setting to shutdown the watch (default 6s).

mfarabee commented 3 years ago

I was able to experiment with the setStartupTime and I was wrong. It did not impact the startup time at all. Sorry for that. It does not appear to have anything to do with the press time for startup. I can do a quick press in any setStartupTime mode and the watch starts up in the same way. The startup time does not change for my application, as it still takes about 8 seconds before the screen appears. Some of that time is required for the complex calculations, because this is a Tide Prediction watch and I do multiple table lookups (SPIFFS) and calculations to determine the current tide height for the requested tide station.

I did change the power off time by setting the AXP202_PEK_SHORTPRESS_IRQ. This changes the length of time that you need to hold the PEK to turn off the watch. Unfortunately it still takes a lot of time to get the watch to come on.

bool irq; // global variable

// in setup() procedure pinMode(AXP202_INT, INPUT_PULLUP); attachInterrupt(AXP202_INT, [] { irq = true; }, FALLING); // Must be enabled first, and then clear the interrupt status, otherwise abnormal ttgo->power->enableIRQ(AXP202_PEK_SHORTPRESS_IRQ, true); ttgo->power->clearIRQ(); // Clear interrupt status

destroyedlolo commented 3 years ago

As per my first tests with deep sleep, startup has an incompressible duration of 1.7 seconds (the time for the ESP to start and load codes). I'm checking if I can reduce the TFT but it's adding another 0.5 seconds.

Now, redesigning library's begin() seems mandatory as the touch screen is not working properly after a restart due to a deep sleep : I'm thinking it's because 2 initialisations w/o reset is trashing its controler ...

raomin commented 2 years ago

I've been facing the same issue. Wanted to be able to deepsleep the watch but still have a decent bootup time. Once you have removed the BMA423, you can still improve pretty much the time with tft optimization. tft_espi uses delay() in the tft_init(). I figured out they are not needed in my case. (They might be needed if you actually want to reset a screen but when you boot it from deepsleep, it works fine without). By commenting the delay()s in TFT_eSPI.cpp:1453 and in ST7789_Init.h I finally get a full tft->begin() in less than 50ms!

Thing is it still takes 880ms to reach setup()... So that's 930ms for a start. Better than 2.5s though...

Pelectrome commented 1 year ago

I test all the possible solutions in this issue, raomin is right the most delay is in BMA423 and about 400ms in tft, but i found that there is about 800ms in esp32 boot nothing to do with the library, so if we can find solution about that the startup time will be about 200ms.

jurov commented 2 weeks ago

Can anyone please comment if S3 has similar problem? Whether it is possible to sleep and disable all peripherals to get good battery life and still be able to wake up and show clock without big delay on button press?