173 lines
4.4 KiB
Markdown
173 lines
4.4 KiB
Markdown
# Waveshare 2.9" Touch ePaper Panel
|
||
|
||
ESPHome project for the [Waveshare 2.9inch Touch e-Paper HAT](https://www.waveshare.com/2.9inch-Touch-e-Paper-HAT.htm) on an ESP32-WROOM-32 (NodeMCU-32S). Drives an LVGL UI with 2-bit grayscale rendering and touchscreen input.
|
||
|
||
## Hardware
|
||
|
||
- **MCU:** ESP32-WROOM-32 (NodeMCU-32S)
|
||
- **Display:** SSD1680, 296×128, 2-bit grayscale via custom component
|
||
- **Touchscreen:** GT1151 / ICNT86X (I2C, polling mode)
|
||
|
||
### Wiring
|
||
|
||
| Function | ESP Pin | HAT Pin |
|
||
|--- |--- |--- |
|
||
| Display SCLK | GPIO18 | Pin23/GPIO11/SPI0_SCLK |
|
||
| Display MOSI | GPIO23 | Pin19/GPIO10/SPI0_MOSI |
|
||
| Display CS | GPIO19 | Pin24/GPIO8/SPI0_CE0 |
|
||
| Display DC | GPIO17 | Pin22/GPIO25 |
|
||
| Display BUSY | GPIO4 | Pin18/GPIO24 |
|
||
| Display RST | GPIO5 | Pin11/GPIO17/SPI1_CE1 |
|
||
| Touch SDA | GPIO21 | Pin3/GPIO2/I2C1_SDA |
|
||
| Touch SCL | GPIO22 | Pin5/GPIO3/I2C1_SCL |
|
||
| Touch RST | GPIO15 | Pin13/GPIO27 |
|
||
| Touch INT | GPIO16 | Pin15/GPIO22 |
|
||
|
||
## Project Structure
|
||
|
||
```
|
||
waveshare-panel/
|
||
├── waveshare-test.yaml # Main ESPHome config (edit LVGL layout here)
|
||
├── secrets.yaml # WiFi/API credentials (not committed)
|
||
├── FreeSans.ttf # Font used in LVGL
|
||
└── custom_components/
|
||
├── waveshare_epaper_2bit/ # 2-bit grayscale display driver
|
||
└── icnt86x/ # ICNT86X touchscreen driver
|
||
```
|
||
|
||
## Build Environment Setup
|
||
|
||
### 1. Install Python 3.11
|
||
|
||
ESPHome 2026.1.0 requires Python 3.11. Check your version:
|
||
|
||
```bash
|
||
python3 --version
|
||
```
|
||
|
||
On Ubuntu/Debian, install it if needed:
|
||
|
||
```bash
|
||
sudo apt update
|
||
sudo apt install python3.11 python3.11-venv python3.11-dev
|
||
```
|
||
|
||
On macOS with Homebrew:
|
||
|
||
```bash
|
||
brew install python@3.11
|
||
```
|
||
|
||
### 2. Create a virtual environment for ESPHome 2026.1.0
|
||
|
||
Using a dedicated venv keeps this version isolated from other ESPHome installs.
|
||
|
||
```bash
|
||
python3.11 -m venv ~/esphome-env/esphome-2026.1.0
|
||
source ~/esphome-env/esphome-2026.1.0/bin/activate
|
||
```
|
||
|
||
### 3. Install ESPHome 2026.1.0
|
||
|
||
```bash
|
||
pip install esphome==2026.1.0
|
||
```
|
||
|
||
Verify the install:
|
||
|
||
```bash
|
||
esphome version
|
||
# Expected: Version: 2026.1.0
|
||
```
|
||
|
||
### 4. Activate the environment (each session)
|
||
|
||
```bash
|
||
source ~/esphome-env/esphome-2026.1.0/bin/activate
|
||
```
|
||
|
||
You can add this to your shell profile or run it manually before working on the project.
|
||
|
||
## Building and Flashing
|
||
|
||
All commands assume the venv is active and you are in the project directory.
|
||
|
||
### Compile only
|
||
|
||
```bash
|
||
esphome compile waveshare-test.yaml
|
||
```
|
||
|
||
### Flash via USB (first flash or if OTA fails)
|
||
|
||
```bash
|
||
esphome upload waveshare-test.yaml
|
||
```
|
||
|
||
Connect the ESP32 via USB before running. You may need to hold the BOOT button during flashing if the device doesn't enter download mode automatically.
|
||
|
||
### Flash via OTA (subsequent flashes)
|
||
|
||
Once the device is on WiFi, OTA upload works without USB:
|
||
|
||
```bash
|
||
esphome upload waveshare-test.yaml
|
||
```
|
||
|
||
ESPHome will automatically attempt OTA if the device is reachable.
|
||
|
||
### Monitor serial output
|
||
|
||
```bash
|
||
esphome logs waveshare-test.yaml
|
||
```
|
||
|
||
Or via USB:
|
||
|
||
```bash
|
||
esphome logs --device /dev/ttyUSB0 waveshare-test.yaml
|
||
```
|
||
|
||
## Secrets
|
||
|
||
Copy the secrets template and fill in your credentials:
|
||
|
||
```bash
|
||
cp secrets.yaml.example secrets.yaml # if an example exists, otherwise create it
|
||
```
|
||
|
||
`secrets.yaml` format:
|
||
|
||
```yaml
|
||
wifi_ssid: "YourNetworkName"
|
||
wappw: "YourWiFiPassword"
|
||
enckey: "<32-byte base64 Home Assistant API key>"
|
||
apipw: "YourOTAPassword"
|
||
hotspotpw: "FallbackPassword"
|
||
```
|
||
|
||
The `fallbackssid` variable is set in `waveshare-test.yaml` and does not go in secrets.
|
||
|
||
## Making Layout Changes
|
||
|
||
The LVGL UI is defined in `waveshare-test.yaml` under the `lvgl:` block. The display renders at **296×128 pixels** in a 4-shade grayscale palette:
|
||
|
||
| LVGL color | Shade |
|
||
|------------|------------|
|
||
| `0xFFFFFF` | White |
|
||
| `0xAAAAAA` | Light grey |
|
||
| `0x555555` | Dark grey |
|
||
| `0x000000` | Black |
|
||
|
||
After editing the YAML, compile and flash:
|
||
|
||
```bash
|
||
esphome upload waveshare-test.yaml
|
||
```
|
||
|
||
The display uses a two-tier refresh:
|
||
- **Partial refresh** (fast, 1-bit) — triggers immediately after any draw event for interactive feedback
|
||
- **Full refresh** (2-bit grayscale quality) — triggers 10 seconds after the last draw event
|
||
|
||
Full refresh restores proper 4-shade rendering after the fast partial updates.
|