Hey, I saw the EL406 washer by biotek in the list of work-in-progress devices for PLR in Ricks presentation on Wednesday. There is only one other mention of this in one post from a year ago: Current capacity of PyLabRobotics and it's limitation - #2 by rickwierenga
But i could not find anything in the repository.
I am curious since I thought that those are supposed to be integrated with the LHC software which provides a licensed 32 bit .dll one is supposed to use. How did you/plan to get it running? I have spent quite some time hacking around that issue.
3 Likes
unfortunately we haven’t made much progress on this last year. probably early next year as we finally started using it in our lab for basic bio tests earlier this month.
as with most devices we have:
you don’t need the vendor software to send firmware commands, we can just do that ourselves. you can intercept commands being sent by a machine (How to make packet usb/ftdi captures) and then analyze them and send the commands yourself
3 Likes
I did the same and yes, you can replicate the sent commands by just copying the bits. Did you make any progress generalizing that to new protocols?
I.e., sending the bit salad making the washer do something defined like this (its for a 405TS washer)?
wash_step = EMWashStep(WashInstructions(
do_final_aspirate=True,
num_cycles=1,
final_aspirate=AspirateSettings(
travel_rate=CWFlowRate(2),
delay=1,
),
buffer_choice="B",
general_dispense=DispenseSettings(
flow_rate=4,
delay_vacuum_start=5,
positioning=Positioning(d_z=44, d_x=55),
)
))
Is the resulting code available somewhere?
1 Like
sorry, so I have not done this for the 405 or 406 washer yet. I am hoping to do it early next year, unless …
very cool!! Want to contribute it as a backend to pylabrobot?
So there is nothing public, yet?
I can use most (I might have missed some) features of the 405 Washer defined by dataclasses as described above. The following code works:
python function
def test_sila_call():
# start a SiLA server
server = WasherServer(simulation=True, com_port="/dev/ttyUSB1")
server.start_insecure("127.0.0.1", 50055)
# define some steps. The numbers are for demonstration and have no real biochemical background.
prime_step = PrimeStep(PrimeInstructions(
volume=200,
flow_rate=11,
))
wait_step = WaitStep(wait_time=3)
wash_step = EMWashStep(WashInstructions(
do_final_aspirate=True,
num_cycles=1,
final_aspirate=AspirateSettings(
travel_rate=CWFlowRate(2),
delay=1,
),
buffer_choice="B",
general_dispense=DispenseSettings(
flow_rate=4,
delay_vacuum_start=5,
positioning=Positioning(d_z=44, d_x=55),
)
))
# connect a SiLA client to the server
client = Client.discover(server_name="Washer", insecure=True)
# converts the steps to json representation for transfer via SiLA as string
protocol = [step.to_string() for step in [prime_step, wait_step, wash_step]]
# call the observable command and receive the observation handler
observable = client.WasherProtocolController.RunCustomSteps(
StepDefinitions=protocol
)
# wait for the command to finish
while not observable.done:
time.sleep(.05)
# check whether the command finished successfully
print(f"Protocol finished with status {observable.status.name}")
server.stop()
I am currently doing the same for the Multiflow FX including syringe pumps. Do you know if there are any serious copy right problems with publishing such stuff?
not for the washer. the other drivers are in our repo: GitHub - PyLabRobot/pylabrobot: interactive & hardware agnostic SDK for lab automation
WasherServer(simulation=True, com_port=“/dev/ttyUSB1”)
how does this work? where does it generate firmware instructions and send them?
that is a question for lawyers
As you described
One does not need the firmware to create those commands either. The generation happens in the background and the code snippet is just how its usage looks including its sila wrapper.
I am still not sure when and where to publish my python-package (without the sila-interface) since agilent might be unhappy when its linked to our university. I do not plan to add it to PLR but that should be quickly done if one know PLR well. I can notify you when its public.
ps: Did you now, that .LHC protocol files are just encrypted XML files.
Hi Rick,
Update: Previously, I figured out the composition of the messages to run program steps by decompiling the .dll and having AI simplify the code and translating it into python. But there is an even better (and not legally questionable) way: You do not need the BTILHCRunner.dll but only the BTI406Interface.dll which can run under ubuntu and wine without problems. It has methods
short RunProgramStep(short p_nStepType, string p_strDefinition);
short SetCOMPortString(string p_strCOMPort);
short TestCommunications();
etc.
I managed to get it imported and running in a 32 bit C# program while emulating the port and receiving its output. This means, I have a python function producing f.e.
[DV103|9|A|44|9|True|5|False|00:01] translates to [01 02 a7 00 01 00 00 0d 00 c9 fe 04 41 2c 00 09 05 00 00 00 00 00 00 00]
which comes for example from a prime step
prime_instructions = PrimeInstructions(
buffer_choice=‘A’,
volume=44,
flow_rate=9,
low_flow_path_volume=5,
do_submerge_after_prime=False,
submerge_time=1,
)
I figured out translation to [DV103|9|A|44|9|True|5|False|00:01] by simply testing what LHC saves in its files.
So, one can generate the firmware instructions on demand or in silico beforehand.
If this is interesting for you, I can keep you updated. I will publish it as soon as im done. Should be much more useful than getting everything from wireshark and a real device.
1 Like