The critical tier proven on a rising loop; the board temperatures watched

forgectrl pin 76115fd: the chassis LM75 and the supply sensor ride /status
as temps (degrees and a raw count), the engine ranges them over every run
session into one run-end line, and a critical fault that clears with its
session yields the reason to the standing hold.

Bench: critical_tier_drill.py (a bench tool now, registered as
critical-tier) sets the ceiling, the resume gate and the critical line a
few tenths above the live upstream reading and lets the engine's own
flow-check heater warm the loop through them inside one M8 session;
temp_calibrate.py gains supply-watch, supply-point and supply-fit for the
supply sensor against a thermometer on its heatsink, the fit shown beside
UAPI.md's unverified guess.

Catalog: cooling.gate-off checks the /status temps fields and the run-end
board-temperature line (the unit fake mirrors both, one new failure
case); cooling.critical-tier checks the reason after a faulted session.

Docs: CAMPAIGN-LOG entries for cooling.critical-tier on dev image
20260822154257 and the warm-loop drill (OVERTEMP at 10 s, CRITICAL at
14 s, the fault ending with the session); BRINGUP item 19, the facts bank
(board temperatures at idle), COOLING section 9, the bench README.
This commit is contained in:
ScottW514
2026-08-22 12:56:40 -04:00
parent f51140e528
commit 9fae47cf14
10 changed files with 372 additions and 9 deletions
+18 -3
View File
@@ -623,6 +623,11 @@ until `releases/v<version>/acceptance.json` is committed.
## Hardware facts bank (measured)
- **Board temperatures at idle** (room ~22 C, machine on for hours): the
chassis LM75 reads **29.0 C**, `pic/pwr_temp` reads **589 raw** (the
unverified guess `raw * 0.08715 - 21` would make that 30.3 C; a thermometer
on the supply heatsink decides). Ranged per job by the engine from here
on.
- **Fan speeds at the cut profile** (exhaust duty 65535, intake 43278, air
assist 1023; sampled at 1 Hz over 120 s from idle, the exhaust duct's
inline booster fan off): exhaust **11640 rpm** steady (spread 11444 to
@@ -1375,9 +1380,19 @@ Open items only. Anything closed is in `CAMPAIGN-LOG.md`.
cross-check) is the fail tier above the ceiling's pause: at or over it
in a run session the verdict is `CRITICAL` (fire blocked, hold, no
resume this job), the fault ends with the session, no header touches
it; `cooling.critical-tier` in the catalog (45), bench run owed on the
next image, plus the heater-driven warm-loop drill to the critical
line. The watch-only board temperatures follow.
it; `cooling.critical-tier` in the catalog (45), PASS on dev image
`20260822154257`, and the warm-loop drill (`critical_tier_drill.py`)
PASS the same day on a genuinely rising loop: `OVERTEMP` at the
ceiling, `CRITICAL` four seconds later at the line, the fault ending
with the session (CAMPAIGN-LOG). **The board temperatures are watched:**
the chassis LM75 (degrees) and the supply sensor (raw count, its
conversion still unverified) ride `/status` as `temps`, show on the
Status tab, and are ranged over every run session into one run-end
log line; no gate behind either until the record says where one
belongs, and the supply's conversion waits on thermometer points at
the heatsink during a long cut (`temp_calibrate.py supply-point`,
three points, then `supply-fit`). Bench run of the status fields and
the log line owed on the next image.
Nothing here can put energy where it was not commanded: the hardware chain
is the emission boundary and no header field touches it, and forgectrl runs
+34
View File
@@ -3368,6 +3368,40 @@ and flashed the same day (dev image `20260822145201`, forgectrl d51dbdb):
`cooling.fan-gate-trips` PASS in 60 s, the engine reading `OK`, no hold,
fire allowed in the smoke-clear phase right after the tripped session.
## 2026-08-22: the coolant critical tier, on an image and on a rising loop
Dev image `20260822154257` (forgectrl a1875a8 pinned by forgefirm f51140e):
`cooling.critical-tier` PASS in 23 s. As recorded: the settings API refused
a critical line equal to the ceiling (`400 cool_temp_critical_c must be
above cool_temp_max`) and changed nothing; with the ceiling at 6 C, the
resume gate at 5 C and the critical line at 7 C under 24.3 C coolant the
session read `CRITICAL` (`fire_ok false`, `hold true`, no `resume_ok`,
reason `CRITICAL: coolant 24.3 C at or over the 7 C critical line - hold,
no resume this job`); after the session the ceiling alone held
(`OVERTEMP`); with the critical line at its top of 70 the gate was off
(`gates_off` naming `coolant_critical`, the run-start log line) and the
ceiling alone paused; restored, `OK` with nothing off.
The physical drill, `critical_tier_drill.py`, the same day. The loop heater
reaches the high twenties at most, so the lines were set a few tenths
above the live upstream reading (24.57 C: ceiling 25.0, resume 24.8,
critical 25.3) and the engine's own flow-check heater (100 percent, 300 s
windows, rechecks every 30 s, the suspect threshold at its top) warmed the
loop through them inside one `M8` session. Transitions, as sampled once a
second: `OK` at 24.1 C; `OVERTEMP` at 10 s with the upstream at 25.05 C
(`coolant 25.0 C over 25 C limit - hold until 25 C`); `CRITICAL` at 14 s
at 26.24 C (`fire_ok false`, `hold true`, relayed on the Grbl port as a
`[MSG:Warning: CRITICAL: ...]`). `M9` ended the fault and the ceiling's
`OVERTEMP` stood in the smoke-clear phase (upstream 27.7 C, downstream
49.7 C from the heater, which the session end switched off). Settings
restored and re-read in a short session: `OK`, limits back to 33 / 31 / 38.
One find, cosmetic: after the session the reason text still read the
critical line's message under the ceiling's verdict, because the ceiling
names itself only on its rising edge and the critical fault had overwritten
it. The engine now re-publishes the standing hold's reason when a critical
fault clears (no new log line), and `cooling.critical-tier` checks it.
## Superseded status notes
### Shared machine services — remaining polish, as listed 2026-08-13
+6
View File
@@ -435,6 +435,12 @@ Stated plainly so nobody counts on them:
cannot be detected (the output has no readback), so this will become a user
setting plus a simple hysteresis around the factory's setpoints.
- **A fire watch that acts** (§7).
- **Chassis and supply ceilings.** Both temperatures are measured and not
gated: the chassis LM75 in degrees and the supply sensor as a raw count,
in `/status` as `temps`, and ranged over every job in one log line
(`temps this job: ...`). A ceiling for each comes from that record once
there is enough of it, and the supply's conversion from a thermometer on
its heatsink (`temp_calibrate.py supply-point`).
- **Fan floors measured on more than one machine.** The shipped floors are
a fraction of one bench machine's run-duty speeds; a machine whose fans
read differently sets its own (§8), and a floor of zero turns that gate