mirror of
https://github.com/openglow-org/forgefirm.git
synced 2026-09-27 16:51:12 -07:00
setup.check-envelope: the head goes back to the home, or the run fails
The test's cleanup jogged the head back to the camera home through the panel's relative jog, the increment taken from the port's position. The core refused it every time (error:15, "the move would leave the work envelope"), eight tries each run, and the test logged "the head is not back at the home" and passed. The takeover that puts the setup record back restarts the controller, which zeroes the kernel counters where the head stands, so the baseline read (0, 0, 0) and called the machine clean. On the bench reference the head was left 10 mm from the home in X and in Y by every run of 2026-09-23 that got that far (three PASSes and one FAIL, images 20260922225653, 20260923084705, 20260923220034). Why the jog was refused: the port reports the step counters, while the core adds a relative jog to its own parser position. The bed check's last jogs, sized from the counters, leave the two apart by up to half a step. The arithmetic reproduces every logged value: the parser held X 60.1 after the answers, the port read 60.099, the check jogged -50.099 toward X 10, so the parser took 10.001, which the step grid (213.33 steps/mm) turned into 2134 steps, read back as 10.003. The test's return of -10.003 then targeted X -0.002, and a camera home's envelope begins at exactly 0, so the core refused the whole jog. No product path returns the head by a relative jog sized from the counters; the panel's Jog card sends fixed steps. Now the head goes back in one jog from a Grbl client to the home in machine coordinates ($J=G90 G53, 0.5 um inside the envelope's start, far under half a step), and the run fails unless the port reads the head on the home's step. That reading is taken before the restart, because nothing after it can see a head left out. Bench reference, image 20260923220034 with the suite file bind-mounted: a negative control that aims the return 1 mm off the home FAILs with "the head is not back at the home (0.0, 0.0, 3.08): [0.998, 0.998, 3.08]" while the baseline still says clean; the fix PASSes with "$J=G90 G53 X0.0005 Y0.0005 F1200 -> ok" and the head at [0.0, 0.0, 3.08]. forgetest's unit tests 454 OK; the coverage lint passes with --enforce on the image's manifest.
This commit is contained in:
@@ -29,7 +29,10 @@ X_STEPS = ["X+10"] * 6 + ["X+1", "X+0.1", "X-1"]
|
|||||||
Y_STEPS = ["Y+10"] * 6 + ["Y+1", "Y+0.1"]
|
Y_STEPS = ["Y+10"] * 6 + ["Y+1", "Y+0.1"]
|
||||||
X_OUT, Y_OUT = 60.1, 61.1
|
X_OUT, Y_OUT = 60.1, 61.1
|
||||||
MARGIN_MM = 1.0
|
MARGIN_MM = 1.0
|
||||||
KEYS = ("envelope_x_mm", "envelope_y_mm", "homing_mode")
|
# The head is back on the home's step: half a step (213.3 steps/mm) and
|
||||||
|
# the port's three decimals.
|
||||||
|
HOME_TOL_MM = 0.003
|
||||||
|
KEYS =("envelope_x_mm", "envelope_y_mm", "homing_mode")
|
||||||
CLOSED = "closed the check's envelope"
|
CLOSED = "closed the check's envelope"
|
||||||
CLOSED_MSG = "Bed check envelope closed: a sender line"
|
CLOSED_MSG = "Bed check envelope closed: a sender line"
|
||||||
|
|
||||||
@@ -107,20 +110,31 @@ def _put_back(ctx, fc, found):
|
|||||||
|
|
||||||
|
|
||||||
def _back_home(ctx, fc, home):
|
def _back_home(ctx, fc, home):
|
||||||
"""The head back where the home put it, in the port's bounded steps, so
|
"""The head back where the home put it: one jog to the home in machine
|
||||||
the run ends where it began."""
|
coordinates, from a Grbl client. A relative jog aimed at the home from
|
||||||
for _ in range(8):
|
the port's position can be refused whole: the port reports the step
|
||||||
at = _port(fc).get("mpos") or [home[0], home[1]]
|
counters, the core adds a relative jog to its own position, which the
|
||||||
dx, dy = home[0] - at[0], home[1] - at[1]
|
check's jogs leave up to half a step off the counters, and the envelope
|
||||||
if abs(dx) < 0.005 and abs(dy) < 0.005:
|
begins at the home, so the target can land microns behind it (error:15).
|
||||||
return
|
Where the head stands after, from the port; None when unread."""
|
||||||
st, body = _jog(fc, max(-100.0, min(100.0, dx)), max(-100.0, min(100.0, dy)))
|
# 0.5 um inside an envelope that begins at the home (a camera home
|
||||||
if st != 200:
|
# behind the origin), far under half a step: the head lands on the
|
||||||
ctx.log("the jog back to the home -> %s %s", st, body)
|
# home's own step.
|
||||||
ctx.wait_for(lambda: fc.status().get("state") == "idle", 10, poll=0.5)
|
line = "$J=G90 G53 X%.4f Y%.4f F1200" % (home[0] + 0.0005, home[1] + 0.0005)
|
||||||
continue
|
try:
|
||||||
_port_idle(ctx, fc)
|
with ctx.grbl() as g:
|
||||||
ctx.log("the head is not back at the home: %s", _port(fc).get("mpos"))
|
reply = g.command(line, timeout=10)
|
||||||
|
ctx.log("the jog back to the home: %s -> %s", line, " | ".join(reply))
|
||||||
|
if reply[-1:] == ["ok"]:
|
||||||
|
t0 = time.time()
|
||||||
|
ctx.wait_for(lambda: time.time() - t0 > 0.5 and g.status_report()["state"].startswith("Idle"),
|
||||||
|
60, poll=0.2)
|
||||||
|
except (OSError, ValueError) as e:
|
||||||
|
ctx.log("the jog back to the home: %s", e)
|
||||||
|
ctx.wait_for(lambda: _port(fc).get("sender") is False and _port(fc).get("state") == "Idle", 20, poll=0.5)
|
||||||
|
at = _port(fc).get("mpos")
|
||||||
|
ctx.log("the head after the jog back: %s (the home %s)", at, home)
|
||||||
|
return at
|
||||||
|
|
||||||
|
|
||||||
def _port_idle(ctx, fc):
|
def _port_idle(ctx, fc):
|
||||||
@@ -171,8 +185,9 @@ def _edge(ctx, fc, ev, axis, edge):
|
|||||||
"closed the envelope and then ok; the port's state then says the envelope is closed, and the "
|
"closed the envelope and then ok; the port's state then says the envelope is closed, and the "
|
||||||
"next answer ends the check in words, with the keys as the "
|
"next answer ends the check in words, with the keys as the "
|
||||||
"first run left them and the edges still in force. The keys, the homing mode, and the setup "
|
"first run left them and the edges still in force. The keys, the homing mode, and the setup "
|
||||||
"record are put back as found, the record under a restart, and the head is jogged back to "
|
"record are put back as found, the record under a restart, and the head goes back to the "
|
||||||
"the home.")
|
"home by a Grbl client's jog in machine coordinates; the run fails unless the port reads "
|
||||||
|
"the head on the home's step before the restart.")
|
||||||
def check_envelope(ctx):
|
def check_envelope(ctx):
|
||||||
fc = ctx.forgectrl
|
fc = ctx.forgectrl
|
||||||
ev = ctx.evidence
|
ev = ctx.evidence
|
||||||
@@ -181,7 +196,7 @@ def check_envelope(ctx):
|
|||||||
raw = read_file(record_path())
|
raw = read_file(record_path())
|
||||||
found = {k: s0.get(k) or "" for k in KEYS}
|
found = {k: s0.get(k) or "" for k in KEYS}
|
||||||
ev["found"] = found
|
ev["found"] = found
|
||||||
home = None
|
home = back = None
|
||||||
try:
|
try:
|
||||||
st, body = fc.post("/settings", data={"homing_mode": "gfcloud"})
|
st, body = fc.post("/settings", data={"homing_mode": "gfcloud"})
|
||||||
ctx.check(st == 200, "homing_mode=gfcloud -> %s %s", st, body)
|
ctx.check(st == 200, "homing_mode=gfcloud -> %s %s", st, body)
|
||||||
@@ -245,7 +260,7 @@ def check_envelope(ctx):
|
|||||||
fc.post("/wiz/%s/abort" % WID)
|
fc.post("/wiz/%s/abort" % WID)
|
||||||
if home and home[0] is not None:
|
if home and home[0] is not None:
|
||||||
ctx.wait_for(lambda: not dark(fc).get("running"), 30, poll=0.5)
|
ctx.wait_for(lambda: not dark(fc).get("running"), 30, poll=0.5)
|
||||||
_back_home(ctx, fc, home)
|
back = _back_home(ctx, fc, home)
|
||||||
_put_back(ctx, fc, found)
|
_put_back(ctx, fc, found)
|
||||||
# The check records itself when it completes; the record goes back
|
# The check records itself when it completes; the record goes back
|
||||||
# as found under a restart, which also ends the envelope it set.
|
# as found under a restart, which also ends the envelope it set.
|
||||||
@@ -253,3 +268,9 @@ def check_envelope(ctx):
|
|||||||
with ctx.takeover():
|
with ctx.takeover():
|
||||||
write_file(record_path(), raw)
|
write_file(record_path(), raw)
|
||||||
ctx.log("the previous setup record is back under a restart")
|
ctx.log("the previous setup record is back under a restart")
|
||||||
|
# Judged from the reading before the restart: the restart zeroes the
|
||||||
|
# counters where the head stands, so the baseline's position check
|
||||||
|
# after it cannot see a head left out.
|
||||||
|
ev["back"] = back
|
||||||
|
ctx.check(back and all(abs(back[i] - home[i]) < HOME_TOL_MM for i in (0, 1)),
|
||||||
|
"the head is not back at the home %s: %s", home, back)
|
||||||
|
|||||||
Reference in New Issue
Block a user