This project turns a Waveshare ESP32-S3 board with a 5-inch LCD into a digital Pokemon card display. Search for cards on your PC, send them one at a time over WiFi, and browse or filter them on the device — no bulk downloads required.
- Shows Pokemon cards on a 5-inch LCD screen (1024x600, RGB565)
- Search cards from the PC web tool (Pokemon TCG API)
- Send cards to the expositor over WiFi (
pokemon.local) - Builds an incremental on-device catalog for filtering (set, year, illustrator, rarity, language)
- Stores cards on the SD card with thumbnails
- Slideshow mode, touch gestures, and a web UI served from the SD card
- OTA firmware updates from the device web page
- Waveshare ESP32-S3 RGB 5" LCD board (1024x600 version works best)
- MicroSD card (FAT32 format)
- WiFi connection (for PC-to-device transfer and remote control)
- Python 3 and PlatformIO on your PC
- Wiki: ESP32-S3-Touch-LCD-5 Wiki
- Schematic: ESP32-S3-Touch-LCD-5-Sch.pdf
The firmware builds with PlatformIO — no Arduino IDE setup needed. Board settings, the ESP32 core (3.3.7 via pioarduino), and library versions are pinned in platformio.ini for reproducible builds.
- Install PlatformIO (CLI or the VS Code extension):
pipx install platformio # or: pip install platformio - Build and upload (connect the board via USB first):
pio run -t upload pio device monitor # serial monitor at 115200 baud
The first build downloads the toolchain and libraries automatically (takes a few minutes).
From the repository root, create a virtual environment and install dependencies:
python3 -m venv .venv
source .venv/bin/activate # Windows: .venv\Scripts\activate
pip install -r tools/requirements.txtRegister for a free API key at dev.pokemontcg.io and export it:
export POKEMONTCG_API_KEY=your_key_hereWithout a key you are limited to about 1,000 requests/day and 30/minute. With a free key you get 20,000/day.
Start the server from the tools folder (with the venv active):
cd tools
uvicorn server:app --port 3000Open http://localhost:3000 in your browser.
Workflow:
- Search — find cards by name, set, artist, type, or year
- Collection — save cards you want to send later
- Send to expositor — click Send to expositor on a single card, or Send collection to expositor to queue them one at a time over WiFi
Each sent card is converted to display format, pushed to the device, and added to the on-device catalog (catalog.bin) so filtering keeps working without downloading whole sets.
Cards are stored locally under images/collection/ on your PC and mirrored to the device SD card.
The status pill at the top shows whether the expositor is reachable at pokemon.local.
The text shown next to each card (name, set, rarity, etc.), the font, and the size are configurable in tools/templates.json. Pick one of the bundled styles (collector, minimal, playful, clean) by changing "active", or define your own. Bundled fonts live in tools/fonts/ (OFL / Apache 2.0 licensed).
Over WiFi (recommended): use the PC web UI — Send to expositor on a search result, or Send collection to expositor from the Collection tab. Cards go straight to pokemon.local with a catalog update.
Via SD card: copy these folders from your PC to the SD card:
images/collection/ -> /images/collection/ (.raw files + thumbnails)
images/catalog/ -> /images/catalog/ (catalog.bin, facets.json)
web/ -> /web/ (on-device browse/filter UI)
Insert a FAT32 SD card and power on the device — it creates /images/ automatically if missing.
The device connects to WiFi in two ways:
Client mode: Connects to your WiFi network. Check the serial monitor for the IP address, or use http://pokemon.local/.
Access Point mode: If it cannot connect to WiFi, it creates its own network called PokemonExpositor. Connect to it and go to http://192.168.4.1.
Copy the repo's web/ folder to /web/ on the SD card, then open http://pokemon.local/.
- Browse & Filter — thumbnail grid with filters for set, year, illustrator, rarity, language, and free text; then Play selection to run a slideshow of exactly those cards (filtering runs on the device, no PC needed)
- Touch — gesture thresholds (swipe distance, tap/long-press timing) editable at runtime, saved to
/config/touch_config.json - System — live status and OTA firmware update
If /web/index.html is missing, the device falls back to the classic built-in page at /settings.
Pokemon-Card-Expositor/
├── platformio.ini # Build configuration (pinned versions)
├── src/ # Firmware sources (ESP32)
│ ├── main.cpp
│ └── *.h / *.cpp # System managers
├── images/ # Local card storage (gitignored)
│ ├── collection/ # Converted .raw + .thumb.jpg per card
│ └── catalog/ # catalog.bin + facets.json
├── tools/ # PC web tool + conversion pipeline
│ ├── server.py # FastAPI server (search + send)
│ ├── card_pipeline.py # Convert, catalog update, WiFi push
│ ├── catalog_writer.py # Incremental catalog.bin writer
│ ├── pc_*.py # Image conversion modules
│ ├── index.html, app.js # PC web UI
│ └── requirements.txt
├── web/ # On-device UI (copy to SD /web/)
└── test/ # Native C++ tests (catalog/filter)
Firmware — edit src/project_config.h for WiFi, display brightness, debug output, and feature flags.
PC tool — useful environment variables:
| Variable | Default | Description |
|---|---|---|
POKEMONTCG_API_KEY |
— | Pokemon TCG API key (strongly recommended) |
EXPOSITOR_HOST |
pokemon.local |
Device hostname for WiFi push |
SEND_DELAY_SEC |
2 |
Pause between cards in a batch send |
DEFAULT_CARD_LANG |
en |
Language stored in the catalog |
pio test -e native # C++ catalog/filter logic (no board)
source .venv/bin/activate
pytest # Python pipeline + API (from repo root)The native suite includes a contract test that decodes a catalog.bin blob produced by tools/catalog_writer.py, keeping the Python writer and the C++ reader in sync.
Device won't start: Check your SD card is FAT32 formatted. Look at the serial monitor (115200 baud).
WiFi not working: Double-check your WiFi password. Try access point mode instead.
No cards showing: Make sure .raw files are under /images/collection/ on the SD card.
Web interface won't load: Check the IP address in the serial monitor, or try http://pokemon.local/. Try a different browser.
Search or send fails (429): Set POKEMONTCG_API_KEY or wait before retrying.
Expositor shows offline in the PC tool: Ensure PC and device are on the same WiFi network; ping pokemon.local.
Hardware:
- Some fast SD cards don't work — stick to Class 10 or slower (tested with a 32 GB Samsung card)
- Screen can flicker when changing images, especially in the upper part of the card
Software:
- Set
POKEMONTCG_API_KEYto avoid search/send rate limits (free at dev.pokemontcg.io) - Really big source images (>2048px) might not convert properly
- WiFi drops out occasionally (automatic reconnect)
Performance:
- Takes 10–15 seconds to boot
- First image load is slow while it processes
- Card search can be slow when the public API is under heavy load
Compatibility:
- Only FAT32 SD cards work
- Toolchain and library versions are pinned in
platformio.ini— bumping them may break the display
Quick fixes:
- If it crashes, restart it
- If the API is rate-limiting you, wait and retry
- If WiFi is flaky, power-cycle the device
- If compilation fails, run
pio run -t cleanand rebuild
Check GitHub issues for ongoing work.
Anyone can contribute:
- Found a bug? Report it
- Have an idea? Suggest it
- Want to code? Fork the repo and open a pull request
- Documentation unclear? Help improve it
Standard GitHub workflow:
- Fork this repo
- Create a branch (
git checkout -b my-feature) - Commit changes (
git commit -m 'Add my feature') - Push (
git push origin my-feature) - Open a pull request
This project is licensed under CC BY-NC-SA 4.0.
- You can share, copy, and modify this project
- You must credit the original project
- Derivative works must use the same license
- Commercial use is not allowed
Pokemon and Pokemon cards are trademarks of their owners. This project is for personal, non-commercial use and learning.
Made for Pokemon card fans