An E-Paper Weather Display, Driven by Three Software Layers

E-paper displays are becoming a common sight in retail settings—they offer high contrast, no backlight, and a clean look. But what does it take to run one in your own project? The goal here is to explore the hardware's capabilities by feeding it data from the web, with the end result being a weather display. The challenge isn't the physical hookup; it's that the ESP32 chip driving the screen isn't powerful enough to render complex HTML or parse heavy JSON. The solution is to split the work across three distinct software layers.

The Hardware Setup

Waveshare provides a range of e-paper options. For this build, the 7.5-inch, two-color "e-Paper (G)" display was paired with Waveshare's ESP32 universal driver board. Connecting the two requires attaching the display's ribbon cable to the board; it's a simple process that needs no soldering. The unit is powered via a 5V micro-USB connection.

The ESP32 is a system-on-chip with built-in Wi-Fi and Bluetooth. While the newer models adopt the RISC-V instruction set, the chip itself is well-supported by the Arduino environment, making setup relatively painless. Waveshare provides a demo that lets you upload images via a local web server. Running it requires:

  • Installing the Arduino IDE.
  • Adjusting permissions for the /dev/ACM0 device.
  • Adding the "esp32 by expressif" board bundle via the "Additional Boards Manager URL."
  • Opening the "Loader_esp32wf" example and updating the Wi-Fi name, password, and IP address in the srvr.h tab.

Once the board is on the network, you can connect to its IP address and use the web interface to push a test image to the screen.

A Three-Part Architecture

The ESP32 has 520 KiB of RAM and a 240 MHz clock. It's fine for network requests, but it's not suited for rendering web pages or running layout engines. Rather than burden the embedded device, the logic splits into three separate roles:

  1. The Display Layer (ESP32): The device simply fetches a pre-rendered bitmap from a server and pushes it to the e-paper screen on a loop. In this case, it checks for an update every minute.
  2. The Rendering Layer (Server A): This server receives a URL, fetches the HTML page, renders it with a headless browser, and rasterizes it into a monochrome bitmap suitable for the display.
  3. The Content Layer (Server B): This is the actual website source—for this project, a page that queries a weather API and presents the data in a styled layout that renders well at low resolution.

The ESP32 and Display Lifespan

The Arduino code for the device follows a simple loop: connect to Wi-Fi, fetch the bitmap over HTTP, display it if it's new, and then pause for a minute. The libraries used are the standard Wi-Fi, HTTPClient, and Waveshare's EPD driver.

Because e-paper screens have a limited refresh cycle—roughly a million before degradation begins—the firmware is written to avoid unnecessary screen updates. It only pushes a new frame to the display if the incoming bitmap has changed, preserving the hardware's longevity.

The Rendering Layer with Browser Rendering

Instead of running headless Chrome and scripting an ImageMagick pipeline, server-side rendering uses Cloudflare's Browser Rendering API. This tool easily generates a scaled PNG of a website. While the remote browser startup takes a few seconds, the delay is irrelevant for a display that refreshes on an interval of minutes.

Once the PNG is captured, it needs to be processed to match the panel's monochrome requirement. The code decodes the PNG, reduces the palette, and applies the Floyd–Steinberg dithering algorithm. This deterministic approach prevents harsh banding and produces a smoother visual representation of the gradient-heavy weather graphics. Deploying this Worker requires installing the necessary npm package for Puppeteer, setting up the wrangler.toml configuration, and publishing the script.

The output is impressive: a fully processed webpage, such as the 1.1.1.1 landing page, appears in 800x480 monochrome with crisp dithering—proving the end-to-end pipeline works.

The Weather Content Worker

For the weather data, a second Cloudflare Worker was created as the content source. This one was written in Python, which is a beta feature for Workers but worked reliably for this use case. The script's task is simple: it fetches conditions from an external API and generates the clean HTML and CSS page that the rendering layer will later capture.

In a browser, the weather panel looks colorful and detailed. After passing through the rendering Worker, it looks like a polished, high-contrast image on the e-paper device—exactly what a retail-style screen should show.

Key Takeaways from the Build

The hardware setup is only a small part of this project; the bulk of the time is spent in the software layer. That said, each component offers a surprisingly enjoyable development experience:

  • ESP32: A capable processor with strong library support; the high-level interfaces mask the chip's complexity.
  • Browser Rendering API: This is a powerful yet understated feature that easily handled the heavy lifting of page rasterization and the dithering algorithm.
  • Python on Workers: Despite being in beta, it functioned continuously without issues, making light work of API calls and dynamic content delivery.

This project ends with a framed, living weather panel on the wall. The total cost—inexpensive hardware plus free-tier cloud services—shows how accessible this kind of custom display technology has become.