Server: Frame.panel_type (new column + migration) is auto-derived from the device's reported board (X-Frame-Board), never user-set -- the panel is a property of the hardware, not a picker in the UI. image_pipeline's packing/render pipeline is parameterized by panel geometry instead of hardcoded 800x480 globals, with the real confirmed 13.3in geometry (1600x1200) registered alongside the original 7.3in panel. Existing 7.3in frames are unaffected (column default + board mapping both resolve to the original panel). Board identifiers are also renamed (devkit/xiao -> devkit_esp32c6/ xiao_esp32c6, plus new "ee02") since the EE02 board also carries a XIAO module -- "xiao" alone stopped disambiguating hardware. The server keeps accepting the legacy bare names indefinitely for already-flashed devices. Firmware: scaffolds a third build target (ee02, ESP32-S3 -- a real chip-target change, not just a same-chip Kconfig variant like xiao) and a new epd13in3e driver component skeleton. The actual panel init/LUT/ refresh register sequence isn't ported from vendor demo code yet (none was available), so that component deliberately fails to compile (#error) rather than risk sending unverified register values to real hardware -- devkit/xiao are unaffected and build identically to before. CI's ee02 build step is continue-on-error for the same reason.
213 lines
11 KiB
Markdown
213 lines
11 KiB
Markdown
# Hardware
|
|
|
|
## Parts
|
|
|
|
- An ESP32-C6 dev board (e.g. ESP32-C6-DevKitC-1). Needs 8MB flash --
|
|
see [`firmware/sdkconfig.defaults`](../firmware/sdkconfig.defaults) and
|
|
[`firmware/partitions.csv`](../firmware/partitions.csv) if yours differs.
|
|
- [Waveshare 7.3" E Ink Spectra 6 (E6) panel](https://www.waveshare.com/7.3inch-e-paper-hat-e.htm) --
|
|
800x480, 6-color, SPI.
|
|
- A USB cable for flashing/power.
|
|
|
|
## Wiring
|
|
|
|
The panel connects over SPI plus three control lines (data/command, reset,
|
|
busy). Defaults below match the reference build and are set in
|
|
[`firmware/components/epd7in3e/Kconfig`](../firmware/components/epd7in3e/Kconfig) --
|
|
override via `idf.py menuconfig` under **E-Paper Display (epd7in3e)
|
|
Configuration** if your wiring differs.
|
|
|
|
| Panel pin | ESP32-C6 GPIO | Kconfig option |
|
|
| --------- | ------------- | ----------------- |
|
|
| CLK | 20 | `EPD_PIN_CLK` |
|
|
| DIN | 19 | `EPD_PIN_MOSI` |
|
|
| CS | 18 | `EPD_PIN_CS` |
|
|
| DC | 9 | `EPD_PIN_DC` |
|
|
| RST | 10 | `EPD_PIN_RST` |
|
|
| BUSY | 11 | `EPD_PIN_BUSY` |
|
|
| VCC | 3.3V | -- |
|
|
| GND | GND | -- |
|
|
|
|
Optionally, three buttons, all wired the same way -- momentary push button
|
|
between the GPIO and GND, no external resistor needed (the firmware
|
|
enables each pin's internal pull-up, so it idles high and reads low when
|
|
pressed):
|
|
|
|
- **Next photo (GPIO2)**: a normal press skips immediately to the next
|
|
photo; see
|
|
[`firmware/README.md`](../firmware/README.md#skipping-to-the-next-photo).
|
|
- **Back photo (GPIO0)**: a normal press returns to the previously-shown
|
|
photo; see
|
|
[`firmware/README.md`](../firmware/README.md#going-back-to-the-previous-photo).
|
|
- **Menu / reset (GPIO1)**: one button, three actions by hold duration --
|
|
a quick press soft-resets the device (config kept); holding ~3s then
|
|
releasing overlays a "scan to manage" QR code on the current photo for
|
|
30 seconds; holding ~15s factory-resets it (clears WiFi/server config,
|
|
reprovisions); see
|
|
[`firmware/README.md`](../firmware/README.md#managing-the-queue-soft-resetting-and-factory-resetting).
|
|
|
|
All three pins were picked because they're within GPIO 0-7 -- the only
|
|
pins the ESP32-C6 can wake from deep sleep on -- aren't strapping pins,
|
|
and aren't already used by the panel wiring above. Also, not
|
|
incidentally, GPIO 0-7 is *all* the deep-sleep-wakeup-capable pins this
|
|
chip has (`SOC_RTCIO_PIN_COUNT` is 8) -- worth knowing if you're
|
|
targeting a compact board like the Seeed XIAO ESP32-C6, which only
|
|
breaks out 3 of them (GPIO0/1/2). These three buttons were deliberately
|
|
designed to fit exactly that budget: two dedicated pins for the
|
|
actions where instant, unambiguous response matters most (next, back),
|
|
and everything else folded onto the third pin via hold duration instead
|
|
of needing its own pin.
|
|
|
|
### Wiring on the Seeed XIAO ESP32-C6
|
|
|
|
The XIAO only breaks out 11 GPIOs (0, 1, 2, 16, 17, 18, 19, 20, 21, 22,
|
|
23), so the dev-board defaults above don't fit -- DC/RST/BUSY (GPIO 9,
|
|
10, 11) aren't exposed on this board at all. Built with
|
|
[`build_for_board.sh xiao`](../firmware/README.md#building-for-the-seeed-xiao-esp32-c6-production-board),
|
|
which layers [`firmware/sdkconfig.xiao`](../firmware/sdkconfig.xiao) on
|
|
top of the dev-board defaults, remapping DC/RST/BUSY onto three of the
|
|
remaining free pins:
|
|
|
|
| Panel pin | XIAO GPIO | XIAO silkscreen label | Kconfig option |
|
|
| --------- | --------- | ---------------------- | --------------- |
|
|
| CLK | 20 | D9 | `EPD_PIN_CLK` (unchanged) |
|
|
| DIN | 19 | D8 | `EPD_PIN_MOSI` (unchanged) |
|
|
| CS | 18 | D10 | `EPD_PIN_CS` (unchanged) |
|
|
| DC | 16 | D6 | `EPD_PIN_DC` |
|
|
| RST | 17 | D7 | `EPD_PIN_RST` |
|
|
| BUSY | 21 | D3 | `EPD_PIN_BUSY` |
|
|
| VCC | 3.3V | 3V3 | -- |
|
|
| GND | GND | GND | -- |
|
|
|
|
The XIAO's silkscreen labels its pins D0-D10, not raw GPIO numbers --
|
|
the table above gives both.
|
|
|
|
Buttons (unchanged from the table above -- the XIAO's only three
|
|
ADC/deep-sleep-capable pins, GPIO 0/1/2, are exactly the ones already
|
|
used): next=GPIO2/**D2**, back=GPIO0/**D0**, menu/reset=GPIO1/**D1**.
|
|
That leaves GPIO22/**D4** and GPIO23/**D5** free, e.g. for the optional
|
|
VBUS mains-sense divider described under
|
|
[Battery](#battery-optional-xiao-esp32-c6) below.
|
|
|
|
`sdkconfig.xiao` also sets `FRAME_XIAO_ANTENNA_INIT=y`, which powers
|
|
the XIAO's onboard RF switch and selects its ceramic antenna at boot
|
|
(GPIO3/14, internal to the board -- not part of the wiring above).
|
|
Without it, WiFi doesn't reliably work on this board at all: the radio
|
|
comes up and logs look normal (e.g. the softAP starts and prints its
|
|
SSID/password) but the switch's control pins are left floating, so
|
|
nothing actually reaches the antenna -- the AP never becomes visible to
|
|
a scan, and a station connection would fail to associate the same way.
|
|
Seeed's own Arduino board package does this automatically; plain
|
|
ESP-IDF (what this firmware uses) doesn't, hence the explicit init.
|
|
|
|
A couple of things worth knowing if you pick different pins:
|
|
|
|
- **Avoid the ESP32-C6's strapping pins** (GPIO 4, 5, 8, 9, 15) and the
|
|
USB-JTAG pins (12, 13) where possible -- strapping pins are sampled at
|
|
reset to select boot mode. The reference wiring above already uses
|
|
GPIO9 for DC, which *is* a strapping pin; it's only sampled during
|
|
power-on/reset, so it's safe once the app is running, but if
|
|
flashing/boot ever misbehaves on your board, check whether the panel is
|
|
pulling that line low during reset.
|
|
- The panel's SPI interface is rated well above the firmware's default
|
|
4MHz clock (`EPD_SPI_CLOCK_HZ`), but breadboard/dupont-wire connections
|
|
are often unreliable much past a few MHz. Raise it once your physical
|
|
wiring is confirmed solid.
|
|
|
|
## Battery (optional, XIAO ESP32-C6)
|
|
|
|
For a battery-powered build on the Seeed XIAO ESP32-C6 (which has
|
|
BAT+/BAT- charge pads on its underside and charges over USB-C):
|
|
|
|
- A 1S 3.7V LiPo **with an integrated protection circuit** (the board
|
|
does no low-voltage cutoff of its own), soldered or JST-PH-pigtailed
|
|
to the BAT pads. JST-PH polarity is not standardized -- verify with a
|
|
multimeter before connecting.
|
|
- Battery level sense: two equal-value resistors in series from BAT+ to
|
|
GND (200k is the reference value, but any matched pair works -- it's
|
|
a ratio divider, so what matters is the two resistors matching each
|
|
other, not the absolute value; higher values just draw less constant
|
|
current from the battery, e.g. ~10uA for 200k+200k vs ~2uA for
|
|
1M+1M, at the cost of a slightly noisier ADC reading from the higher
|
|
source impedance -- not noticeable in practice up to around 1M given
|
|
how coarse the percent curve already is). Midpoint to GPIO0/A0
|
|
(shared with the back button -- deliberate, see
|
|
[`firmware/README.md`](../firmware/README.md#battery-xiao-esp32-c6)).
|
|
- Optional mains detection: 2x100k divider from the 5V pin to GND,
|
|
midpoint to a spare GPIO (e.g. 22).
|
|
|
|
Both features are off by default in firmware
|
|
(`FRAME_BATTERY_ADC_GPIO`/`FRAME_VBUS_SENSE_GPIO` = -1) -- except
|
|
`FRAME_BATTERY_ADC_GPIO`, which [`firmware/sdkconfig.xiao`](../firmware/sdkconfig.xiao)
|
|
turns on (GPIO0) by default for XIAO builds, since that's the one
|
|
board this feature was designed for. Mains detection stays off by
|
|
default even there; set `FRAME_VBUS_SENSE_GPIO` yourself if you wire
|
|
that divider too.
|
|
|
|
## Power
|
|
|
|
The device spends nearly all its time in deep sleep, waking briefly once
|
|
an hour (configurable, see the server's web UI) to fetch and display a
|
|
photo. A full-color refresh on this panel takes 15-30+ seconds and draws
|
|
more current than deep sleep by a wide margin -- expect battery life (if
|
|
not running from USB power) to be dominated by refresh frequency, not
|
|
sleep current.
|
|
|
|
## Board identifiers
|
|
|
|
Each board reports a name to the server (`X-Frame-Board`,
|
|
`CONFIG_FRAME_BOARD_NAME`) that's chip-qualified rather than the plain
|
|
`devkit`/`xiao` older firmware used -- `devkit_esp32c6`, `xiao_esp32c6`,
|
|
`ee02` (see below). This changed once a second XIAO-based board (EE02,
|
|
an ESP32-S3) existed and "xiao" alone stopped disambiguating hardware.
|
|
The server keeps accepting the old bare names indefinitely, since
|
|
already-flashed devices can't be retroactively renamed.
|
|
|
|
## 13.3" Spectra 6 panel on Seeed's EE02 board (driver not yet functional)
|
|
|
|
A second panel size is supported server-side (the web UI shows a
|
|
read-only "Panel: 13.3\" Spectra 6" once a frame's device reports
|
|
itself as `ee02`) but **the firmware driver for it does not work yet**
|
|
-- `firmware/components/epd13in3e`'s panel init/LUT/refresh register
|
|
sequence hasn't been ported from Waveshare's/Seeed's own reference code
|
|
(which wasn't available at the time this was scaffolded), so a build for
|
|
this board deliberately fails to compile (`#error`) rather than risk
|
|
sending wrong register/LUT/timing values to real hardware. Confirmed so
|
|
far, from Waveshare's/Seeed's public product pages and a community
|
|
ESPHome integration (not an official vendor reference driver):
|
|
|
|
- Panel: [Waveshare 13.3" e-Paper (E) Spectra 6](https://www.waveshare.com/13.3inch-e-paper-hat-plus-e.htm) --
|
|
1600x1200, 270.40x202.80mm, same 6-ink Spectra family as the 7.3"
|
|
panel. Full refresh ~19s.
|
|
- Board: [Seeed's EE02](https://www.seeedstudio.com/XIAO-ePaper-DIY-Kit-EE02-for-13-3-Spectratm-6-E-Ink.html) --
|
|
a XIAO ESP32-S3 Plus (16MB flash, 8MB PSRAM) socketed into a dedicated
|
|
driver PCB, one reset + three user buttons, JST 2.0mm battery
|
|
connector with built-in charging IC.
|
|
- Wiring (source: [github.com/rkaramandi/esphome-seeed-ee02](https://github.com/rkaramandi/esphome-seeed-ee02), a community integration, not Seeed's own schematic --
|
|
treat as a starting point, confirm before relying on it): unlike
|
|
epd7in3e's single chip-select, this panel is driven as two halves
|
|
sharing one CLK/MOSI/DC/RST/BUSY bus with independent chip-selects.
|
|
|
|
| Signal | GPIO | Kconfig option |
|
|
| --- | --- | --- |
|
|
| CLK | 7 | `EPD_PIN_CLK` |
|
|
| MOSI | 9 | `EPD_PIN_MOSI` |
|
|
| CS (master half) | 44 | `EPD_PIN_CS_MASTER` |
|
|
| CS (slave half) | 41 | `EPD_PIN_CS_SLAVE` |
|
|
| DC | 10 | `EPD_PIN_DC` |
|
|
| RST | 38 | `EPD_PIN_RST` |
|
|
| BUSY | 4 | `EPD_PIN_BUSY` |
|
|
| Panel power-enable | 43 | `EPD_PIN_POWER_EN` |
|
|
|
|
User buttons are reportedly at GPIO 2/3/5, but which physical button
|
|
maps to which logical role (next/back/menu) isn't confirmed, and the
|
|
firmware's button Kconfig options (`FRAME_NEXT_BUTTON_GPIO` etc.,
|
|
`firmware/main/Kconfig.projbuild`) still range-limit to GPIO 0-7 --
|
|
the ESP32-C6's deep-sleep-wakeup-capable set, not yet verified against
|
|
the ESP32-S3's. SPI clock is reportedly reliable only up to 2MHz on
|
|
this panel/board (vs. epd7in3e's 4MHz default) -- see
|
|
`firmware/sdkconfig.ee02`.
|
|
|
|
See `firmware/components/epd13in3e/epd13in3e.c`'s own top comment for
|
|
what's needed to actually make this board work.
|