ESP32 Display Example: Connect and Drive a Screen Step-by-Step

What hardware do I need for an ESP32 display project?
Gather every component before writing code. The table below lists a proven combination from a working e-paper weather display build.
| Component | Example part | Notes |
|---|---|---|
| ESP32 board | FireBeetle 2 ESP32-E | Low-power design, USB-C, onboard battery management |
| E-paper panel | Waveshare 7.5" e-paper v2 | 800×480 px, black/white |
| Display adapter | DESPI-C02 | Waveshare HATs rev 2.2/2.3 are not recommended |
| Sensor (optional) | BME280 | Temperature, humidity, pressure; 3.3 V/5 V compatible |
| Battery | 3.7 V LiPo, JST-PH2.0 | 5000 mAh gives 6–12 months at 30-minute refresh intervals |
| Wires | Jumper wires | Minimises soldering during prototyping |
You also need a computer running Linux, Windows, or macOS to compile and flash firmware.
If you prefer a TFT panel, Adafruit's HX8357D 3.5" TFT is one option—it supports both SPI and 8-bit parallel interfaces—though its Arduino library only exposes SPI on ESP32 by default, making parallel-mode support a custom addition.
\2ESP32 dev board connected to an SH1106 OLED display on a breadboard, powered via USB Image: King of Pwnt, CC0, via Wikimedia Commons
How do I wire a display to the ESP32?
Most display modules connect over SPI. The Waveshare e-paper library's default Arduino pin assignments are:
#define RST_PIN 8
#define DC_PIN 9
#define CS_PIN 10
#define BUSY_PIN 7
Those constants target a standard Arduino board, not an ESP32. You must replace every number with the GPIO number you physically wired on your ESP32 module. Pass your chosen GPIOs into SPI.begin() during bus initialisation rather than relying on the defaults.
Heltec WiFi LoRa boards: This board already uses SPI for its onboard LoRa radio and OLED display, so none of the default pin numbers listed above are freely available. Start instead with a bare ESP-WROOM-32 devkit that has no other SPI peripherals, confirm the display works there, then port the code to a more complex board once the basics are solid.
Using the DESPI-C02 adapter: Wire your SPI signals to the adapter board rather than directly to the display ribbon cable. The adapter handles the level-shifting and timing the e-paper panel requires.
8-bit parallel speed (advanced): If you need faster refresh than SPI allows, you can bit-bang a parallel bus by assigning eight GPIO pins and driving them with gpio_set_level(), assembling or disassembling bytes pin-by-pin through a helper function.
Which display library should I use?
Three libraries appear consistently in ESP32 display work:
- Waveshare's own Arduino library – a direct starting point, but requires pin-mapping edits for any board that isn't a standard Arduino Uno.
- GxEPD2 – recommended for e-paper panels; verified working on the ESP-WROOM-32 and licensed under GPLv3.0. Both Waveshare and Good Display panels are supported.
- Adafruit GFX – a general graphics layer that many display drivers sit on top of, providing consistent drawing primitives across panel types.
For a first ESP32 display example, GxEPD2 combined with Adafruit GFX is a reliable stack. Install both through the Arduino Library Manager before opening any example sketch.
The library's Init() function is the critical first test: a return value of 0 means the panel acknowledged the initialisation sequence. Any non-zero result is almost always a wiring problem—re-check pin assignments before debugging the code itself.
Step-by-step: configure and write the example code
- Open a library example. In the Arduino IDE go to File → Examples → GxEPD2 and open a basic hello-world or graphics sketch.
- Set your board target. Under Tools → Board, select your ESP32 variant (for example, FireBeetle-ESP32-E or ESP32 Dev Module).
- Edit pin definitions. Near the top of the sketch find the
RST_PIN,DC_PIN,CS_PIN, andBUSY_PINdefines (or equivalent constructor arguments) and replace placeholder numbers with the GPIO numbers you physically wired. - Configure SPI. If the library calls
SPI.begin()with no arguments, change it toSPI.begin(SCK, MISO, MOSI, CS)using your actual GPIO numbers so the ESP32 hardware SPI controller uses the correct pins. - Wrap Init in a guard:
if (epd.Init() != 0) { Serial.print("e-Paper init failed"); return; } - Add drawing calls. After a successful init use the library's text and graphics methods to write to the display buffer, then call the library's display or update function to push the buffer to the panel—nothing appears on screen until this flush step.
- Add deep sleep (optional, but valuable for battery builds). The FireBeetle 2 ESP32-E draws only ~14 μA in sleep, making multi-month battery runtimes practical when the board wakes, refreshes the display, then sleeps again.
- Verify the sketch compiles without errors before proceeding to the flash step.
How do I build and flash the firmware?
Arduino IDE path:
- Click Verify (tick icon) to compile.
- Connect your ESP32 board via USB-C or Micro-USB.
- Select the correct port under Tools → Port, then click Upload (arrow icon).
ESP-IDF path (native framework):
Build the project first:
idf.py build
Then flash using Ninja directly:
ninja flash
To specify the serial port explicitly:
ESPPORT=/dev/ttyUSB0 ninja flash
On Windows with make, append the variable at the end of the command instead:
make -j3 app-flash ESPPORT=COM4 ESPBAUD=2000000
Note that inline variable assignment before a command (e.g. ESPPORT=... ninja flash) is Bash syntax and works on Linux and macOS but not in Windows Command Prompt.
How do I verify the display is working?
Open the serial monitor at the baud rate your sketch sets. A working init sequence prints progress messages and no error text. If Init() passes but the panel stays blank, check these points in order:
- Power – confirm 3.3 V on the display's VCC pin with a multimeter.
- SPI activity – a logic analyser or oscilloscope should show toggling on the SCK and MOSI lines during the init sequence.
- BUSY pin – the display holds BUSY high while processing a command. If your code does not wait for BUSY to fall before sending the next command, commands arrive out of order and produce garbled or blank output.
- Buffer flush – confirm your code calls the library's
display()orupdate()method after all drawing calls. E-paper libraries write to RAM first; the panel is not updated until that explicit flush.
What are the most common mistakes when connecting a display?
Using default Arduino pin numbers without remapping. The Waveshare library defaults—RST=8, DC=9, CS=10, BUSY=7—are Arduino Uno assignments. On an ESP32 those numbers address completely different or non-existent GPIO pads. Always remap every pin define to match your actual wiring before flashing.
Choosing a board with conflicting SPI peripherals. The Heltec WiFi LoRa board shares its SPI bus between a LoRa radio and an OLED. Adding an e-paper display on the same bus without careful pin management causes all three devices to conflict. Start with a plain ESP-WROOM-32 devkit until wiring and library code are confirmed working, then migrate to a more complex board.
Using Waveshare HAT rev 2.2 or 2.3 with the DESPI-C02. These HAT revisions are explicitly flagged as not recommended when using the DESPI-C02 adapter. Use a supported panel revision or a different adapter combination.
Skipping the BUSY pin connection. Leaving BUSY unconnected means the host never waits for the panel to finish processing, resulting in commands piling up and a blank or corrupted display.
Forgetting the explicit buffer flush. All draw operations land in the library's RAM buffer. Nothing appears on the e-paper panel until you call the library's display or update function to physically transfer that buffer to the screen.
Frequently asked questions
Can I use GxEPD2 on an ESP-WROOM-32?
Yes. GxEPD2 has been personally verified working on an ESP-WROOM-32. It is licensed under GPLv3.0.
How long will a battery last with an ESP32 e-paper display?
A 5000 mAh LiPo can provide 6–12 months of runtime at a 30-minute refresh interval. The ESP32 draws ~14 μA in deep sleep and ~83 mA for roughly 15 seconds during each display refresh.
Which adapter board works with Waveshare e-paper panels?
The DESPI-C02 adapter is recommended. Waveshare HATs revision 2.2 and 2.3 are explicitly not recommended for this application.
What display resolutions are available for ESP32 e-paper projects?
The Waveshare 7.5" v2 and the equivalent Good Display GDEY075T7 both provide 800×480 px in black/white. A 7-color 800×480 px option also exists—the Waveshare 7.3" ACeP e-Paper F and the Good Display GDEY073D46.
Can I add a sensor alongside the display?
Yes. A BME280 (temperature, humidity, pressure) is a common addition to ESP32 display projects and is 3.3 V/5 V compatible, making it straightforward to wire alongside the display module.
Connecting a display to an ESP32 is approachable once you remap the library's default SPI pin numbers to your board's actual GPIO layout and confirm the BUSY pin is connected and polled correctly. E-paper panels paired with the ESP32's deep-sleep mode are a particularly compelling combination—drawing only ~14 μA between refreshes and lasting up to a year on a mid-sized LiPo—making them ideal for wall-mounted display boards and low-maintenance sensor dashboards.
Sources
github.comBuild System (esp-idf docs)stackoverflow.comESP32 Heltec wifi LoRa, Waveshare e-Paper 4.2", how to connect via SPI and how to display something on the display (which library to use)?stackoverflow.comESP32 direct port manipulationgithub.comlmarzen/esp32-weather-epd (GitHub README)This guide summarises the public sources listed above in our own words. Check the original documentation before relying on exact figures.


