| Supported Targets | ESP32-S3 · Project Babble · FaceFocusVR |
|---|
Firmware and tools for OpenIris — Wi‑Fi, UVC streaming, and a Python setup CLI.
- ESP‑IDF firmware (C/C++) with modules for Camera, Wi‑Fi, UVC, REST/Serial commands, and more
- Python tools for setup over USB serial:
tools/switchBoardType.py— choose a board profile (builds the right sdkconfig)tools/setup_openiris.py— interactive CLI for Wi‑Fi, MDNS/Name, Mode, LED PWM, Logs, and a Settings Summary
- Composite USB (UVC + CDC) when UVC mode is enabled (
GENERAL_INCLUDE_UVC_MODE) for simultaneous video streaming and command channel - LED current monitoring (if enabled via
MONITORING_LED_CURRENT) with filtered mA readings - Configurable debug LED + external IR LED control with optional error mirroring (
LED_DEBUG_ENABLE,LED_EXTERNAL_AS_DEBUG) - Auto‑discovered per‑board configuration overlays under
boards/ - Command framework (JSON over serial / CDC / REST) for mode switching, Wi‑Fi config, OTA credentials, LED brightness, info & monitoring
- Single source advertised name (
CONFIG_GENERAL_ADVERTISED_NAME) used for both UVC device name and mDNS hostname (unless overridden at runtime)
If you’re starting fresh on Windows, this workflow is smooth and reliable:
- Install tooling
- Git: https://git-scm.com/downloads/win
- Visual Studio Code: https://code.visualstudio.com/
- Get the source code
- Create a folder where you want the repo (e.g.,
D:\OpenIris-ESPIDF\). In File Explorer, right‑click the folder and choose “Open in Terminal”. - Clone and open in VS Code:
git clone https://github.com/lorow/OpenIris-ESPIDF.git
cd OpenIris-ESPIDF
code .- Install the ESP‑IDF VS Code extension
- In VS Code, open the Extensions tab and install: https://marketplace.visualstudio.com/items?itemName=espressif.esp-idf-extension
- Set the default terminal profile to Command Prompt
- Press Ctrl+Shift+P → search “Terminal: Select Default Profile” → choose “Command Prompt”.
- Restart VS Code from its normal shortcut (not from Git Bash). This avoids running ESP‑IDF in the wrong shell.
- Configure ESP‑IDF in the extension
- On first launch, the extension may prompt to install ESP‑IDF and tools — follow the steps. It can take a while.
- If you see the extension’s home page instead, click “Configure extension”, pick “EXPRESS”, choose “GitHub” as the server and version “v5.4.2”.
- Then open the ESP‑IDF Explorer tab and click “Open ESP‑IDF Terminal”. We’ll use that for builds.
After this, you’re ready for the Quick start below.
Boards are auto‑discovered from the boards/ directory. First list them, then pick one:
Windows (cmd):
python .\tools\switchBoardType.py --list
python .\tools\switchBoardType.py --board seed_studio_xiao_esp32s3 --diffmacOS/Linux (bash):
python3 ./tools/switchBoardType.py --list
python3 ./tools/switchBoardType.py --board seed_studio_xiao_esp32s3 --diffNotes:
- Use
--listto see all detected board keys. - Board key = relative path under
boards/with/replaced by_(and duplicate tail segments collapsed, e.g.project_babble/project_babble->project_babble). --diffshows what will change vs the currentsdkconfig.- You can also pass partial or path‑like inputs (e.g.
facefocusvr/eye_L), the tool normalizes them.
- Set the target (e.g., ESP32‑S3).
- Build, flash, and open the serial monitor.
- (Optional) For UVC mode ensure
GENERAL_INCLUDE_UVC_MODE=y. If you want device to boot directly into UVC: also setSTART_IN_UVC_MODE=y. - Disable Wi‑Fi services for pure wired builds:
GENERAL_ENABLE_WIRELESS=n.
Configure the device over USB serial.
Before you run it:
- If you still have the serial monitor open, close it (the port must be free).
- In VS Code, open the sidebar “ESP‑IDF: Explorer” and click “Open ESP‑IDF Terminal”. We’ll run the CLI there so Python and packages are in the right environment.
Then run:
python .\tools\setup_openiris.py --port COMxxExamples:
- Windows:
python .\tools\setup_openiris.py --port COM69, … - macOS: idk
- Linux: idk
What the CLI can do:
- Wi‑Fi menu: automatic (scan → pick → password → connect → wait for IP) or manual (scan, show, configure, connect, status)
- Set MDNS/Device name (also used for the UVC device name)
- Switch mode (Wi‑Fi / UVC / Setup)
- Adjust LED PWM
- Show a Settings Summary (MAC, Wi‑Fi status, mode, PWM, …)
- View logs
- Internally, the serial number is derived from the Wi‑Fi MAC address.
- The CLI displays the MAC by default (clearer); it’s the value used as the serial number.
- The UVC device name is based on the MDNS hostname.
CONFIG_GENERAL_ADVERTISED_NAME (Kconfig) defines the base name announced over:
- USB UVC descriptor (appears in OS camera list)
- mDNS hostname / service name
Runtime override: If the setup CLI (or a JSON command) provides a new device name, that value supersedes the compile-time default until next flash/reset of settings.
- Fast Wi‑Fi setup: in the CLI, go to “Wi‑Fi settings” → “Automatic setup”, then check “status”.
- Change name/MDNS: set the device name in the CLI, then replug USB — UVC will show the new name.
- Adjust brightness/LED: set LED PWM in the CLI.
- Switch to UVC mode over commands (CDC/serial):
{"commands":[{"command":"switch_mode","data":{"mode":"uvc"}}]}then reboot. - Read filtered LED current (if enabled):
{"commands":[{"command":"get_led_current"}]}
main/— entry pointcomponents/— modules (Camera, WiFi, UVC, CommandManager, …)tools/— Python helper tools (board switch, setup CLI, scanner)
If you want to dig deeper: commands are mapped via the CommandManager under components/CommandManager/....
When UVC support is compiled in, the device enumerates as a composite USB device:
- UVC interface: video streaming (JPEG frames)
- CDC (virtual COM): command channel accepting newline‑terminated JSON objects
Example newline‑terminated JSON commands over CDC (one per line):
{"commands":[{"command":"ping"}]}
{"commands":[{"command":"get_who_am_i"}]}
{"commands":[{"command":"switch_mode","data":{"mode":"wifi"}}]}
Chained commands in a single request (processed in order):
{"commands":[
{"command":"set_mdns","data":{"hostname":"tracker"}},
{"command":"set_wifi","data":{"name":"main","ssid":"your_network","password":"password","channel":0,"power":0}}
]}
Responses are JSON blobs flushed immediately.
Enabled with MONITORING_LED_CURRENT=y plus shunt/gain settings. The task samples every CONFIG_MONITORING_LED_INTERVAL_MS ms and maintains a filtered moving average over CONFIG_MONITORING_LED_SAMPLES samples. Use get_led_current command to query.
| Kconfig | Effect |
|---|---|
| LED_DEBUG_ENABLE | Enables/disables discrete status LED GPIO init & drive |
| LED_EXTERNAL_CONTROL | Enables PWM control for IR / external LED |
| LED_EXTERNAL_PWM_DUTY_CYCLE | Default duty % applied at boot (0–100) |
| LED_EXTERNAL_AS_DEBUG | Mirrors only error patterns onto external LED (0%/50%) when debug LED absent or also for redundancy |
Each file under boards/ overlays sdkconfig.base_defaults. The merge order: base → board file → (optional) dynamic Wi‑Fi overrides via switchBoardType.py flags. Duplicate trailing segment directories collapse to unique keys.
- UVC doesn’t appear on the host?
- Switch mode to UVC via CLI tool, replug USB and wait 20s.
- Create a new config file under
boards/(you can nest folders): for exampleboards/my_family/my_variant. - Populate it with only the
CONFIG_...lines that differ from the shared defaults. Shared baseline lives inboards/sdkconfig.base_defaultsand is always merged first. - The board key the script accepts will be the relative path with
/turned into_(example:boards/my_family/my_variant->my_family_my_variant). - Run
python tools/switchBoardType.py --listto verify it’s detected, then switch using-b my_family_my_variant. - If you accidentally create two files that collapse to the same key the last one found wins—rename to keep keys unique.
Tips:
- Use
--diffafter adding a board to sanity‑check only the intended keys change. - For Wi‑Fi overrides on first flash: add none—pass
--ssid/--passwordwhen switching if needed.
The firmware uses a small set of LED patterns to indicate status and blocking errors. When LED_DEBUG_ENABLE is disabled and LED_EXTERNAL_AS_DEBUG is enabled the external IR LED mirrors ONLY error patterns (0%/50% duty). Non‑error patterns are not mirrored.
Feedback, issues, and PRs are welcome.