STARBackend: direct X-drive head96_move_x via EEPROM X-offset (per-axis motion control)#1081
Merged
Merged
Conversation
…AP), keep EM as _OLD Mirror the iSWAP rotation-drive X handling on the 96-head: read the X-arm-carriage <-> channel-A1 X-offset from master EEPROM (_head96_request_x_offset, RA ra=kf - key pending hardware verification), cache it on Head96Information.x_offset (populated in set_up_core96_head like the iSWAP block), and rework head96_move_x to drive the X arm directly to (x - x_offset) via experimental_x_arm_move, with an A1 X-range guard and acceleration/current control. The previous EM-based move is preserved as head96_move_x_OLD for A/B verification; move_iswap_x_OLD recovers the pre-PyLabRobot#1053 relative-step iSWAP X move for the same comparison. Both _OLD methods are scaffolding to delete after validation. Chatterbox supplies a canned x_offset. format/lint/mypy clean; STAR tests pass. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Hardware A/B (target A1 500 -> OLD EM lands 500.0, NEW direct-drive landed 94.8) exposed two bugs in head96_move_x: - Sign: A1 sits left of (below) the X-arm carriage center, so deck-A1 = carriage - offset; the carriage target is therefore A1 + offset (inverse of iswap_rotation_drive_request_x). The move subtracted instead of added. - Field width: the head96 offset is ~10x the iSWAP's, so its 0.1 mm EEPROM value is 4 digits (3684); fmt "kf###" truncated it to 368 -> 36.8 mm. Widen to "kf####" -> 368.4 mm, which matches the value the hardware geometry implies. Chatterbox canned x_offset updated 0.0 -> 368.4 to match. lint/mypy clean; STAR tests pass. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
… x_offset The C0 command set lists the CoRe 96 head X-offset (AF/kf) default as 3650 (0.1 mm) = 365.0 mm. Use that for the chatterbox canned value, mirroring how the iSWAP chatterbox uses its documented 34.0 mm default; real hardware reads its per-machine calibrated value from EEPROM at setup. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The direct-drive head96_move_x is hardware-validated (lands A1 within 0.1 mm of the EM command, Y-invariant), so drop the head96_move_x_OLD A/B scaffold and its dead docstring reference. Also drop move_iswap_x_OLD, which was only an iSWAP A/B helper and does not belong in a head96 change; it is recoverable from history for the separate iSWAP work. Remove the "kf hypothesis" hedge in the getter docstring now that the EEPROM field is confirmed. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
Rework
head96_move_xfrom theEM"move all axes together" command into a real single-axis X-arm drive, so the CoRe 96 head's X move gets the same per-axis acceleration and current control thathead96_move_yandhead96_move_zalready have. The implementation mirrors the existing iSWAP rotation-drive X handling exactly: a master-EEPROM offset getter (_head96_request_x_offsetalongside_iswap_rotation_drive_request_x_offset), the offset cached on the setup info record (Head96Information.x_offsetalongsideiSWAPInformation.rotation_drive_x_offset), and a move that converts a target deck position to a carriage target via that offset (the inverse ofiswap_rotation_drive_request_x).Why
head96_move_xwas the only head96 axis without dedicated motion control: it did a position round-trip then issuedEM, which moves all axes together and exposes no speed/acceleration. A direct X-arm drive needs the X distance between the X-arm carriage center and channel A1, which the firmware stores in master EEPROM.Pattern
This is the second adopter of a low-to-high command-layering standard for STAR moves, after
move_iswap_x: a low-level primitive that exposes motion control (X0:XPviaexperimental_x_arm_move), a cached EEPROM calibration offset on the*Informationrecord, and a deck-frame public method that transforms via the offset and threads the motion params through. It replaces the anti-pattern of going straight to a monolithicEMmacro that bundles all axes and exposes nothing. Candidates to migrate next: iSWAP Y/Z, head96 Y/Z, CoRe 384 head, nano pipettor.What this enables
Per-move acceleration, impossible with
EM's single fixed ramp:Changes
_head96_request_x_offset(): reads the carriage-center-to-A1 X offset from master EEPROM (parameterkf, set viaC0:AF, read viaC0:RA), in mm.Head96Information.x_offset, populated inset_up_core96_head(mirrorsiSWAPInformation.rotation_drive_x_offset).head96_move_xto drive the X arm tox + x_offsetviaX0:XP(channel A1 sits left of the carriage center, so the carriage target isA1 + offset), guarded by the 96-head A1 X range, exposingacceleration_level/current_protection_limiter.Behavior change
head96_move_xnow issues a single-axis X move instead of theEMall-axes coordinate move. Likehead96_move_y/head96_move_zit moves only its own axis and assumes a safe Z (noEMlower-then-move). The signature stays backward compatible:xremains positional, the new parameters default.Compatibility
All firmware commands used (
C0:RA,C0:AF/kf,X0:XP) are long-standing STAR commands, stable across firmware versions; the change was validated on a head96 running 2021 firmware.current_protection_limiteris capped at 7, which is valid on every firmware track.Validation
Hardware A/B on a STAR against the previous
EMmove: for target A1 X = 500, the direct drive lands A1 at 499.90 mm vs 500.00 (EM), a 0.1 mm delta (one firmware increment), and is Y-invariant (identical front and back of the deck) whereEMdrifted ~0.2 mm with Y. The EEPROM read returned 368.2 mm on that machine. lint, mypy, and the STAR test suite pass.