Hi, first timer here!
Wanted to share some significant (~40%) power saving gains I've achieved by a couple of simple tweaks to @ZinggJM 's awesome library ![]()
When looking at the _waitWhileBusy function I noticed that it polls the 'busy' pin twice per millisecond (one before the delay, and again after the delay).
I setup a quick test, where I do one partial update to the epaper and run a counter on that loop: my epaper goes over the loop some 420 times, for 1 single partial update (that's polling the busy pin some 840 times for 1 partial update!).
I figured, since epaper is slow by nature, I'd rather have this loop run a bit less frequently, and instead have my esp32 enjoy some more time in light-sleep (I use esp-idf in my project, which can automatically set the MCU to enter light sleep when there's nothing to do).
The changes I implemented sum up as:
- polling the pin once per loop iteration, instead of twice
- delay for 40ms, instead of 1ms.
this way, in my case the loop is going to run ~10 - 12 times per partial update, as opposed to ~420 times. This saves considerable power, specially when running on batteries.
in diff format, these are the changes I made for above point:
diff --git a/src/GxEPD2_EPD.cpp b/src/GxEPD2_EPD.cpp
index 2f06ff2..af67f0f 100644
--- a/src/GxEPD2_EPD.cpp
+++ b/src/GxEPD2_EPD.cpp
@@ -140,12 +140,14 @@ void GxEPD2_EPD::_waitWhileBusy(const char* comment, uint16_t busy_time)
{
delay(1); // add some margin to become active
unsigned long start = micros();
+ //int busy_count = 0;
while (1)
{
+ //busy_count++;
if (digitalRead(_busy) != _busy_level) break;
if (_busy_callback) _busy_callback(_busy_callback_parameter);
- else delay(1);
- if (digitalRead(_busy) != _busy_level) break;
+ else delay(40); //with previous delay(1) this loops ~420 times for a partial update. Reduce to ~10 times.
+ //if (digitalRead(_busy) != _busy_level) break;
if (micros() - start > _busy_timeout)
{
Serial.println("Busy Timeout!");
@@ -155,6 +157,7 @@ void GxEPD2_EPD::_waitWhileBusy(const char* comment, uint16_t busy_time)
yield(); // avoid wdt
#endif
}
+ //printf("busy loop iterations: %d\n", busy_count);
if (comment)
{
#if !defined(DISABLE_DIAGNOSTIC_OUTPUT)
The second tweak might be more specific for my epaper, worth sharing anyway!
In this case, I simply edit GxEPD2_290::_PowerOff to combine power off and hibernate into one. For some reason, this executes 200ms faster than calling hibernate() separately.
diff --git a/src/epd/GxEPD2_290_BS.cpp b/src/epd/GxEPD2_290_BS.cpp
index 7e3ead4..8d5793c 100644
--- a/src/epd/GxEPD2_290_BS.cpp
+++ b/src/epd/GxEPD2_290_BS.cpp
@@ -340,6 +340,14 @@ void GxEPD2_290_BS::_PowerOff()
}
_power_is_on = false;
_using_partial_mode = false;
+
+ if (_rst >= 0)
+ {
+ _writeCommand(0x10); // deep sleep mode
+ _writeData(0x1); // enter deep sleep
+ _hibernating = true;
+ _init_display_done = false;
+ }
}
My project is a simple clock that updates every 1 minute, running on esp32 and powered by a 950mAh battery. Before these tweaks, I was getting an estimated 3 months on battery. After tweaks, new estimate is a little above 5 months ![]()
There's probably some better ways to tweak the busy loop for efficiency. Happy hacking!