For Agents

Living index of themes for this project. Each H2 is a topic; bullets are wikilinks to related notes. Updated by obsidian-documenter when documenting work. Read by historian at bootstrap. Topics kept alphabetical.

Architecture — What Actually Exists

  • Receiver Split — and a Proposal That Might Add One — ⚠️ confirmed by exhaustive search 2026-09-03: lightaim is ONE ESP32-S3, all wired. The joystick is cabin-mounted on a 4-wire run (W9) back to the same board that drives the servo — no sender, no receiver, no radio link. A battery-powered joystick “sender” is a brand-new proposal introduced 2026-09-02 with no transport chosen; it is not existing architecture and must not be designed against as though it were. Helped by a prior decision: the joystick is on GPIO1/ADC1 specifically so WiFi could be added later without re-routing
  • buttonbox — the same battery-vs-mains and transport questions, worked through end to end on a different device
  • esp32-battery-deep-sleep — the research the sender proposal would need

Control Design

  • lightaimvelocity control, not position control: deflection sets the rotation rate, the angle is integrated, so the light holds where you left it on release. Position control was rejected (snap-back to centre makes aiming impossible). Deadband + expo shaping; boot auto-calibration of centre with a 1200–2900 plausibility guard; short-press SW homes to 90°, hold ≥600 ms re-calibrates

Cross-Project

ESP32-S3 Gotchas

  • 2026-08-12-lightaim-bench-bringup — ⭐ LEDC caps at 14-bit duty resolution on the S3 (classic ESP32 does 20); at 16 bits LEDC never initialises and there is zero PWM output while the firmware looks healthy. ⭐ Bootloader flashes at 0x0, not the classic ESP32’s 0x1000. ⭐ Only the CH343 UART port can flash a running chip; the native USB/OTG port reports No serial data received on both reset modes. ⭐ ADC2 is unusable while WiFi is active — hence GPIO1/ADC1 even though this firmware has no WiFi
  • lightaim — pin map and the strapping/USB pins deliberately avoided (GPIO0, GPIO3, GPIO19, GPIO20, GPIO45, GPIO46)

Firmware Constants & Limits

  • Full Speed Is a Code Constant, Not a Power Limit — ⭐ MAX_RATE_DEG_S = 60.0f in src/main.cpp is the slew cap — not the supply, not the servo. An MG996R at 6 V does ~430 °/s, so the rig runs at ~1/7 of mechanical capability; the XL4015 at 6.0 V has never browned out and no current has ever been measured. ✅ Cancelled a UBEC + 2200 µF purchase aimed at a power problem that does not exist. ⛔ ANGLE_MIN_DEG/ANGLE_MAX_DEG must come off their 0/180 defaults FIRST — a stalled MG996R strips gears in seconds and faster slew makes hitting a stop more likely. General rule: before buying hardware to raise a ceiling, check whether the ceiling is a literal in the source
  • Tuning constants — the full constant table and what each one does

Hardware Hazards

  • lightaim — 🔴 the joystick’s +5V pad must be fed from 3V3 (resistive divider; 5 V reaches a 3.3 V ADC pin and damages it — the silkscreen lies). 🔴 set ANGLE_MIN/MAX_DEG to real mechanical limits before bolting to the horn — a stalled MG996R strips its gears in seconds. 🔴 never power the servo from the board’s 5 V pin (~2.5 A stall brownout). 🔴 automotive 12 V is 13.8–14.4 V running, 6–9 V cranking, 35–40 V+ load dump against the XL4015’s 38 V ceiling → TVS required

Power & Wiring

  • inventory — ⭐ what is physically owned, vault-wide — the receipts behind this project’s parts gap. 🔴 The single XL4015 in the house is currently set to 6.0 V for this bench: it is a configured part in a live rig, not free stock, and anything that borrows it must set the pot back. MINI560-5V-5A 100.423.75 (552 Ft) is wanted independently by the KrakenSDR car rig too (Pi 5 browns out at 5 V/3 A) — buy at least 2. Confirms the SMBJ33A, the 2 A fuse and the reverse-polarity part are genuinely unowned — but soldering is not a blocker, 3 irons are owned (models unknown)
  • lightaim — split supply: servo on an XL4015 @ 6 V, ESP32 on USB (bench) or its own 5 V buck (vehicle). Common ground is mandatory (W4 bench / W10 vehicle) — PWM is a voltage relative to ground. The split is why no bulk cap was needed. Vehicle chain: 2 A fuse → reverse-polarity + SMBJ33A TVS → terminal split → two bucks
  • Parts Gap — Not Yet Orderedonly one buck was ordered; the second 5 V rail (MINI560-5V-5A 100.423.75 recommended), fuse, TVS and reverse protection are not yet bought
  • Why WireViz and not Fusion Electronics — WireViz chosen over Fusion Electronics (no Fusion MCP, PCB-oriented, needs custom symbols for non-stock parts)

Toolchain

  • 1. Toolchain: uvx + PlatformIO needs pipuvx --from platformio must be --with pip: PlatformIO shells out to pip install for esptool’s deps and a uvx env has none → No module named pip then MissingPackageManifestError. Recovery also needs rm -rf ~/.platformio/packages/tool-esptoolpy. Applies to any PlatformIO-via-uvx use
  • 2026-08-12-lightaim-bench-bringup — Arduino core landed at 2.0.17, so the #if ESP_ARDUINO_VERSION_MAJOR >= 3 guard takes the 2.x ledcSetup/ledcAttachPin branch; build on the Mac, flash on the mainframe from the ESP-IDF container

Unresolved

  • Receiver Split — and a Proposal That Might Add One — ❓ the battery-powered joystick sender is a PROPOSAL, not architecture. Introduced 2026-09-02, no transport chosen — not WiFi, not ESP-NOW, not BLE, not LoRa. Nothing about it is decided
  • Full Speed Is a Code Constant, Not a Power Limit — ❓ the rate can be raised ~7×, but only after ANGLE_MIN/MAX_DEG are set to real mechanical limits. Neither has been done
  • Open Decision: Parked or Movingparked vs aimed at speed decides the mechanics. Parked: MG996R is fine. Moving: wind load is a constant force the servo fights (buzz, continuous current, gear wear) → wants a worm-gear drive (self-locking) or a DS5160. Cutting PWM when idle is deliberately not implemented — an unpowered servo has no holding torque and the light would flop