ESP32-S3 learning labs, one standalone PlatformIO project per lab. It was extracted from hardware-diary/test-esp; the full course text is in docs/course.md.
Every lab builds on its own (labs/<lab>), shares board settings through common.ini and pulls only the kit libraries it includes. labs.json is the machine-readable index (tracks, labs, environments, kit libraries, companion apps, host tests): the learning dashboard links to labs through it. The bench guide, esp-labs-web, is cloned next to this repo and reads the lab code from it at build time (FIRMWARE_DIR=../esp-labs).
flowchart LR
subgraph repo["esp-labs"]
common["common.ini<br/>board, flags, library sets"]
subgraph kit["kit/"]
inc["include/pins.h"]
libs["lib/ bench · wifi-kit · rfid-kit · rfid-lab-kit<br/>door-rules · ble-kit · sound-kit"]
ktests["test/host/ kit tests"]
end
subgraph labs["labs/<lab>/"]
ini["platformio.ini<br/>(extra_configs = ../../common.ini)"]
src["src/"]
ltests["test/host/ lab tests"]
end
apps["apps/ dashboard · ai-gateway · door-app<br/>friends-app · ble-app"]
manifest["labs.json"]
end
ini --> common
common --> kit
src -->|"#include"| libs
manifest -.->|indexes| labs
manifest -.-> apps
Run from the repo root.
uv sync # once: PlatformIO 6.2.0 into .venv
uv run pio device list # which serial port is the board on?
uv run pio run -d labs/01-hello # compile a lab (its default environment)
uv run pio run -d labs/01-hello -t upload -t monitor # flash it and watch the logs
uv run pio run -d labs/wifi-lab-w2 -e wifi-lab-w2-remote # a lab with several variations
ESP_PORT=/dev/cu.usbmodem1101 uv run pio run -d labs/01-hello -t upload # force a port
./tools/host-tests.sh # every host test, on the Mac, no boardLibraries and compiled objects are shared across labs in the root .pio/ (libdeps_dir, build_cache_dir), so switching labs doesn't download or rebuild everything.
- Create
labs/<lab>/src/main.cppand aplatformio.inilike any other lab:extra_configs = ../../common.ini, one[env:<lab>], andlib_deps = ${display.lib_deps}(orjson,web,relay,ble). - Code shared by two labs goes into
kit/lib/<name>/srcwith alibrary.json. A lab never includes another lab's files. - Add the lab to
labs.jsonand give it aREADME.md.
| Track | Lab | Environments | Kit | App |
|---|---|---|---|---|
| Intro | Meet the board | 01-hello |
none | none |
| Intro | First circuit | 02-led |
none | none |
| Display & input | The 1 | 03-display |
none | none |
| Display & input | Variation 1 | 03b-showcase, 03b-showcase-button |
bench | none |
| Display & input | Diagnostic | pin-check |
none | none |
| Wi-Fi | W1 Scan & join | wifi-lab-w1 |
bench, wifi-kit | none |
| Wi-Fi | W2 Phone control, variation 1 | wifi-lab-w2, wifi-lab-w2-remote |
bench, wifi-kit | dashboard |
| Wi-Fi | W3 Internet & AI | wifi-lab-w3 |
bench, wifi-kit | ai-gateway |
| RFID & NFC | R1 Wire & talk | rfid-lab-r1 |
rfid-lab-kit | none |
| RFID & NFC | R2 Wake a card | rfid-lab-r2 |
rfid-lab-kit | none |
| RFID & NFC | R3 Who's there | rfid-lab-r3 |
rfid-lab-kit | none |
| RFID & NFC | R4 Inside the card | rfid-lab-r4 |
rfid-lab-kit | none |
| RFID & NFC | R5 Write & count | rfid-lab-r5 |
rfid-lab-kit | none |
| RFID & NFC | R6 Edge lab | rfid-lab-r6 |
rfid-lab-kit | none |
| RFID & NFC | R7 Card manager | rfid-lab-r7 |
bench, door-rules, rfid-kit, wifi-kit | door-app |
| RFID & NFC | R8 Card friends | rfid-lab-r8 |
bench, door-rules, rfid-kit, wifi-kit | friends-app |
| RFID & NFC | R9 Vault (work in progress) | not wired yet | bench, rfid-kit, wifi-kit | none |
| Bluetooth LE | B1 Listen | ble-lab-b1 |
bench, ble-kit | none |
| Bluetooth LE | B2 Be seen | ble-lab-b2 |
bench, ble-kit | none |
| Bluetooth LE | B3 Connect & talk | ble-lab-b3 |
bench, ble-kit | none |
| Bluetooth LE | B4 Pair & trust | ble-lab-b4 |
bench, ble-kit | none |
| Bluetooth LE | B5 Phone app | ble-lab-b5 |
bench, ble-kit | ble-app |
| Bluetooth LE | B6 Keyboard & media | ble-lab-b6 |
bench, ble-kit | none |
| Bluetooth LE | B7 Music | ble-lab-b7 |
bench, ble-kit | ble-app |
| Bluetooth LE | B8 Host | ble-lab-b8 |
bench, ble-kit | none |
| Sound | S1 Hear | sound-lab-s1 |
bench, sound-kit | none |
| Sound | S2 Loudness | sound-lab-s2 |
bench, sound-kit | none |
| Sound | S3 Clap control | sound-lab-s3 |
bench, sound-kit | none |
| Sound | S4 Recorder | sound-lab-s4 |
bench, sound-kit, wifi-kit | none |
| Sound | S5 Spectrum | sound-lab-s5 |
bench, sound-kit | none |
| Sound | S6 Sound games | sound-lab-s6 |
bench, sound-kit | none |
| Sound | S7 Speaker | sound-lab-s7 |
bench, sound-kit | none |
| Sound | S8 Voice FX | sound-lab-s8 |
bench, sound-kit | none |
Released under the MIT License: free and open source, with one condition, credit the original work.
You can
- use it for anything: learning, teaching, workshops, work, commercial products
- change it, fork it, build on it, mix it into your own projects
- deploy it, share it, sell it
You must
- keep the copyright notice and the LICENSE text with any copy or substantial part you reuse. That is how the original work is credited.
Good to know
- You don't need to ask permission or tell anyone.
- Your own changes can carry any license you like, as long as the original notice stays.
- The code comes as is: no warranty, and the authors aren't liable for what you do with it.
- Third-party libraries and dependencies keep their own licenses.
This summary is a guide only; the LICENSE file is the legal text.