Demo epaper clock - martinberlin/cale-idf GitHub Wiki

Just one day before summer holidays I had time for a day sprint to create something fun and also educational. It's in branch:

git checkout refactor/oop

Described in Issue 8 but let's summarize it our goal in a short sentence:

The mission is to make an epaper digital clock with the lowest power consumption in ESP32

It will do this 3 things and this three things only:

  • It will Sync with internet time using our own super fast IoT API to retrieve time once a day
  • The epaper will render the day, Month and in next line the Hour:Minute just as any digital clock
  • It will go to seep N minutes defined in the beginning of sleepMinutes (Does not matter, can be 2 minutes, 5 minutes, etc)

ESP32 deep-sleep-clock demo

This example is also available for PlasticLogic small displays in Arduino-esp32 version

Arduino-ESP32 In the picture, the display used is 1.1" UC8156, with a small SPI adapter that I designed myself for TinyPICO ESP32.

Disclaimer: Because of the nature of ESP32 deepsleep this clock it's not precise. It may differ 4 or 5 minutes a day, depending on temperature and other factors that are deeply out of my understanding. That's precisely why is cool to research and use this concepts for other Internet of the Things applications.

The idea is to have fun making an over-engineered, imprecise, and cool ESP32 digital epaper clock that is fully customizable. Along the journey you can gain experience with many Espressif things, like NVS key-value storage, epaper displays and using C++ in ESP-IDF.

Learning IDF

It's a nice example to learn how to store values in Non Volatile Storage of the ESP32 where you can store value types like integers and \0 terminated strings in a way that is persisted even if the chip is powered off. I call \0 terminated strings char arrays but I'm not sure if that is the best denomination. Is also interesting to practice doing short internet queries and to learn how to do it in Espressif's own IoT development framework without any Arduino boilerplate functions on top. The ESP32 consumes quite a lot when it's connected to WiFi so it's smart to connect only for short times and build something that can work long days with small batteries. That's why this clock offers the option to sync up to two times a day, but of course you can update it, and do the Sync request when (HOUR%3 == 0) as an example, to update it every 3 hours. As you update more often, it will be more precise and at the same the battery lifetime will be shortened.

Todos and not part of this short day sprint

FIX partialUpdate in gdew027w3 class. This is a perfect scenario to only update the HH:MM part with a fast refresh instead of doing a full update of the whole display.

Models of epaper and code walk

Use any epaper model. Just modify the class as described in this WiKi, as default it uses the small display of a TTGO T5s (Also Good display):

#include <gdew027w3.h>

How often will your clock be updated? This will also affect the battery lifetime:

// Clock will refresh each N minutes
int sleepMinutes = 5;

Timezone setting Make sure to adjust the Europe/Berlin to your city timezone otherwise you will see Berlin time:

const char* timeQuery = "http://fs.fasani.de/api/?q=date&timezone=Europe/Berlin&f=Hi";
const char* dayQuery = "http://fs.fasani.de/api/?q=date&timezone=Europe/Berlin&f=D+d,+M";

Do not change Hi since we read it per char. But feel free to change the Day, Month D+d,+M default format checking PHP date() section of the manual.

At this hour(s) the clock will connect and sync time or date with the www

// Important: Leave syncHour1 in 0 for the first run! (So it thinks automatically with internet time)
uint8_t syncHour1 = 0;     // At this hour in the morning the clock will Sync with internet time
uint8_t syncHour2 = 13;    // Same here, 2nd request to Sync hour 
uint8_t syncHourDate = 7; // The date request will be done at this hour, only once a day

Partial update depending on your display

In the function updateClock() at the end there is a new line that does a partial update using the CalEPD method updateWindow:

// Note this x,y,width,height coordinates represent the bounding box where the update takes place:
display.updateWindow(0, 0, display.width()-30, display.height()/2, true);

If you use another display, bigger or smaller, than the demo you will need to change this box coordinates otherwise it will not update the full digital clock. With further ado, if you want to optimize this even more, then only the clock part should be updated every N minutes and the day part only when the day update takes place.

Compiling

Select what is the compile target:

idf.py set-target esp32

Also will work in esp32s2 if you want to use the S2 for this.

That's mostly all configuration. Of course needs as any other display, the PIN configuration, that can be done using:

idf.py menuconfig

Make sure to configure: Display configuration - Epaper GPIOs that connect to ESP32 CALE configuration - WiFi credentials and display rotation (0 to 3, 90° rotation each) Only those 3 are important.

Select source:

Last but not least, don't forget this lives in branch refactor/oop and not in master. To select the C++ target that is compiled as the main program just uncomment the SRCS line in main/CMakeLists.txt

idf_component_register(
# Main CALE 
#SRCS "cale.cpp"

SRCS "demo-sleep-clock.cpp"

#SRCS "demo-fonts.cpp"
#SRCS "demo-epaper.cpp"
INCLUDE_DIRS ".")

Doing that only demo-sleep-clock.cpp will be compiled and flashed as your main program:

idf.py flash monitor

Under "Display configuration". I left in the directory config-examples some demo configurations including the T5s pins.