diff --git a/docs/BRINGUP.md b/docs/BRINGUP.md index ed5a519..efe5e9b 100644 --- a/docs/BRINGUP.md +++ b/docs/BRINGUP.md @@ -1045,11 +1045,10 @@ Open items only. Anything closed is in `CAMPAIGN-LOG.md`. 1. **Laser commissioning leftovers.** Verify the hardware button latch persists across kernel-run gaps mid-job (if OK_2_FIRE drops between motion bursts, the - fix is a stream keepalive across armed gaps); the flow check's bands from - a loop warmer than 25 C (the bands hold from 19 to 25 C with the margin - widening warm; the warm-up in `flow_warm_validate.py` must be judged on - the mixed bulk, not the upstream sensor beside the heater, to reach 28 C - and above). + fix is a stream keepalive across armed gaps). The flow check's bands + hold from 19 to 27 C, the loop heater's ceiling in a 20 C room, with the + margin widening warm; above that only a running tube warms the loop, + and the check takes the tube's share off. 2. **Low-temperature gates and warm-up (planned).** Two keys in the Cooling card: `cool_temp_min` (hard floor, default ~5 °C, a fire gate) and `cool_temp_start` (warm-up gate, default ~16 °C) — a job starting below the diff --git a/docs/CAMPAIGN-LOG.md b/docs/CAMPAIGN-LOG.md index a626ca7..f6ff078 100644 --- a/docs/CAMPAIGN-LOG.md +++ b/docs/CAMPAIGN-LOG.md @@ -4535,6 +4535,30 @@ compensation's whole path stands on the bench: the tool measures the machine's number, Apply writes it, and both coolant readings hold within 0.1 C when the run airflow comes on. +## 2026-08-29: the flow check from a warm loop, to the heater's ceiling + +`flow_warm_validate.py` with its warm-up rewritten to judge the mixed bulk +(the heater at 50 % for three minutes, off, 45 s of circulation, the two +sensors' mean; a round that lifts the bulk under 0.15 C ends the warm-up), +run from the bench page as the `flow-warm` takeover with a 28 C target and +a 20 min budget, three checks pump on and three pump off, alternating. +The bulk plateaus at 27.2 C in this room, so the checks ran at 26.2 to +27.2 C baselines, the most the loop heater can give. + +| case | rises (C) | band | +|---|---|---| +| pump on | 11.08, 11.89, 10.98 | max 11.89 | +| pump off | 18.69, 18.42, 18.00 | min 18.00 | + +Every verdict correct; the 14.4 C limit sits 2.51 C above the warm flow +band and 3.60 C below the warm no-flow band. With the 19 to 23 C +characterization (12.75 / 16.04) and the 24 to 25 C run earlier in the +day (12.15 / 18.07), the bands hold from 19 to 27 C with the margin +widening warm. Above 27 C only a running tube warms this loop, and the +check takes the tube's share off; `cool_flow_rise` needs no warm-end +value. Records `bench-data/flow_warm_log_20260829b.txt`, +`flow_warm_results_20260829b.json`. + ## Superseded status notes ### Shared machine services — remaining polish, as listed 2026-08-13 diff --git a/scripts/bench/flow_warm_validate.py b/scripts/bench/flow_warm_validate.py index c24fd12..8f037f6 100644 --- a/scripts/bench/flow_warm_validate.py +++ b/scripts/bench/flow_warm_validate.py @@ -68,41 +68,53 @@ def pump(on): board('echo %d > /sys/glowforge/thermal/water_pump_on' % (1 if on else 0)) +WARM_ROUND_S = 180 # heater on per round, then a mix and a bulk reading +WARM_MIX_S = 45 +WARM_PLATEAU_C = 0.15 # a round that lifts the bulk less than this is the end + + def warm_to(target, log): - """Warm with the loop heater, pump circulating, fans off.""" + """Warm with the loop heater in rounds, pump circulating, fans off: + heater on for WARM_ROUND_S, heater off and WARM_MIX_S of circulation, + then the bulk read as the two sensors' mean. Judged on that mixed + bulk, never on the upstream sensor beside the heater, which reaches + any target within two minutes while the bulk has barely moved (the + 2026-08-29 run stopped at 24.5 C that way). 50 % is the practical + heater ceiling: the downstream sensor sits at the element and 100 % + drives it past 50 C in 30 s.""" pump(True) board(FANS_OFF) - # 50% is the practical ceiling: the downstream sensor sits AT the - # heater element, so 100% drives it past 50 C within 30 s while the - # bulk has barely moved. At 50% it plateaus near 41 C, leaving the - # bulk free to climb for as long as we let it. - heater(50) t0 = time.time() - # Plateau detection compares against the reading two minutes back: - # with the pump circulating, the bulk climbs only ~0.5-0.8 C/min, so - # a per-sample threshold mistakes normal warming for a plateau (it - # did exactly that on the first attempt and the whole run executed - # at ambient). - hist = [] + last_bulk = None while time.time() - t0 < WARM_MAX_S: + heater(50) + r0 = time.time() + abort = False + while time.time() - r0 < WARM_ROUND_S and time.time() - t0 < WARM_MAX_S: + d, u = temps() + if d >= ABORT_C: + log(' warm abort: downstream %.2f C' % d) + abort = True + break + time.sleep(15) + heater(0) + if abort: + break + time.sleep(WARM_MIX_S) d, u = temps() + bulk = (d + u) / 2.0 el = (time.time() - t0) / 60 - if u >= target: - log(' warm target reached: up=%.2f at %.1f min' % (u, el)) + log(' warming: %.1f min bulk %.2f (down %.2f, up %.2f)' % (el, bulk, d, u)) + if bulk >= target: + log(' warm target reached: bulk %.2f at %.1f min' % (bulk, el)) break - if d >= ABORT_C: - log(' warm abort: downstream %.2f at %.1f min' % (d, el)) + if last_bulk is not None and bulk - last_bulk < WARM_PLATEAU_C: + log(' (warming plateaued at %.2f C after %.1f min)' % (bulk, el)) break - hist.append(u) - if len(hist) % 4 == 0: - log(' warming: %.1f min down=%.2f up=%.2f' % (el, d, u)) - if len(hist) > 8 and u - hist[-9] < 0.3: - log(' (warming plateaued at %.2f C after %.1f min)' % (u, el)) - break - time.sleep(15) + last_bulk = bulk heater(0) pump(True) - time.sleep(45) # mix so the bulk is uniform before measuring + time.sleep(WARM_MIX_S) # mix so the bulk is uniform before measuring d, u = temps() log(' warmed to down=%.2f up=%.2f in %.1f min' % (d, u, (time.time() - t0) / 60)) return u