How I built a minimalist dashboard using an ESP32 board and an e-paper display with Python.

I was genuinely excited when the long-awaited delivery finally landed on my desk. Among other components, the most interesting ones were:

Classic ESP32-WROOM board (bare version, with empty flash)

2.9" E-paper Module from WeAct Studio (resolution: 128×296)

un_plate un_display

**When you unwrap a new weekend obsession

This wasn’t my first encounter with microcontrollers. Back in my marine electrician days, I’ve dealt with more PLCs, control modules, and rugged automation units than I care to count. I’ve even done some emergency non-standard modifications at sea, sometimes without documentation, just intuition, a multimeter, and lots of coffee.

But this was my first ESP32 Python/MicroPython project from scratch.

 

Development: Environment / Display

Initially, I tried using PyMakr with VS Code, but found it clunky and unreliable for live updates. 

Instead, I went with a more minimalistic workflow:

Writing scripts mostly locally (the main code is still in the IDE)

Using ampy (Adafruit MicroPython Tool) to upload and run them via the terminal

ampy

>Tip: ampy is a small but mighty command-line tool for pushing Python code to microcontrollers running MicroPython or CircuitPython.

E-paper display

Finding clear and complete info on connecting e-paper modules wasn’t as easy as I expected - forums were full of conflicting pinouts.

So here’s the exact mapping I used for my 2.9" WeAct Studio E-paper with ESP32:

pins_display pins_plate

E-paper pins ESP32 GPIO D
BUSY GPIO D4
RES(RST) GPIO D16
DC GPIO D17
CS GPIO D5
SCL(CLK) GPIO D18
SDA(DIN) GPIO D23
GND GND
VCC 3.3V

**Double-check your connections! E-paper displays are sensitive, and one wrong wire can damage the board.

 

Software: Widgets / APIs

To control the display and draw widgets, I used Peter Hinch’s excellent MicroPython GUI library for e-paper displays. Big thanks to the author for the great documentation, it really helped me avoid a lot of trial and error.

I started by writing small, standalone widgets and testing each one directly on the display:

Clock (synced via NTP client)

Weather (data fetched from OpenWeatherMap API)

◊ Views from my personal website widget (built a tiny Django REST API)

Pi-hole status widget - fetching status from my Raspberry Pi-hosted Pi-hole instance (although their recent jump to v6 made API integration more "dynamic")

test_clock test_weather

>Known issue: The Pi-hole widget occasionally fails to handle POST requests reliably due to changes in the v6 API structure. According to the Pi-hole forums, a fix is coming in a future patch.

 

Integration: Layout logic

Once all four widgets were tested independently, I started combining them into a single display layout. This was a bit tricky:

The 128x296 resolution doesn’t give you much real estate

No fancy graphic libraries, pixel control was manual

No schematic drawings, just a quick sketch in Excalidraw

scetch_zone

I divided the screen into four zones, one for each widget. In hindsight, the 3.7" or 4.2" display might’ve made things a bit easier.

To improve readability, I used three different font sizes, converted to .py files using Peter Hinch’s font tool. I wrote code to center the text dynamically in each zone - no hardcoded coordinates. I experimented with font sizing and spacing to make sure each widget felt balanced in its space. Despite the limitations, this part of the project was the most creative, turning raw pixels into a clean, readable interface.

 

Final touch: Wrap-up & What's next

To complete the project, I made a simple wooden frame that now sits proudly and aesthetically (at least for me) on my desk.

fdash2

fdash1 fdash3

Next, I’m planning to:

◊ Refactor widget code for better modularity

◊ Maybe migrate to a bigger screen version

Add e-ink refresh optimization (currently it flashes a bit too often)

If you're working on a similar ESP32 + E-Paper, Raspberry Pi project or considering starting one, feel free to fork the repository, contribute, or get in touch. I'd love to connect!

All technical details, including explanations for each file and the libraries used, can be found in the GitHub repository, complete with a detailed README.

You can reach me via the contact page on the website or directly by email: max@pflaumax.dev