Arm-wait lid cancel expectations: reset banner and no alarm (harness, laser.arm-wait-lid, LIGHTBURN.md)

This commit is contained in:
ScottW514
2026-08-16 19:31:42 -04:00
parent c4ea96127c
commit 6b35f9c534
3 changed files with 16 additions and 13 deletions
+2 -1
View File
@@ -35,7 +35,8 @@ The laser fires only inside an operator-armed window:
cancels the wait at any time. Opening the lid (or a Pro's interlock cancels the wait at any time. Opening the lid (or a Pro's interlock
loop) while the button is lit cancels the job the same way — the loop) while the button is lit cancels the job the same way — the
message names the reason, the latch relocks, and a press with the lid message names the reason, the latch relocks, and a press with the lid
open never arms; close the lid, clear the alarm, and start again. open never arms; the job ends for LightBurn (a clean cancel, no alarm to
clear); close the lid and start again.
- One press covers one job — power changes and M5/M3 toggles do not - One press covers one job — power changes and M5/M3 toggles do not
re-prompt. The window relocks when the job ends (program end re-prompt. The window relocks when the job ends (program end
`M2`/`M30`), when the sender connection changes, or after `M2`/`M30`), when the sender connection changes, or after
+8 -8
View File
@@ -436,9 +436,9 @@ def kill_mid_fire(ctx):
"When the white button lights, do NOT press it: open the lid instead."], "When the white button lights, do NOT press it: open the lid instead."],
description="Start a laser job so the controller unlocks the latch and lights the button, " description="Start a laser job so the controller unlocks the latch and lights the button, "
"then open the lid while it waits. The wait must abort with the lid named as the " "then open the lid while it waits. The wait must abort with the lid named as the "
"reason and alarm 3, the armed window closed (armed -> false), the kernel latch " "reason, cancelled with a soft reset (no alarm - nothing to unlock), the armed "
"back to locked, and no emission; closing the lid and clearing the alarm returns " "window closed (armed -> false), the kernel latch back to locked, and no emission; "
"the controller to Idle. No press is given, so nothing can fire.") "the controller ends Idle. No press is given, so nothing can fire.")
def arm_wait_lid(ctx): def arm_wait_lid(ctx):
ev = ctx.evidence ev = ctx.evidence
with ctx.grbl() as g, LiveJob(ctx, g): with ctx.grbl() as g, LiveJob(ctx, g):
@@ -463,14 +463,15 @@ def arm_wait_lid(ctx):
while time.time() - t1 < 15: while time.time() - t1 < 15:
ctx.checkpoint() ctx.checkpoint()
text += g.drain() text += g.drain()
if "job cancelled" in text and "ALARM:3" in text: if "job cancelled" in text and "help]" in text:
break break
time.sleep(0.1) time.sleep(0.1)
ev["messages"] = [ln for ln in text.splitlines() if ln.startswith("[MSG:") or ln.startswith("ALARM")] ev["messages"] = [ln for ln in text.splitlines() if ln.startswith("[MSG:") or ln.startswith("ALARM")]
ctx.log("controller: %s", ev["messages"]) ctx.log("controller: %s", ev["messages"])
ctx.check("lid opened during arm - job cancelled" in text, ctx.check("lid opened during arm - job cancelled" in text,
"the lid open was not reported as cancelling the arm") "the lid open was not reported as cancelling the arm")
ctx.check("ALARM:3" in text, "no alarm 3 after the lid-open cancel") ctx.check("help]" in text, "no reset banner after the lid-open cancel (it must be a clean cancel)")
ctx.check("ALARM" not in text, "an alarm was raised on the lid-open cancel")
# Armed window closed and the kernel latch locked. # Armed window closed and the kernel latch locked.
t2 = time.time() t2 = time.time()
s = None s = None
@@ -489,11 +490,10 @@ def arm_wait_lid(ctx):
ctx.check(not ev["emission"], "emission_samples nonzero (%s) - nothing may have fired", ev["emission"]) ctx.check(not ev["emission"], "emission_samples nonzero (%s) - nothing may have fired", ev["emission"])
ctx.instruct("Close the lid, then click Done.") ctx.instruct("Close the lid, then click Done.")
ctx.sleep(1) ctx.sleep(1)
ctx.log("unlock: %s", g.command("$X"))
st = g.status_report()["state"] st = g.status_report()["state"]
ev["state_after"] = st ev["state_after"] = st
ctx.check(st.startswith("Idle"), "controller is %s after $X, expected Idle", st) ctx.check(st.startswith("Idle"), "controller is %s after the cancel, expected Idle (no unlock needed)", st)
ctx.log("PASS: lid open during the arm wait cancelled the job (alarm 3), armed=false, latch locked") ctx.log("PASS: lid open during the arm wait cancelled the job (clean reset, no alarm), armed=false, latch locked")
@test("laser.lid-cancel-mid-fire", title="Lid open mid-burn: beam off in hardware, job cancelled, head home", @test("laser.lid-cancel-mid-fire", title="Lid open mid-burn: beam off in hardware, job cancelled, head home",
+6 -4
View File
@@ -18,8 +18,8 @@ reported messages:
armed message appears armed message appears
6. with a switch source present (GF_SWITCH_FILE), the arm blocks on the 6. with a switch source present (GF_SWITCH_FILE), the arm blocks on the
button: a press with the lid closed arms, and the lid or the button: a press with the lid closed arms, and the lid or the
interlock loop opening during the wait cancels the job (alarm, interlock loop opening during the wait cancels the job (a clean
latch relocked, never armed) soft reset, no alarm; latch relocked, never armed)
7. outside the arm wait the button is the pause/resume toggle: a press 7. outside the arm wait the button is the pause/resume toggle: a press
while running feed-holds, a press while held resumes; the arming while running feed-holds, a press while held resumes; the arming
press itself is not a pause press press itself is not a pause press
@@ -433,8 +433,10 @@ def test_lid_open_in_wait():
s.set_switches(SW_LID_OPEN) s.set_switches(SW_LID_OPEN)
if not wait_for(s.log, LID_CANCEL, 5, s.sock): if not wait_for(s.log, LID_CANCEL, 5, s.sock):
fail("[lid-in-wait] lid open during the wait was not reported as a cancel") fail("[lid-in-wait] lid open during the wait was not reported as a cancel")
if not wait_for(s.log, "ALARM:3", 5, s.sock): if not wait_for(s.log, "for help]", 5, s.sock):
fail("[lid-in-wait] no alarm after the lid-open cancel") fail("[lid-in-wait] no reset banner after the lid-open cancel (a clean cancel, not an alarm)")
if "ALARM" in "".join(s.log):
fail("[lid-in-wait] an alarm was raised on the lid-open cancel")
# Press with the lid still open: nothing may arm. # Press with the lid still open: nothing may arm.
s.set_switches(1 << 2) s.set_switches(1 << 2)
read_avail(s.sock, s.log, 1.0) read_avail(s.sock, s.log, 1.0)