Build a DIY E-Ink Smart Calendar Display with ESP32
Pull your Google Calendar, weather forecast and to-do list onto a paper-thin display that runs for months on a single charge. The ultimate refrigerator art for 2026.
Why an e-ink dashboard?
Phones are wonderful, but they hide information behind apps and lock screens. An e-ink calendar lives on the wall like a painting; it consumes about 0 watts when idle, refreshes a few times a day, and acts as a quiet, ambient anchor for your week. In 2026, with seven-color e-paper panels under $60 and ESP32-S3 boards under $10, this is the cheapest "AI-era ambient display" you can build.
Bill of materials (~ $75 USD)
| Part | Why | Cost |
|---|---|---|
| ESP32-S3 dev board | Wi-Fi, deep sleep, USB-C | $8 |
| Waveshare 7.5" e-paper (800×480) | Sweet spot of size and price | $48 |
| 3.7V 5000 mAh LiPo | Months of runtime | $12 |
| TP4056 charge module | Safe USB charging | $2 |
| 3D-printed wood-veneer frame | Aesthetic — matters | $5 |
The architecture in one picture
Step 1 — Wire the panel
The 7.5" Waveshare panel uses SPI. Connect VCC→3.3V, GND→GND, DIN→GPIO11, CLK→GPIO12, CS→GPIO10, DC→GPIO9, RST→GPIO8, BUSY→GPIO7. Keep wires short. Twisted-pair the SPI lines if you go beyond 15 cm.
Step 2 — Render on the server, not the MCU
Drawing fonts and layouts on the ESP32 wastes battery and space. Instead, run a tiny Cloudflare Worker (free tier) that renders your dashboard with HTML+Canvas, then returns a 1-bit BMP. The MCU just downloads and pushes pixels.
// pseudo: Cloudflare Worker
export default {
async fetch(req, env) {
const events = await getCalendar(env.CAL_TOKEN);
const weather = await getWeather('40.7,-74.0');
const png = await renderHTMLToImage(template(events, weather));
return new Response(pngToBitplane(png), { headers: { 'content-type':'application/octet-stream' }});
}
};
Step 3 — ESP32 firmware
void wakeAndPaint() {
WiFi.begin(SSID, PASS);
while (WiFi.status() != WL_CONNECTED) delay(50);
HTTPClient http;
http.begin("https://your-worker.workers.dev/dash");
if (http.GET() == 200) {
WiFiClient* s = http.getStreamPtr();
epd.begin();
epd.streamWrite(s, 800*480/8); // 1-bit
epd.refresh();
}
esp_sleep_enable_timer_wakeup(6 * 3600ULL * 1000000ULL);
esp_deep_sleep_start();
}
Step 4 — Battery math
Average current matters more than peak. Refreshing 4×/day for 90 seconds at 80 mA, plus 23 h 54 min in deep sleep at 25 ยตA, comes out to ~0.95 mAh/day. A 5000 mAh cell at 70% efficiency = ~3,700 days of theoretical runtime. Real-world losses (Wi-Fi reconnects, cold weather) drop this to ~150 days. Still good.
Make it beautiful
The difference between "weekend project" and "people ask where you bought it" is the frame. Print a wood-veneer bezel, route a 2 mm channel for the ribbon cable, and finish with matte beeswax. Aesthetic is not a luxury here — it determines whether your spouse lets it stay on the wall.
Where to take it next
- Ship it as a product — Mudita Pure and TRMNL prove the market exists.
- Add a touch button on the side to "snooze" the next event.
- Train a tiny on-device summary model to write the daily intro.
Comments
Post a Comment