Long-time lurker etc etc. Thought I’d share a recipe to get an Adafruit Feather ESP32-S2 working with ESPHome, along with the ThinkInk E-paper display.
Hardware-wise, it’s a nice straightforward way to get started with E-Paper (or is it EPaper? epaper?).
As a bonus, I wrote a basic driver for the max17048 battery fuel gauge which is integrated on many Adafruit Feathers.
Here’s the end result:
The ThinkInk display isn’t officially supported by ESPHome, but it appears to be similar enough to a WaveShare display that it works alright.
The max17048 battery monitor works, though its accuracy leaves something to be desired.
Basic steps
- Buy the parts
- Solder pin headers to the Feather
- Plug it all together
- Flash it with ESPHome using the .yaml file below
- Profit
- Add the device to Home Assistant if you’d like
Parts List
This is all stuff off of Adafruit:
ESPHome .yaml file
# Handy docs:
# the basics of using a qt py with ESPHome: https://jamesachambers.com/home-assistant-tiny-wifi-button-guide-ft-adafruit-qt-py/
# ESP32-S2 Feather pinout: https://learn.adafruit.com/adafruit-esp32-s2-feather/pinouts
# E-ink feather pinout: https://learn.adafruit.com/adafruit-2-9-eink-display-breakouts-and-featherwings/pinouts#featherwing-connections-3102326
# Chip selects: e-ink: GPIO9 sRAM: GPIO6 SD: GPIO5
# EINK DC: D10
esphome:
name: esp32-s2-mini-feather
friendly_name: ESP32 S2 Mini Feather E-ink
esp32:
board: featheresp32-s2
framework:
type: arduino
# Enable logging
logger:
web_server:
port: 80
# Enable Home Assistant API
api:
encryption:
key: "REDACTED"
ota:
password: "REDACTED"
wifi:
ssid: !secret wifi_ssid
password: !secret wifi_password
spi:
clk_pin: GPIO36
mosi_pin: GPIO35
miso_pin: GPIO37
interface: hardware
i2c:
sda: GPIO3
scl: GPIO4
font:
- file:
type: gfonts
family: Montserrat
weight: 600
id: title_font
size: 40
- file:
type: gfonts
family: Montserrat
weight: 300
id: small_font
size: 20
external_components:
- source: github://Option-Zero/esphome-components
components: [max17048]
time:
platform: sntp
id: current_time
display:
- platform: waveshare_epaper
model: 2.90in-bV3
id: eink_display
cs_pin: GPIO9
dc_pin: GPIO10
update_interval: 1min
rotation: 90
lambda: |-
it.print(0, 0, id(title_font), "Current Time");
it.strftime(0, 50, id(title_font), "%H:%M", id(current_time).now());
it.printf(0, 100, id(small_font), "Batt: %.1f%% %.2fV %.0f%%/hr", id(batt_pct).state, id(batt_v).state, id(batt_discharge_rate).state);
sensor:
- platform: max17048
battery_voltage:
name: Battery voltage
id: batt_v
battery_level:
name: Battery level
id: batt_pct
rate:
name: Battery discharge rate
id: batt_discharge_rate
output:
- platform: gpio
pin: GPIO21
id: neopixel_power_gpio
switch:
- platform: output
name: "Neopixel power bus"
output: neopixel_power_gpio
id: neopixel_power_switch
restore_mode: ALWAYS_ON
disabled_by_default: True
light:
- name: "Neopixel"
id: neopixel
platform: neopixelbus
type: GRB
variant: WS2812
pin: GPIO33
method:
type: esp32_rmt
channel: 0
num_leds: 1
restore_mode: RESTORE_DEFAULT_ON
default_transition_length: 100ms
binary_sensor:
- platform: gpio
pin:
number: GPIO13
mode: INPUT_PULLUP
inverted: True
name: "Button A"
- platform: gpio
pin:
number: GPIO12
mode: INPUT_PULLUP
inverted: True
name: "Button B"
on_press:
- light.toggle: neopixel
- platform: gpio
pin:
number: GPIO11
mode: INPUT_PULLUP
inverted: True
name: "Button C"
on_press:
then:
- component.update: eink_display
Gotchas, tips n tricks, and TODOs
Some cool / annoying stuff I encountered along the way:
Manual reset
After updating firmware, you have to manually hit the reset button or else the E-ink display may not update. I’m not sure why that is. But it’ll drive ya crazy if you forget to reset it.
Partial screen refresh
Every screen refresh is a full refresh, which is an epilepsy-triggering, 6-second-long sequence of flashes. I haven’t looked into whether a partial screen refresh is possible with this hardware.
Battery usage
Battery life is currently ~24 hours without any kind of optimization.
The max17048 tended to underreport battery percentage in my testing with this setup (it hit ~1% after 12 hours, but the clock kept running for another 12 hours). I do like how it also reports battery charge or discharge rate in %/hr though.
Trouble with initial flash of the Feather S2
When the Feather hasn’t been flashed with ESPHome, the first flash can be tricky. I was getting the “Failed to initialize. Try resetting your device or holding the BOOT button while selecting your port.” error as seen in Getting started with ESPHome and Adafruit ESP32-S2 Feather .
Luckily I was able to cold-start the device with this sequence:
- Build the firmware from the ESPHome add-on and download the .bin file (“new style”). Make sure you supply wi-fi login info.
- Connect to the device using Adafruit ESPTool
- Flash the
.bin
firmware file to the device at offset0x0
- From there, you should be able to detect the device in the ESPHome add-on and use OTA updates.
Screen color
This is a 3-color display (black, white, red) but it’s currently only working with black and white. Some folks have managed to get the red working: Use ESPHome with e-ink Displays to blend in with your home decor! - #303 by skybarberom
My initial forays into this weren’t immediately successful so I figured I’d share what I have.
Extra flash, buttons n goodies
The Adafruit 2.9" Tri-Color eInk / ePaper Display FeatherWing has a MicroSD card slot and some SRAM as well. I didn’t need those for this project, but I included the Chip Select pins in the YAML.
There are also three buttons on the FeatherWing. I set those up to report to ESPHome so you can use them to trigger automations. I also set one of them to flash the neopixel on the Feather, and the other to trigger an immediate screen refresh.