Skip to content

feat(azenta): add FluidX IntelliXcap 96 decapper driver#1175

Open
rickwierenga wants to merge 4 commits into
v1b1from
feat/fluidx-intellixcap96
Open

feat(azenta): add FluidX IntelliXcap 96 decapper driver#1175
rickwierenga wants to merge 4 commits into
v1b1from
feat/fluidx-intellixcap96

Conversation

@rickwierenga

Copy link
Copy Markdown
Member

What

Adds FluidXIntelliXcap96, a driver for the FluidX (Azenta) IntelliXcap 96 automated screw-cap decapper.

It lives at pylabrobot/azenta/fluidx/intellixcap96.py as a single plain class, alongside the existing a4s and xpeel Azenta devices.

Device

A benchtop instrument that unscrews, holds, and rescrews all 96 caps of a screw-cap tube rack in a single stroke. A plate mover loads the rack onto its one nest.

Protocol

  • Serial 9600 8N1, no handshake, ETX (0x03) line terminator (not CR/LF)
  • Single-character commands, each written followed by ETX; the reply is read back up to the next ETX:
    a status · h decap · i recap · b waste · f/g tray open/close · Z home · z reset · j/k standby/ready
  • Long-running motions are acknowledged with a single 0x06 byte, then the driver polls a until the status reports ...DONE / StatusOK (success) or ...ERROR / StatusError / Error (fault)
  • Each command resets the input buffer before writing and paces afterward

Public API

setup / stop, decap, recap, waste, open_tray, close_tray, home, reset, standby, ready, request_status, send_command.

Testing

  • ruff check and ruff format clean
  • mypy clean on the new module
  • 12 unit tests exercising the wire protocol (command bytes, ACK handling, status polling, and each error path) against a stubbed serial

Not yet tested against hardwaresetup() logs a warning asking for a PR to remove it once verified on a real device.

rickwierenga and others added 4 commits July 20, 2026 18:33
FluidXIntelliXcap96 drives the FluidX IntelliXcap 96 automated screw-cap
decapper over serial. It decaps, holds, and recaps a 96-format rack of
screw-cap tubes, drops held caps to waste, opens and closes the tray, homes,
resets, and enters/leaves standby.

Serial 9600 8N1, no handshake, ETX (0x03) line terminator; motions are
acknowledged with a single 0x06 byte and progress is tracked by polling the
status command. Single plain class under pylabrobot/azenta/fluidx/, with docs
and wire-protocol tests against a stubbed serial.

Not hardware-tested: setup() emits a not-verified warning.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Rework the IntelliXcap 96 I/O to the protocol confirmed on hardware: replies are
STX/ETX framed, and a command is answered with an ACK frame, a "<cmd>OK" echo
frame, and a result frame. A motion completes when the status word returns from
StatusBUSY to StatusOK; a refused or no-op command answers CommandIgnore.

setup() now reads the real status and, when the device reports StatusBUSY at
connect, raises with an e-stop / safety-guard / interlock hint (the instrument
locks out and ignores commands until it is cleared). Status words are matched
case-insensitively (the firmware reports StatusSLEEP, StatusBUSY).

Verified against hardware: connection, status, tray open/close, home, and
standby/ready. Decap, recap, and waste are not yet verified; setup() warns.

Add a hello-world tutorial notebook under docs/user_guide/azenta/fluidx.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Bring back the ERROR_MESSAGES table (the fault text read out of the instrument
firmware) that was dropped during the framing rework, and raise every fault
through it again via _fault() so exceptions carry the device's own wording
instead of paraphrases.

Uncomment decap/recap/waste in the tutorial and split each operation into its
own cell.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
reset() reads status first and raises CannotReset (the firmware's own wording)
when the device is already in an error state, matching the vendor sequence,
before issuing the reset and re-checking for ResetNotSuccesful.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant