Push photos from your iPhone straight to a Seeed XIAO 13.3″ color e‑paper panel over your own Wi‑Fi — no cloud, no app. The device runs a tiny web server; you open a page in Safari (or share a photo to it), it resizes and dithers the picture to the panel's 6 colors, shows it, and keeps a small gallery in the device's internal flash. No microSD required.
Built for the Seeed Studio XIAO ePaper Display Board (EE02) with a 13.3″ E Ink Spectra 6 panel:
| Thing | Value |
|---|---|
| MCU | Seeed XIAO ESP32‑S3 (Plus: 16 MB flash, 8 MB OPI PSRAM) |
| Driver board | XIAO ePaper Display Board (EE02) — JST battery connector + charge IC, 3 buttons |
| Panel | 13.3″ E Ink Spectra 6 (6 colors), 1200×1600 portrait, full‑refresh only (~30–40 s) |
| Panel controller | T133A01, dual‑chip (two 600‑px halves, separate chip‑selects) |
| e‑paper SPI | SCK 7, MOSI 9, DC 10, RST 38, BUSY 4 (active‑low), CS 44 (left half), CS1 41 (right half), panel‑enable 43 (drive HIGH) |
| Battery sense | ADC 1 (÷2 divider), load‑switch enable 6 (drive HIGH) |
| Panel driver | vendored GxEPD2_T133A01_1200x1600 via GxEPD2 GxEPD2_7C |
This board is easy to mis‑identify — the firmware talks to the T133A01 dual‑chip controller with the EE02 pin map above. Everything hardware‑specific lives in src/config.h.
- 📶 Joins your home Wi‑Fi; first‑time setup via an
InkFrame-Setuphotspot. - 🌐 Reachable at http://inkframe.local (mDNS) or its IP (shown on the panel).
- 📱 Mobile web UI: pick a photo → Send to frame. No app to install.
- 🎨 On‑device pipeline: JPEG decode → fit (cover/contain) → Floyd–Steinberg / Bayer dithering to the Spectra‑6 palette → e‑paper.
- 🖼️ Gallery in internal flash: show / delete / next / clear‑all, remembers the current photo. Thumbnails are the actual 6‑color rendering; tap to enlarge.
- 🎞️ Slideshow: auto‑cycle on a timer (1 min – 1 h).
- 🎛️ Pick dithering and fit from the web UI.
- 🔋 Optional battery gauge on the panel + % in the web UI.
- ⚡ e‑paper keeps its image with no power, so reboots don't redraw.
- Seeed XIAO ESP32‑S3 seated on the XIAO ePaper Display Board (EE02) + 13.3″ Spectra 6 panel, and a USB‑C cable.
- A 2.4 GHz Wi‑Fi network (the ESP32‑S3 does not do 5 GHz).
- PlatformIO (CLI or the VS Code extension).
Photos are stored in the device's internal flash (LittleFS fills the 16 MB
chip, ~13 MB usable) as compact packed e‑paper frames (~960 KB each → roughly a
dozen photos). microSD is off by default; set USE_SD 1 in
src/config.h if your board has a slot and you want more capacity.
# from the project root
pio run # compile
pio run -t upload # flash over USB-C
pio device monitor # optional: view logs (115200)If
uploadcan't find the port, put the board in download mode — hold BOOT, tap RESET, release BOOT — then retry. The port appears as/dev/cu.usbmodem*(macOS) /COMx(Windows).
Recommended — join your network directly:
cp src/secrets.h.example src/secrets.h, then setWIFI_SSID/WIFI_PASS(2.4 GHz). Optionally setWEB_USER/WEB_PASSto require a web login.secrets.his git‑ignored, so your password is never committed.- Build + flash. On boot the frame joins your Wi‑Fi and shows its address on the panel.
- Open http://inkframe.local (or the IP on the panel) from the same network.
Fallback — on‑device hotspot (only when no Wi‑Fi is configured or saved):
- Join Wi‑Fi
InkFrame-Setup(passwordphotoframe). - Open http://192.168.4.1 (not
.local— mDNS isn't up in hotspot mode) and enter your Wi‑Fi → the frame restarts and joins.
Option A — Safari (simplest):
Open http://inkframe.local → Choose photo → Send to frame. iOS converts
HEIC to JPEG automatically.
⏳ Displaying a photo takes ~30 seconds — this is normal. A color e‑paper panel physically redraws slowly. After the upload the page shows a live "Updating the panel… Ns" counter, then "✅ Done — your photo is now on the frame." The web UI stays usable during the wait — just leave the page open.
Option B — Share‑sheet Shortcut (send straight from Photos):
- Shortcuts app → + → Add Action → Get Contents of URL.
- URL:
http://inkframe.local/api/upload - Show More → Method
POST, Request BodyForm, add a field of type File, Key =photo, Value = Shortcut Input. - Enable Show in Share Sheet (accept Images) and name it "Send to InkFrame".
- In Photos: share a picture → Send to InkFrame. (It still takes ~30 s to show on the panel — the Shortcut just fires the upload and returns.)
iPhone (Safari / Shortcut)
│ multipart POST /api/upload
▼
WebServer (sync) ─ buffers JPEG in PSRAM ─► TJpg decode ─► resize/fit ─►
dither ─► pack 4bpp ─► /photos/<id>.epd (LittleFS)
│ queues render id
▼
main loop ─ read .epd ─► unpack ─► GxEPD2 dual‑chip full refresh (~30–40 s)
- The web server is synchronous on purpose: the long e‑paper refresh runs in the main loop so nothing else fights over the shared SPI bus.
- Photos are read fully into PSRAM before the panel is driven.
- Source map: src/config.h (all pins/options), src/image_pipeline.cpp (decode/dither), src/GxEPD2_T133A01_1200x1600.cpp (dual‑chip panel driver), src/display_epd.cpp, src/storage.cpp (LittleFS), src/net.cpp (Wi‑Fi/mDNS), src/web.cpp (+ src/web_ui.h).
Everything hardware‑specific is in src/config.h and the driver class. For a different Spectra‑6 size, swap to the matching GxEPD2 driver and update the pin map; the T133A01 driver here is specific to the 13.3″ dual‑chip panel (it splits every frame into a left/right 600‑px half).
- To receive photos the frame stays awake on Wi‑Fi (it does not deep‑sleep) — run it on USB power; battery life is short with Wi‑Fi always on.
- Spectra‑6 has 6 colors; expect poster‑like results. Cover/contain fit is selectable in the web UI.
- Displaying a photo takes ~30 s — color e‑paper redraws slowly. The web UI shows a live countdown and confirms when it's on the frame, so it isn't frozen.
- Photos are stored as the processed e‑paper image (not the original JPEG), so about a dozen fit in flash; the gallery shows the on‑panel rendering — ideal for checking quality, but the full‑res original isn't kept on‑device.
- The on‑panel battery gauge needs a battery connected; on USB‑only power the reading may be off — turn it off under Rendering.
- Don't refresh e‑paper excessively; frequent full refreshes shorten panel life.
MIT. Bundles GxEPD2, Adafruit GFX, TJpg_Decoder and ArduinoJson via PlatformIO — each under its own license.