Record tower 111 has no hardware.ini; BOOTSEL and USB preconditions are solved
This commit is contained in:
parent
b6308c1eda
commit
7a7e7ab0a5
|
|
@ -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
|
existing fleet that drops yaw 50000 → 30000, a real behaviour change that wants a deliberate rig check
|
||||||
rather than a silent correction.
|
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
|
## 14. Firmware changes, collected
|
||||||
|
|
||||||
- **Per board** → `platform_leonardo.h` / `platform_iota.h`: pin map plus the three AVR-isms
|
- **Per board** → `platform_leonardo.h` / `platform_iota.h`: pin map plus the three AVR-isms
|
||||||
|
|
|
||||||
|
|
@ -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
|
> 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
|
> 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
|
> a mast. **That one is still true.**
|
||||||
> honours the 1200-baud reset but returns to the application, so a tower cannot
|
|
||||||
> currently be re-flashed over the network at all.
|
|
||||||
>
|
>
|
||||||
> **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
|
> `rp2040.rebootToBootloader()` — implemented and proven on tower 121 the same
|
||||||
> day. The full loop now runs with nobody at the board:
|
> day. The full loop now runs with nobody at the board:
|
||||||
>
|
>
|
||||||
|
|
@ -295,7 +297,7 @@ commit `aab1925`.
|
||||||
|
|
||||||
| Phase | Item | State |
|
| 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 | **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 | `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** |
|
| 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 | 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 |
|
| 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 |
|
| 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
|
> **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
|
> *remotely on a tower* by `firmware/deploy.sh --compile-only`. Locally, the Arduino-free sources
|
||||||
|
|
|
||||||
|
|
@ -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). |
|
| 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. |
|
| 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. |
|
| 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
|
## 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
|
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
|
this does **not** cover is image *content* — the lens was covered, so exposure/blur behaviour on a real
|
||||||
scene remains open (#15–#17).
|
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
|
- **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.
|
`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
|
- **Demo mode** copies `bin/x64/Release/test_smoke.jxl`, resolved relative to the working directory. Run from a
|
||||||
|
|
|
||||||
|
|
@ -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
|
(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
|
metrics come off the firmware clock instead of host `ST` sampling; plus a
|
||||||
`PING`/`PONG` link-health command for `test system link`.
|
`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
|
## Planned components & integrations
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue