Adding a Board Variant¶
The scanner firmware supports a fixed set of boards, each with its own compile-time pin map and PlatformIO build environment. If your ESP32 board isn't on the list, you can add it yourself and submit a PR. This page walks through every file a new variant touches.
Current variants: esp32dev (WROOM), esp32s3zero, esp32s3devkitc, esp32c3.
Before you start¶
- Check whether an existing variant already works. Boards with the same chip and compatible free GPIOs can often run an existing build unmodified. Wire it per the closest variant's wiring guide and test before adding a new env.
- Pins are compile-time on purpose. Runtime pin configuration for the SPI/NFC bus is not planned — a wrong bus pin produces a scanner that won't boot cleanly, which is a support problem we've chosen to avoid. The status LED pin is becoming runtime-configurable separately (#203).
Pin selection rules¶
Every chip family has pins you must avoid:
| Chip | Avoid | Reason |
|---|---|---|
| ESP32 (WROOM) | GPIO 0, 2, 12, 15 as outputs to peripherals that drive them at boot | Strap pins |
| ESP32 (WROOM) | GPIO 34-39 for outputs | Input-only |
| ESP32-S3 (N16R8 / octal PSRAM) | GPIO 33-37 | Reserved by PSRAM |
| ESP32-S3 | GPIO 0, 3, 45, 46 | Strap pins |
| ESP32-C3 | GPIO 2, 8, 9 | Strap pins |
| All | GPIO 6-11 (classic ESP32) / flash pins | Connected to SPI flash |
A peripheral that can hold a strap pin low at power-on (like an NFC reader's RST line) will put the board into download mode. This is why the C3 variant wires PN5180 RST to GPIO 0 (not a strap pin on C3) instead of GPIO 2.
Files to change¶
1. include/BoardPins.h (scanner repo)¶
Add an #elif defined(BOARD_YOUR_BOARD) block defining the full pin set. Copy the closest existing variant as a starting point. Pins for unsupported peripherals get -1 (see the C3 block, which disables TFT and keypad).
2. platformio.ini¶
Add a new [env:yourboard] section. Set board, flash size/mode, and a -DBOARD_YOUR_BOARD=1 build flag that selects your BoardPins block. Keep platform = espressif32@6.10.0 inherited from [env] — the pin is deliberate (Arduino 3.x breaks the build).
3. .github/workflows/release.yml¶
The release workflow builds each env explicitly. Add your env to three places: the pio run -e build steps, the cp .pio/build/... copy block (firmware, bootloader, partitions), and the release-files list.
4. Wiring documentation (this site)¶
Add a pinout section for your board to wiring-pn5180.md and/or wiring-pn532.md, matching the format of the existing tables. Note any scoping decisions (e.g. "no TFT on this board — single SPI controller").
5. Optional: web flasher¶
Web-flasher manifests live in this site's repo (docs/installation/manifest-*.json) and are updated by the release workflow. Mention in your PR that the board should be added to the flasher and we'll wire it up.
6. Optional: installer¶
The interactive installer keeps its own board list (spoolsense_installer/constants.py in the installer repo — display name, chip ID, firmware suffix, minimum flash, bootloader offset). ESP32 uses offset 0x1000; S3 and C3 use 0x0.
Testing checklist¶
Before opening the PR:
- [ ] Firmware builds:
pio run -e yourboard - [ ] Board boots and joins WiFi (or starts AP mode)
- [ ] NFC reader initializes and reads a tag (
http://spoolsense.local/logsshows the detection) - [ ] Any scoped-in peripherals (LCD, LED) work
- [ ] Cold boot works from a plain power supply, not just USB-from-computer
Submitting¶
Open a PR against dev in spoolsense_scanner with the firmware changes, and mention the wiring-doc addition in the PR description (docs live in this site's repo — we can take the wiring table from your PR text). Include what hardware you tested on.