Why an e-paper display ghosts after partial refresh
The demo looked perfect. The clock updated without a flash, the battery icon changed in a blink. A week later there is a faint shadow of yesterday’s screen behind today’s, the corners look gray, and the first cold morning outdoors makes it worse. The display is not defective. The firmware has no refresh policy.
E-paper is easy to get running and easy to get wrong in a product. Most example code is written to make one pretty image appear. A shipped device has to update for months, sleep for most of that time, survive power loss, and work at temperatures nobody tested on the bench.
What ghosting actually is
An electrophoretic panel moves charged particles between two electrodes. Black and white states are particle positions. A full refresh drives the particles all the way to their end positions, which is why it flashes the screen through black and white. A partial refresh uses a shorter waveform on only the pixels that change.
Waveshare’s ESP32 e-paper tutorial states the trade-off directly. The shorter waveform cannot move every particle fully to a stable endpoint, so “after repeated partial refreshes, this error accumulates and produces ghosting.” A full refresh resets the particles and clears it.
That explains the symptoms people post about:
- A faint outline of a previous screen that gets stronger the more partial updates run.
- Gray instead of white in the area that updates often, such as a clock or a value readout.
- A clean image right after a full refresh, followed by slow decay.
None of this is a bug in your driver code. It is how the panel works. The only question is how often your firmware pays for a full refresh.
The refresh policy to write down
Treat the refresh strategy as a design decision, not a tuning knob you find at the end. Write it down before the UI is built, because it changes what the UI is allowed to do.
1. Count partial updates and force a full refresh on a schedule. Waveshare’s tutorial suggests a full refresh typically every 5 to 10 updates. Its FAQ for a 1.54-inch panel suggests a full clear after 5 partial refreshes, and reducing the number of separate partial-refresh regions. Those are one vendor’s guidance for its own panels. Your panel’s datasheet and your own eyes decide the real number. Persist the counter so a reboot does not reset it to zero.
2. Design the screen so partial refresh is rare. A screen that changes one small region once a minute ghosts differently than a screen that redraws a large area every second. If the information changes slowly, update slowly. A thermostat that redraws on a real change in setpoint ghosts far less than one that redraws every sensor sample.
3. Rate-limit refreshes in firmware, not in the UI layer. The Waveshare tutorial warns that rapid, continuous refreshing accelerates display aging, and for its four-color and six-color panels it specifies a minimum gap of at least 180 seconds between refreshes. Put the limit in the display driver so no screen, menu or error path can bypass it. Read the exact wording in the datasheet of your panel, because refresh-interval guidance differs by panel type and the phrasing is easy to misread.
4. Clear to white before long storage. The same tutorial recommends refreshing to white before long-term storage so a held image does not leave lasting ghosting. For a product, that means the factory or shipping state should be a deliberate white screen or a full-screen logo refreshed on purpose, not whatever the test fixture last drew. This ties directly into production test software: the last step of a test sequence should leave the display in a known, clean state.
Sleep, wake and the state your driver forgets
Two rules cause more field problems than ghosting itself.
Do not leave the panel energized. Waveshare’s FAQ says that after a refresh the display should go into sleep mode or be powered off, and warns that leaving it powered for a long time under high voltage may cause irreversible damage. A bench setup that runs forever on USB power hides this. A battery product that crashes with the panel mid-state may not.
Deep sleep erases the controller’s memory of the last frame. The tutorial notes that after the driver’s deep-sleep command, the previous-frame data in the driver IC becomes invalid, so the firmware must reinitialize and do a full refresh before resuming partial refreshes. The FAQ says the same in practical terms: waking is treated like a power-on, so run initialization again and clear the screen first to minimize ghosting.
The bug this produces is familiar. The firmware wakes from sleep, skips initialization to save time, sends a partial update, and the screen shows a mix of the old image and the new one. The fix is a small state machine in the display driver: asleep, initialized, full image known, partial-capable. A partial update is only legal in the last state. Every wake goes back through the first two.
Also protect against power loss during a refresh. Waveshare notes that cutting power mid-refresh can leave the image in an intermediate state. Firmware that may lose power, such as a battery product with a brownout, should detect an interrupted refresh on the next boot and run a full one. Store a small “refresh in progress” flag in nonvolatile memory before starting and clear it after the busy line releases.
Temperature is part of the waveform
Particles move more slowly when cold. The Waveshare tutorial puts the lower operating limit of most of its displays at around 0 °C and tells builders to check specifications before outdoor winter use. Below the rated range the update gets slow, contrast drops and ghosting gets worse.
Many controllers account for this in hardware. The Solomon Systech SSD1680 family, for example, can use either an integrated temperature sensor or an external one, and its Zephyr devicetree binding exposes that choice. Check your controller’s datasheet for how it uses the temperature reading to pick a waveform. That only helps if the reading is representative of the glass.
This is where the board matters, not just the firmware:
- An internal sensor on the controller reads the controller. A display that sits behind a warm regulator or battery charger, or against a cold enclosure wall, can differ from it.
- An external sensor placed on the PCB should sit near the panel connector and away from heat sources. Plan the footprint and I2C routing when you lay the board out, not after the first cold-room test.
- Check which waveforms your panel actually ships with. Whether a given module has a full temperature range of waveforms, and whether partial refresh is supported at all, is a panel-and-controller question. Waveshare’s FAQ notes that only some of its black-and-white panels support partial refresh, so confirm it for your exact part.
If the product has to work outdoors in winter, test the display at the cold end of the range with the real enclosure and real battery, and measure refresh time as well as appearance.
What to check before you ship
- Does the panel’s datasheet list partial refresh and the temperature range you need?
- Is there a persisted counter that forces a full refresh on a schedule?
- Is there a minimum refresh interval enforced in the driver?
- Does every wake from sleep reinitialize and clear before any partial update?
- Is the panel put to sleep or powered down after each refresh?
- Is an interrupted refresh detected and repaired at the next boot?
- Is the temperature sensor the controller uses actually near the glass?
- Does the unit leave the factory showing a deliberate, clean screen?
If your e-paper product ghosts, flashes more than it should or misbehaves in the cold, we start from the panel and controller datasheets, write the refresh and sleep state machine, and check sensor placement on the board. Send us the panel part number, the controller, your update pattern and the temperature range, and we will tell you what we would change.
If your e-paper product ghosts, flashes too often or fades in the cold, we would write a refresh policy around your panel's own datasheet and test it on your hardware.
Tools for this topic
- ESP32 browser flasherFlash a .bin over USB from the browser. It reads the chip and the file first and refuses firmware built for a different chip, revision or flash size.
- STM32 browser flasherFlash a .dfu, .hex or .bin over USB DFU from the browser. It reads the chip’s flash map and identity first and refuses firmware whose bytes or vector table do not belong on it. Never touches option bytes.
- Browser serial terminalConnect a USB board and read or send serial text and hex from the browser. Baud rate and format, DTR/RTS reset profiles for ESP32 and Arduino, timestamps and a saved log. Nothing leaves your computer.
Related notes
- Linux board or microcontroller for a new productHow to decide between a Linux compute module and a microcontroller: the tests on power, storage, updates and supply that settle it before layout starts.
- Why an ESP32-P4 MIPI DSI display stays blackA bring-up order for an ESP32-P4 MIPI DSI panel: DPHY power, timing, init sequence, touch, and the v3.2 silicon change that affects old boards.
- Why a GT911 touch controller doesn't respond over I2CFix a GT911 touch panel that never answers: the INT address strap, reset sequence, status-register clearing and the schematic checks that prevent it.