A customizable desk dashboard for ESP32 boards and 7.5" ePaper displays. It combines local status widgets, cloud-fetched data, and optional Zigbee automation in a single low-power display.
This project is designed for a desk or workshop display that can show:
- time and date
- Google Calendar events
- weather forecast
- stock prices
- parcel tracking
- Proxmox server status
- Bambu Lab printer status
- MakerWorld statistics
- optional Zigbee automation
It supports configurable widget layout, cached data for offline rendering, and partial refresh on supported black-and-white ePaper panels.
- Multi-widget ePaper dashboard
- Remote configuration page on first boot
- Cached layout and widget data in Preferences
- Configurable widget refresh intervals
- Optional ESP32-C6 Zigbee support
- Support for prebuilt firmware and local compilation
Minimum setup:
- ESP32 board
- 7.5" GxEPD2-compatible ePaper display
- Wi-Fi network
Optional:
- battery-powered setup
- Bambu Lab printer via MQTT
- Zigbee switch for automation
Boards used during development:
- ESP32: Lolin D32
- ESP32-C6: DFRobot FireBeetle 2 ESP32-C6
- ESP32-C6 SuperMini: MakerGO-style ESP32-C6 SuperMini clone
Hardware sourcing note:
- the ESP32 boards and accessories used during testing came from common AliExpress-style marketplace listings
- the e-paper display used during testing was purchased from Amazon
- clone boards and hats can vary slightly, so verify the pinout if your hardware differs
Important notes:
- most color ePaper displays do not support partial refresh
- some large panels can take 20+ seconds for a full refresh
| ESP Model | CS | DC | RST | BUSY | SCK | MOSI | Display Power | Battery | Demo Button |
|---|---|---|---|---|---|---|---|---|---|
| ESP32-C6 SuperMini | 4 |
20 |
21 |
22 |
7 |
5 |
1 |
not used | GPIO_NUM_2 |
| ESP32-C6 | 1 |
8 |
14 |
7 |
23 |
22 |
4 |
0 |
GPIO_NUM_2 |
| ESP32 | 15 |
27 |
26 |
25 |
13 |
14 |
4 |
35 |
GPIO_NUM_33 |
The board wiring now uses a preset-backed pin map in configure.h. The firmware auto-selects the matching default preset for ESP32 or ESP32-C6, and you can switch presets with applyPinPreset(...) or provide a fully custom mapping with setCustomPinConfig(...) before the display is initialized.
For ESP32-C6 SuperMini boards, the validated preset avoids the onboard RGB LED pin on GPIO8 and turns the onboard LEDs off in firmware when that preset is selected.
The wake/demo input is optional. If you do not connect a button or touch-output board, the device will still work normally and will wake on timer only.
Demo mode and forced configuration mode require an external trigger on the configured wake/demo pin, such as:
- a physical push button
- a
TTP223capacitive touch switch module used as a simple digital output
When a wake/demo button is configured, the firmware checks it at boot and on deep-sleep wake.
- short tap: normal boot, no special action
- hold about 2 seconds: enter demo mode
- hold about 6 seconds: force configuration mode / AP setup
Preset defaults:
ESP32-C6 SuperMini: wake/demo pinGPIO_NUM_2, suitable for aTTP223output used as a simple digital wake signalESP32: wake/demo pinGPIO_NUM_33
Open ESP32-eInk-Dashboard.ino, select the correct ESP32 board, then compile and upload as usual.
For Zigbee on ESP32-C6:
- set
USE_ZIGBEEto1in configure.h - use an ESP32-C6 board
- select a Zigbee-capable partition scheme and Zigbee mode in the board menu
The repo includes sketch.yaml profiles.
Standard ESP32 build:
arduino-cli compile --profile esp32 /Users/nasoni/ESP32-eInk-DashboardESP32 Waveshare build:
arduino-cli compile --profile esp32_waveshare /Users/nasoni/ESP32-eInk-DashboardESP32-C6 FireBeetle build:
arduino-cli compile --profile esp32c6_firebeetle /Users/nasoni/ESP32-eInk-DashboardESP32-C6 FireBeetle Zigbee build:
arduino-cli compile --profile esp32c6_firebeetle_zigbee /Users/nasoni/ESP32-eInk-DashboardESP32-C6 SuperMini build:
arduino-cli compile --profile esp32c6_supermini /Users/nasoni/ESP32-eInk-DashboardESP32-C6 SuperMini Zigbee build:
arduino-cli compile --profile esp32c6_supermini_zigbee /Users/nasoni/ESP32-eInk-DashboardOnly the ESP32-C6 builds have Zigbee variants.
If you prefer a direct command, this Zigbee build works:
arduino-cli compile \
--fqbn esp32:esp32:esp32c6:PartitionScheme=custom,ZigbeeMode=zczr \
/Users/nasoni/ESP32-eInk-Dashboard \
-eWhy Arduino IDE and arduino-cli can behave differently:
- Arduino IDE remembers board-menu selections in the GUI
arduino-clineeds those board options passed explicitly- Zigbee on ESP32-C6 requires both the correct partition scheme and Zigbee mode
Prebuilt merged binaries are available in the project releases:
To flash them from a browser, you can use:
Use address 0x0000 when flashing the merged image.
After flashing:
- power on the device
- connect to the setup Wi-Fi network:
Dashbboard-Setup - open
http://192.168.4.1 - fill in the configuration page
The setup page can store:
- Wi-Fi SSID and password
- device timezone
- Google Script ID
- MQTT IP, port, username, and password
- pin preset selection
- custom pin mapping when
Customis selected - optional Zigbee-related settings when Zigbee firmware is enabled
These settings are stored on the device. Depending on upload and erase settings, they may be reset after flashing new firmware.
The AP web configuration page is also where you can:
- choose a predefined board wiring preset
- expand the
Custompreset to enter your own pin mapping - set the fallback timezone used by the clock when the layout does not define one
- configure wake/demo behavior through the selected wake/demo input pin
Zigbee support is intended for ESP32-C6 builds.
Current behavior:
- Zigbee control follows the Bambu aux fan state
- when the aux fan turns on, the Zigbee switch is turned on
- when the aux fan turns off, the Zigbee switch is turned off
Because printer status is refreshed periodically, the Zigbee off action can happen about 1 to 5 minutes after the fan stops.
The firmware expects a Google Apps Script web app that acts as a central data source.
Supported data:
- parcel tracking
- calendar events
- stocks
- layout configuration
- Proxmox data
- weather
- MakerWorld data
- create a new Google Apps Script project
- add your script
- deploy it as a Web App
- copy the published URL
The published URL looks like:
https://script.google.com/macros/s/<SCRIPT_ID>/exec
The firmware only needs the <SCRIPT_ID> portion. You enter that value on the device setup page, not in the source code.
The easiest setup is to use the bundled spreadsheet template:
- create a new empty Google spreadsheet in Google Drive
- import ESP32_Import.ods
- rename the spreadsheet to
ESP32Dashboard
The script looks for a spreadsheet with that exact name in Google Drive.
The imported file includes the expected sheets and starter structure for:
StocksTrackingLayoutListCarriers
If you prefer a manual setup, sample CSV files are also included in googleScripts.
Clock widget:
- put the timezone string in the
Extra1field of the clock row - example:
EST5EDT,M3.2.0/2:00:00,M11.1.0/2:00:00
Weather widget:
Extra1: latitudeExtra2: longitude
Example:
Extra1 = 40.712Extra2 = -74.006
Font tooling and conversion notes are documented in fonts/README.md.
That folder includes:
- conversion scripts
- glyph lists
- Material Design icon setup
- ePaper font optimization notes
Important:
- glyph order must remain consistent
The case model is available here:
GitHub Actions can build firmware for:
- ESP32
- ESP32-C6
- ESP32-C6 with Zigbee
The workflow uses the repo partitions.csv and can inject a firmware version string that is shown on the device near the battery indicator.
Key files:
- ESP32-eInk-Dashboard.ino: main sketch, display update flow, setup portal
- configure.h: board options, feature flags, icon constants
- fetchAllInfo.cpp: JSON parsing and widget rendering
- bambulab.cpp: printer status and MQTT fetch
- dash_zigbee.cpp: Zigbee integration
- googleScripts: Apps Script samples and CSV examples
Material Design Icons:
- source: materialdesignicons.com
- license: Apache 2.0
Montserrat:
- source: Google Fonts
- license: SIL Open Font License 1.1
HighSpeed:
- source: dafont.com/high-speed.font
- license: free for personal use, commercial use requires permission
Contributions are welcome. Good areas for improvement include:
- new widgets
- layout and UI polish
- performance tuning
- network and parsing robustness
- documentation
Open an issue or submit a pull request if you want to contribute.

