diff --git a/docs/hardware-config-plan.md b/docs/hardware-config-plan.md index d1e1747..7a0e78e 100644 --- a/docs/hardware-config-plan.md +++ b/docs/hardware-config-plan.md @@ -402,6 +402,27 @@ Deploy host-before-firmware (A.6). Fix the `Application.cpp:1040` literals in th existing fleet that drops yaw 50000 → 30000, a real behaviour change that wants a deliberate rig check rather than a silent correction. +> ### ⚠️ The Delta fleet is NOT migrated, and flashing it first would strand it +> +> Checked 2026-09-23: tower **111 has no `/etc/fire_gimbal_control/hardware.ini`**. +> Only tower 121 has been migrated. This is a live hazard rather than a leftover +> chore, because the firmware half is now written: **an axis with no declared +> drivetrain sits in `NEEDCFG` and refuses to move.** Flashing 111 with current +> firmware today would leave it unable to home, with nothing wrong that an +> operator could see on the board. +> +> The ordering rule above is what prevents it, and it is not advisory: +> +> 1. Write 111 a `hardware.ini` — `hardware/lattepanda-iota/install.sh --stdout` +> generates the shape; the Delta's own values come from its `config.ini`. +> 2. Deploy the **host** and run `test hardware`. It must pass on the old +> firmware, which is the point of the `_current`/`_declared` metrics reporting +> an absent field as unconfirmable rather than as a mismatch. +> 3. Only then flash the firmware, and re-run `test hardware`. +> +> Until step 1 is done for every Delta tower, phase 1's gate — "`test hardware` +> green on every existing tower" — is **not met**, whatever 121 reports. + ## 14. Firmware changes, collected - **Per board** → `platform_leonardo.h` / `platform_iota.h`: pin map plus the three AVR-isms diff --git a/docs/hardware-porting-plan.md b/docs/hardware-porting-plan.md index 8a5c1ae..7c59b98 100644 --- a/docs/hardware-porting-plan.md +++ b/docs/hardware-porting-plan.md @@ -133,11 +133,13 @@ size or override it, or the filesystem/OTA layout will be wrong. > > So the **first** flash of a factory board needs the REPL trick or a physical > BOOTSEL press — one time per board, and worth knowing before someone drives to -> a mast. The **update** case is the one that still has no answer: our firmware -> honours the 1200-baud reset but returns to the application, so a tower cannot -> currently be re-flashed over the network at all. +> a mast. **That one is still true.** > -> **Fixed by a `BOOTSEL` serial command** calling arduino-pico's +> The **update** case was the one that had no answer at the time of that table: +> our firmware honoured the 1200-baud reset but returned to the application, so a +> tower could not be re-flashed over the network at all. +> +> **Since fixed by a `BOOTSEL` serial command** calling arduino-pico's > `rp2040.rebootToBootloader()` — implemented and proven on tower 121 the same > day. The full loop now runs with nobody at the board: > @@ -295,7 +297,7 @@ commit `aab1925`. | Phase | Item | State | |---|---|---| -| 0 | Remote-flash question researched — two viable paths, design rule derived (§2) | **done, and now measured on the board: neither works** (§2). First flash needs the MicroPython REPL or BOOTSEL; remote *update* is unsolved pending a `BOOTSEL` command | +| 0 | Remote-flash question researched — two viable paths, design rule derived (§2) | **done, and solved** (§2). Both researched paths turned out not to work on the board; the answer was a `BOOTSEL` serial command, proven on tower 121 and now sent automatically by `firmware/deploy.sh` before every RP2040 upload. The **first** flash of a factory board still needs the MicroPython REPL or a physical BOOTSEL press — once per board | | 2 | **Phase 2 gate: RP2040 + TMC5160-BOB at 3.3 V** | **PASSED** on tower 121, 2026-09-15: `IOIN Y=0x3000001E version=0x30`, encoder reading (`X_ENC`), one axis, `speed=3000` | | 2 | `src/platform.h` — reset cause and free RAM behind one interface per MCU family | **done** | | 2 | `Serial.begin()` moved ahead of all hardware init, so a wedged image stays flashable | **done** | @@ -303,7 +305,7 @@ commit `aab1925`. | 2 | Per-board pin map + `NUM_AXES` in `platform_leonardo.h` / `platform_iota.h`, as-built wiring | **done** — compile-time, not yet generated from `hardware.ini` | | 2 | Pins + `NUM_AXES` generated from `hardware.ini` | **not started, no longer blocked** — the config plan it waited on is complete. The last open phase-2 item | | 3 | Yaw homing on the real drivetrain | **done** — the endstop was being sheared through at full torque; homing at 189 mA holds. See below | -| 1 | Phase 1 in full — `hardware.ini`, the config handshake, presence reconciliation, `test hardware` | **done.** [hardware-config-plan.md](hardware-config-plan.md) is complete and validated on tower 121; the gate ("`test hardware` green on every existing tower") is met on 121, and still wants running against the Delta fleet | +| 1 | Phase 1 in full — `hardware.ini`, the config handshake, presence reconciliation, `test hardware` | **built and validated on 121, NOT rolled out.** [hardware-config-plan.md](hardware-config-plan.md) is complete, but tower **111 has no `hardware.ini` at all** (checked 2026-09-23), so the gate ("`test hardware` green on every existing tower") is not met. Flashing a Delta before writing it one would strand the axis in `NEEDCFG` — see the migration warning in [the config plan §13](hardware-config-plan.md#13-migration) | > **Where the firmware gets built.** PlatformIO is not installed on the dev box; the firmware is built > *remotely on a tower* by `firmware/deploy.sh --compile-only`. Locally, the Arduino-free sources diff --git a/docs/known-issues.md b/docs/known-issues.md index 9d49ae3..04cd886 100644 --- a/docs/known-issues.md +++ b/docs/known-issues.md @@ -31,7 +31,7 @@ doctest unit-test suite (`ctest`). | 14 | Capture sweep on hardware | **Mechanically verified on the rig (2026-08-07).** A full `--init --start` run homed both axes and completed `MOVE → settle → trigger` for 15/15 waypoints with 0 dropped frames, 0 stalls and 0 acquisition failures. `kSettleTolCounts` (600) and the per-interval timing in [CaptureScheduler.cpp](../src/core/CaptureScheduler.cpp) have **not** been tuned against observed `ST` behaviour yet, and the settle tolerance has not been checked against a sharp image (see #16). | | 15 | **Camera profiles unverified on a lit scene** | The `standard`/`night` profiles must be exported from the VimbaX Viewer (see `config/camera_profiles/rgb/README.md`) and have not been measured against real light. Confirm on the rig that `LoadSettings` succeeds, that `standard` sustains 10 fps with `frames_dropped` at 0, and that the auto-exposure lands on a sensible `ExposureTime` outdoors. The only previous rig test ran with the lens covered. | | 16 | **`settle_wait_ms` untuned** | `standard` waits 1 s and `night` 2.5 s after standstill before keeping a frame. Both are reasoned (≫ one frame period; long enough for the auto-exposure to see the new scene) but not measured. Check on a lit scene that the kept frame shows no slew blur and that its exposure has actually converged for that heading, and shorten the wait if it has. | -| 19 | **USB preconditions do not survive a reboot** | `usbcore.usbfs_memory_mb` reverts to 16 (needs 1000) and USB3 LPM re-enables on the camera's port. **Both were wrong on the LattePanda when tested on 2026-08-07**, and frame delivery stalls without them regardless of application code. Needs the udev rule + kernel cmdline persistence described under *Camera acquisition* below. | +| 19 | **USB preconditions do not survive a reboot** | `usbcore.usbfs_memory_mb` reverts to 16 (needs 1000) and USB3 LPM re-enables on the camera's port. **Both were wrong on the LattePanda when tested on 2026-08-07**, and frame delivery stalls without them regardless of application code. **Solved on tower 121 by the setup kit** (`hardware/lattepanda-iota/preconditions/`): a systemd-tmpfiles drop-in for usbfs and two udev rules, all installed by `install.sh --preconditions`. Verified 2026-09-23 — `usbfs_memory_mb` reads 1000 after **6 days of uptime**, so it survived the boot, and both rules are in `/etc/udev/rules.d/`. Note it is **tmpfiles, not the kernel cmdline** the original entry proposed. **Still open on the Delta fleet**, which has not had the kit applied. | ## Camera acquisition (USB3) — root cause + approach @@ -100,6 +100,18 @@ scripts for this are worth keeping; note that wrapping them in `timeout` SIGTERM and real motor captured 15/15 waypoints, one software-triggered frame each, 0 dropped and 0 stalls. What this does **not** cover is image *content* — the lens was covered, so exposure/blur behaviour on a real scene remains open (#15–#17). +- **Log rotation verified on the rig (2026-09-23); pruning is not.** With + `[Logging] file_max_mb = 1` on tower 121, a segment closed at 1048513 bytes against + the 1048576 cap — rotating *before* the write that would cross it, on a whole line — + and the next segment re-emitted the header. Retention (`file_keep`) needs a fourth + segment to observe a deletion, roughly three hours at that cap, and was not run. + `tests/test_filelogsink.cpp` covers it directly. +- **The positive-travel guard has never fired in anger.** `checkTravelFitsPositive()` + catches a `center_count` smaller than half the homed travel, which puts the negative + end below zero. It was tested against real numbers and shipped *after* 121's centre + was raised to 1000000, so no tower has ever tripped it. Whether the TMC5160 actually + misbehaves below zero is still not established — see the note in + `include/fgc/HardwareChecks.h`. - **Makefile parity** is moot: the Makefile was removed in favour of CMake, and the full `WITH_VIMBA=ON WITH_MQTT=ON` CMake build now runs on the device. - **Demo mode** copies `bin/x64/Release/test_smoke.jxl`, resolved relative to the working directory. Run from a diff --git a/docs/roadmap.md b/docs/roadmap.md index a0fb942..88904b1 100644 --- a/docs/roadmap.md +++ b/docs/roadmap.md @@ -18,6 +18,15 @@ Keep entries dated; move shipped items into the reference docs. (peak/mean CS, SG, PWM during a move) so the friction/balance/homing-time metrics come off the firmware clock instead of host `ST` sampling; plus a `PING`/`PONG` link-health command for `test system link`. + - ⚠️ **This collides with AVR flash headroom.** Three new commands are the + kind of growth the ATmega32U4 no longer has room for — it sits at **79.8 % + of its 28 KB** (5828 B free, measured 2026-09-23), up from 19254 B at the + phase 2 gate. The RP2040 is a non-issue at 0.6 % of 8 MB. So either these + land RP2040-only behind the `platform_*.h` split, or the Delta fleet gets a + deliberate answer on flash first — `PROGMEM` for the string tables, dropping + a command, or accepting that the Delta is feature-frozen. Note §14 of the + config plan *cost* 222 B rather than freeing any, so the obvious saving has + already been spent. See [hardware-porting-plan.md](hardware-porting-plan.md). ## Planned components & integrations