Skip to content

v1 CLARIOstar: prime and backflush the injector pumps - #1632

Draft
maraxen wants to merge 3 commits into
PyLabRobot:mainfrom
maraxen:clariostar-pumps
Draft

maraxen wants to merge 3 commits into
PyLabRobot:mainfrom
maraxen:clariostar-pumps

Conversation

@maraxen

@maraxen maraxen commented Nov 13, 2026

Copy link
Copy Markdown
Contributor

Stacked on #1606, which adds an original CLARIOstar with firmware 1.20 and two XCalibur pumps. Until #1606 merges, this PR also shows its two commits; the new code is the last commit, 22fd467. I will rebase onto main once #1606 merges. This PR adds
CLARIOstar.pumps.prime() and backflush(); CLARIOstar.pumps exists when the reader reports a pump.

Command encoding

The command is family 0x02 with payload 02 <pump> <flow rate code> <volume / 500 uL>. The pump byte is the pump
number, plus 0x10 for a backflush.

flow rates (uL/s) verified volumes (uL) verified
prime 100 (0c), 300 (04), 430 (01) 500, 2000, 4500
backflush 100, 430 500, 1000

The other settings in range (500-4500 uL in steps of 500, and 300 uL/s for a backflush) follow the same rule, and the
driver sends them with a warning. The tests compare seven of these frames, checksum included, with what prime and
backflush write.

Runs on the reader

We ran backflushes of pumps 1 and 2 and primes of pump 1 on this reader, all 500 uL at 100 uL/s with water. Each
command's reply or the next status read busy. During backflushes, status byte 6 read 02, the pump family. The
reader read idle again after 13.5 to 31 s.

When a call returns

The driver sends a pump command once. If the reply is malformed, the driver discards it and reads busy and idle from
status polls, as initialize does for INIT. It then waits for busy and then idle, with a 5 s start window, because a
command's reply can read idle while the reader starts it. After a timeout or a cancelled call the reader keeps
pumping; the driver sends no stop. The driver raises RuntimeError for a pump command during a measurement, and for
a measurement during a pump command, using the existing one-measurement guard.

Reagent door

STATUS byte 3 bit 6 is CLARIOstarStatus.reagent_door_open. On this reader, while idle, it read set in all 60 polls
with the door open and clear in all 60 with the door latched shut, over three captures of each. A door that is closed
but not latched appears to read open.

  • On firmware 1.20, prime raises RuntimeError without sending when the bit reads the door shut. On other firmware
    prime does not check the bit and sends with a warning.
  • With the door shut, the reader answered a prime with quit codes 243/12 in the next status reply (seen once).
    prime and backflush raise PumpAbortedError with the codes of any new warning in a reply.
    describe_quit_codes describes 243/12 as the reagent door abort and keeps its existing description for 243 alone.
  • If the bit clears during a prime and no warning is read, the driver logs it, waits until the reader reads idle and
    then raises PumpAbortedError, so the caller does not see the prime end while the reader may still be pumping.
    When the door was closed during a prime (once), one status reply carried the bit clear, busy clear and 243/12. We
    do not know how much a prime delivers when it ends early.
  • backflush does not check the door.

Simulation

Given this reader's recording, the simulated driver builds CLARIOstarSimulationPumps. Its prime and backflush
check the settings and return at once, and the simulated status reads the door open.

Not covered

Pump 3, whose byte is not known; injection during a read, which is the next PR; primes of pump 2, and settings other
than 500 uL at 100 uL/s, on the reader.

Tests

pumps_tests.py checks exact command frames against synthetic status replies, and simulator_tests.py has the
simulated pumps and the device property. The 465 BMG tests pass.

Questions

  1. Could you read bit 6 of status byte 3 on your reader with its reagent door open and then shut, if it has a door
    even without pumps? If the bit follows the door there too, the door check can cover more than firmware 1.20.
  2. The FTDI read path can drop a warning that the reader sends between exchanges, because _read_frame keeps bytes
    past a frame only until the next exchange. We have only seen warnings inside a status reply, and for a prime the
    driver also watches the door bit. Is that acceptable, or would you rather ftdi_interface.py kept the bytes past a
    frame for the next read?

🤖 Generated with Claude Code

https://claude.ai/code/session_011KebPWoZ9NbAsYfKYTkZQ2

maraxen and others added 3 commits November 10, 2026 12:15
…nal CLARIOstar

An original CLARIOstar (main board revision 1) on firmware 1.20, compiled
2017-04-27, lays out its INIT reply as the Plus 1.35 does but for a longer
pumps block (0F: 31 bytes, against 3 on the Plus, which has no pumps), and its
stored parameters as 1.35's. Read with the 1.x decoders unchanged, every block
and parameter decodes; the fields match the reader as known to its users.

DECODED_FIRMWARE now starts at 1.200; the undecoded-firmware test moves its
example from 1.29 to 1.19.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011KebPY9ZD8HmWuTM4tQpVz
…lies decode to its recording

The payloads of its INIT, stored parameters and firmware info replies, with
the serial number zeroed at SERIAL_NUMBER_ADDRESSES and the pumps' part
numbers in block 0F's text zeroed (neither is decoded).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011KebPY9ZD8HmWuTM4tQpVz
`CLARIOstar.pumps` (`driver.pumps`) exists when the reader reports a pump. It
has `prime` and `backflush` for pumps 1 and 2, 500-4500 uL in steps of 500, at
100, 300 or 430 uL/s. The driver sends a command once and waits until the
reader reads idle. Settings outside those verified on firmware 1.20 are sent
with a warning.

`CLARIOstarStatus.reagent_door_open` reads STATUS byte 3 bit 6. On firmware
1.20, `prime` raises `RuntimeError` without sending when that bit reads the
door shut. The driver raises `PumpAbortedError` when the reader reports a pump
command aborted, and when the door closes during a prime, once the reader reads
idle. `describe_quit_codes` describes quit codes 243/12 as the reagent door
abort. The driver does not start a pump command during a measurement, or a
measurement during a pump command. A simulated reader with pumps checks the
settings and returns at once.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011KebPWoZ9NbAsYfKYTkZQ2

This branch has not been deployed

No deployments
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