Tecan Initialization Error

Hi, I tried to set up a Tecan using the following code to try out:

from pylabrobot.liquid_handling import LiquidHandler
from pylabrobot.liquid_handling.backends import EVO
from pylabrobot.resources.tecan import TecanDeck
import asyncio

lh = LiquidHandler(backend=EVO(), deck=TecanDeck(num_rails=45, size_x=1315, size_y=780, size_z=765))

async def visualiser():
    await lh.setup()

asyncio.run(visualiser())

However, it seems like there has been some error with initialization. It shows this in my terminal:

Traceback (most recent call last):
  File "c:\Users\Name\Downloads\plr test\visualisertest.py", line 11, in <module>
    asyncio.run(visualiser())
  File "C:\Program Files\Python311\Lib\asyncio\runners.py", line 190, in run
    return runner.run(main)
           ^^^^^^^^^^^^^^^^
  File "C:\Program Files\Python311\Lib\asyncio\runners.py", line 118, in run
    return self._loop.run_until_complete(task)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Program Files\Python311\Lib\asyncio\base_events.py", line 653, in run_until_complete
    return future.result()
           ^^^^^^^^^^^^^^^
  File "c:\Users\Name\Downloads\plr test\visualisertest.py", line 9, in visualiser
    await lh.setup()
  File "C:\Users\Name\AppData\Roaming\Python\Python311\site-packages\pylabrobot\liquid_handling\liquid_handler.py", line 114, in setup
    await super().setup()
  File "C:\Users\Name\AppData\Roaming\Python\Python311\site-packages\pylabrobot\machine.py", line 63, in setup
    await self.backend.setup()
  File "C:\Users\Name\AppData\Roaming\Python\Python311\site-packages\pylabrobot\liquid_handling\backends\tecan\EVO.py", line 241, in setup      
    self._liha_connected = await self.setup_arm(EVO.LIHA)
                           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\Name\AppData\Roaming\Python\Python311\site-packages\pylabrobot\liquid_handling\backends\tecan\EVO.py", line 276, in setup_arm  
    raise e
  File "C:\Users\Name\AppData\Roaming\Python\Python311\site-packages\pylabrobot\liquid_handling\backends\tecan\EVO.py", line 272, in setup_arm  
    await self.send_command(module, command="PIA")
  File "C:\Users\Name\AppData\Roaming\Python\Python311\site-packages\pylabrobot\liquid_handling\backends\tecan\EVO.py", line 143, in send_command
    return self.parse_response(resp)
           ^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\Name\AppData\Roaming\Python\Python311\site-packages\pylabrobot\liquid_handling\backends\tecan\EVO.py", line 98, in parse_response
    raise error_code_to_exception(module, ret)
pylabrobot.liquid_handling.backends.tecan.errors.TecanError: ('Initialization failed', 'C5', 1)

I also tried getting a summary of the Tecan and managed to get some output:

Rail     Resource                   Type                Coordinates (mm)
===============================================================================================
(1)  ├── wash_station               TecanWashStation    (087.500, -20.300, 000.000)
     │   ├── wash_clean_deep        Trash               (099.700, 086.400, 000.000)
     │   ├── wash_waste             Trash               (098.500, 160.400, 000.000)
     │   ├── wash_clean_shallow     Trash               (099.700, 261.400, 000.000)

Traceback (most recent call last):
  File "c:\Users\Name\Downloads\plr test\visualisertest.py", line 11, in <module>
    asyncio.run(visualiser())
  File "C:\Program Files\Python311\Lib\asyncio\runners.py", line 190, in run
    return runner.run(main)
           ^^^^^^^^^^^^^^^^
  File "C:\Program Files\Python311\Lib\asyncio\runners.py", line 118, in run
    return self._loop.run_until_complete(task)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Program Files\Python311\Lib\asyncio\base_events.py", line 653, in run_until_complete
    return future.result()
           ^^^^^^^^^^^^^^^
  File "c:\Users\Name\Downloads\plr test\visualisertest.py", line 9, in visualiser
    await lh.summary()
TypeError: object NoneType can't be used in 'await' expression

What could be the issue?

1 Like

pylabrobot.liquid_handling.backends.tecan.errors.TecanError: ('Initialization failed', 'C5', 1)

Looks like your hardware is not able to initialize. The PLR code is able to communicate via usb, and you’re getting a response from the EVO, but the initialization routine in setup_arm(EVO.LIHA) is failing. If you dig in to that method, you’ll be able to see the firmware commands that are being called (PIA is the first one, ie initialize x,y,z axes), and the responses.

What kind of EVO are you using? Air or liquid filled? Attach a picture if you’re not sure. I’m trying the same thing with an air LiHa and there are some additional commands that are needed to initialize the air LiHa pipettes. I’m not sure yet what those additional commands are - but I’m working on it and going to install wireshark this afternoon to trace further.

3 Likes

lh.summary is not an async method so you should not use await.

1 Like

I’m using a Tecan Freedom EVO 150 Base, not so sure if it’s air or liquid filled, I’ll go check again when I can.

Edit: Oops I am actually using a air LiHa

I tried the setup code again and there were some movement in the Tecan, the ROMA and LiHa did its movement initialization but I was noted that it stopped right before the LiHa and MCA96 did it’s air spraying initialization. Below is my most recent traceback:

Traceback (most recent call last):
  File "c:\Users\Name\Downloads\plr test\visualisertest.py", line 11, in <module>
    asyncio.run(visualiser())
  File "C:\Program Files\Python311\Lib\asyncio\runners.py", line 190, in run
    return runner.run(main)
           ^^^^^^^^^^^^^^^^
  File "C:\Program Files\Python311\Lib\asyncio\runners.py", line 118, in run
    return self._loop.run_until_complete(task)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Program Files\Python311\Lib\asyncio\base_events.py", line 653, in run_until_complete
    return future.result()
           ^^^^^^^^^^^^^^^
  File "c:\Users\Name\Downloads\plr test\visualisertest.py", line 9, in visualiser
    await lh.setup()
  File "C:\Users\Name\AppData\Roaming\Python\Python311\site-packages\pylabrobot\liquid_handling\liquid_handler.py", line 114, in setup
    await super().setup()
  File "C:\Users\Name\AppData\Roaming\Python\Python311\site-packages\pylabrobot\machine.py", line 63, in setup
    await self.backend.setup()
  File "C:\Users\Name\AppData\Roaming\Python\Python311\site-packages\pylabrobot\liquid_handling\backends\tecan\EVO.py", line 261, in setup      
    await self.liha.position_absolute_all_axis(45, 1031, 90, [1200] * self.num_channels)
  File "C:\Users\Name\AppData\Roaming\Python\Python311\site-packages\pylabrobot\liquid_handling\backends\tecan\EVO.py", line 874, in position_absolute_all_axis
    await self.backend.send_command(module=self.module, command="PAA", params=list([x, y, ys] + z))
  File "C:\Users\Name\AppData\Roaming\Python\Python311\site-packages\pylabrobot\liquid_handling\backends\tecan\EVO.py", line 143, in send_command
    return self.parse_response(resp)
           ^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\Name\AppData\Roaming\Python\Python311\site-packages\pylabrobot\liquid_handling\backends\tecan\EVO.py", line 98, in parse_respon    raise error_code_to_exception(module, ret)
pylabrobot.liquid_handling.backends.tecan.errors.TecanError: ('Invalid operand', 'C5', 3)

this sounds as though the Tecan is looking for a location to initialize the plungers,

in EVOware, this would require either a wash/waste station OR a disposable tip waste depending on the arm configuration (liquid or air respectively)

from your description, it seems that the py code is looking for an actual wash/waste station - which isn’t typical for an Air LiHA configured system

I see. The Tecan I use does have waste station to drop the disposable tips, should I define where it is then?

I would add a virtual “wash station” for liquid waste - see if this isolates the issue,

It’s unlikely assigning a trash area in PLR would fix this right now. This might very well be necessary for the final solution, but right now the machine returns an error for command await self.liha.position_absolute_all_axis(45, 1031, 90, [1200] * self.num_channels). All values here are hardcoded / changing the PLR deck setup does not change them.

What I would do is look at the log files, see if C5 is sent, and if so with what parameters. From there, you can see if those correspond to the trash area in your layout file or if there’s another logical way that these are derived. For example, these values could be the center of the trash area. This can then be built into PLR by defining a trash area on the deck and sending the correct C5 command using the trash’s information.

So yours got past the PIA command in setup_arm(EVO.LIHA)? I have an air LiHa too - and haven’t been able to get it past the z axis initialization step.

Invalid Operand from the instrument usually always means its trying to get somewhere it isn’t allowed to, rather than failing to get somewhere it’s not able to. Does changing [x,y,s,z] to different values work?

If memory serves, PAA takes input in 0.1mm, so it’s physically trying to move to - in inches - [x,y,z][0.177,4.06,4.72] from origin: Back left top for EVO. Alternatively, are there any existing limits to the arm X/Y/Z range from axis limit tests? There is a command to retrieve these values but I’m unfortunately blanking.

if PLR is telling the LiHA to move to absolute instrument coordinates, the order of arms on the system could be a factor

what arm configuration is on your system ?
which grid is the disposable tip waste chute located ?

For the Tecan I’m using, the arm configuration from left to right is MCA96, LiHa, ROMA

The disposable tip waste chute wise its around the bottom of grid 27 to grid 34, here’s an image of the worktable editor (sorry for bad resolution it’s the best I could do):

The white box with the pink outline is the waste chute, apparently I heard that when the Tecan was set up there were issues with the waste chute as well and this position was the only position where the Tecan can work with the waste chute attached. I wonder if that’s the issue causing problems here?

Also, log file from the recent run:

2024-03-20 13:42:01,585 - pylabrobot - INFO - Sent command: C5PIA
2024-03-20 13:42:28,293 - pylabrobot - DEBUG - Received data: bytearray(b'\x02C5\x80\x00')
2024-03-20 13:42:28,301 - pylabrobot - INFO - Sent command: C5BMX2
2024-03-20 13:42:28,307 - pylabrobot - DEBUG - Received data: bytearray(b'\x02C5\x80\x00')
2024-03-20 13:42:28,309 - pylabrobot - INFO - Sent command: C1PIA
2024-03-20 13:43:18,068 - pylabrobot - DEBUG - Received data: bytearray(b'\x02C1\x80\x00')
2024-03-20 13:43:18,071 - pylabrobot - INFO - Sent command: C1BMX2
2024-03-20 13:43:18,077 - pylabrobot - DEBUG - Received data: bytearray(b'\x02C1\x80\x00')
2024-03-20 13:43:18,077 - pylabrobot - INFO - Sent command: C1PIX
2024-03-20 13:43:19,413 - pylabrobot - DEBUG - Received data: bytearray(b'\x02C1\x80\x00')
2024-03-20 13:43:19,413 - pylabrobot - INFO - Sent command: C1RPX0
2024-03-20 13:43:19,422 - pylabrobot - DEBUG - Received data: bytearray(b'\x02C1\x803556\x00')
2024-03-20 13:43:19,422 - pylabrobot - INFO - Sent command: C1SAA1,9000,2000,2464,1800,,1,0,0
2024-03-20 13:43:19,432 - pylabrobot - DEBUG - Received data: bytearray(b'\x02C1\x80\x00')
2024-03-20 13:43:19,432 - pylabrobot - INFO - Sent command: C1AAC
2024-03-20 13:43:20,821 - pylabrobot - DEBUG - Received data: bytearray(b'\x02C1\x80\x00')
2024-03-20 13:43:20,827 - pylabrobot - INFO - Sent command: C1RPX0
2024-03-20 13:43:20,835 - pylabrobot - DEBUG - Received data: bytearray(b'\x02C1\x808999\x00')
2024-03-20 13:43:20,837 - pylabrobot - INFO - Sent command: C5PIX
2024-03-20 13:43:22,047 - pylabrobot - DEBUG - Received data: bytearray(b'\x02C5\x80\x00')
2024-03-20 13:43:22,047 - pylabrobot - INFO - Sent command: C5RNT1
2024-03-20 13:43:22,052 - pylabrobot - DEBUG - Received data: bytearray(b'\x02C5\x808\x00')
2024-03-20 13:43:22,052 - pylabrobot - INFO - Sent command: C5RPX5
2024-03-20 13:43:22,055 - pylabrobot - DEBUG - Received data: bytearray(b'\x02C5\x809849\x00')
2024-03-20 13:43:22,055 - pylabrobot - INFO - Sent command: C5RPY5
2024-03-20 13:43:22,063 - pylabrobot - DEBUG - Received data: bytearray(b'\x02C5\x802824,2824\x00')
2024-03-20 13:43:22,066 - pylabrobot - INFO - Sent command: C5RPZ5
2024-03-20 13:43:22,074 - pylabrobot - DEBUG - Received data: bytearray(b'\x02C5\x802100,2100,2100,2100,2100,2100,2100,2100\x00')
2024-03-20 13:43:22,088 - pylabrobot - INFO - Sent command: C5SHZ2100,2100,2100,2100,2100,2100,2100,2100
2024-03-20 13:43:22,096 - pylabrobot - DEBUG - Received data: bytearray(b'\x02C5\x80\x00')
2024-03-20 13:43:22,096 - pylabrobot - INFO - Sent command: C5RPX0
2024-03-20 13:43:22,104 - pylabrobot - DEBUG - Received data: bytearray(b'\x02C5\x802138\x00')
2024-03-20 13:43:22,104 - pylabrobot - INFO - Sent command: C5PAA45,1031,90,1200,1200,1200,1200,1200,1200,1200,1200
2024-03-20 13:43:22,182 - pylabrobot - DEBUG - Received data: bytearray(b'\x02C5\x83\x00')

The coordinates (45, 1031, 90) looks kind of weird to me, because isn’t the Tecan EVO 150’s measurements different? deck=TecanDeck(num_rails=45, size_x=1315, size_y=780, size_z=34.5) was for the deck, the z-axis overshots the deck?

1 Like

thanks for the info,

the C5PAA45,1031,90,1200,1200,1200,1200,1200,1200,1200,1200 is telling the LiHA to move to location around Grid 1,

this won’t work on your config - from what I can see, your init coord should be C5PAA7545,3100,90,2100,2100,2100,2100,2100,2100,2100,2100

2 Likes

@tenkuroh Totally unrelated to PyLabRobot use, but did want to mention that the waste chute absolutely does not need to be at Grid 27 if you don’t want it to be. I also work with a few Tecan Freedom Evo 150s that have all 3 arms (although the configuration i have is LiHa, ROMA, MCA96). Interestingly, it looks like you shuck tips for both heads into the same waste position, as you have a 3 trough carrier. I have a LiHa Waste on the far left side of mine for the LiHa that is attached to a 6 trough carrier, and then have my MCA trash over in Grid 40 or 41 (was previously in Grid 27) .

Having 3 arms on a 150 can be restrictive because of this. It’s a logistics question of what gives you the most deck space, where the ROMA can reach to move plates/replace tip boxes as needed, and how many spots that need access from LiHA+MCA arms only/all 3 arms period. Keeping track of carrier heights around where the MCA96 loads tips is key too (have to be careful about placing labware on raised carriers directly next to it, you can cause crashes that way). Just letting you know that you can probably change if you want to!

2 Likes

This is the problem 100% - [invalid operand] was the clue. Like @Optimize said, the current PAA command is telling the LiHa to head to ~Grid 1 when it should head to somewhere accessible. His suggested home is at ~grid 30 near the waste, but it can really be anywhere between ~ grid 8–>40.
FYI, The grids are each 1" apart so you can easily convert the X value (1/10mm) from firmware commands to grid number by taking / 254 for a sanity check. Same thing works with Y/Z/Raster.

Size_x = 1315 implies ~52 grid segments; somewhere between the 45/69 grids of the 150/200 (speculation, this might be the config for an EVO200 with LiHa/RoMa/MCA). It’s possible that these values aren’t being supplied dynamically and are instead hardcoded. The ranges ought to be different per arm and instrument and firmware commands exist to retrieve these values; for your system, they should look something similar to this:

...Values in 1/10mm	
Arm	    Xmin	Xmax
MCA 	0   	8382
LiHA	2032	9906
RoMa	3556	11430
3 Likes

Glad you got it to initialize. I’m still struggling to get mine to initialize the z-axis through PLR (works fine in EVOware). If anyone has any ideas, my thread is here: Trying to connect to a Tecan EVO

I see, thank you very much!
I was wondering if I should change my liquidhandler line lh = LiquidHandler(backend=EVO(), deck=TecanDeck(num_rails=45, size_x=1315, size_y=780, size_z=34.5)) since it implies a grid space larger than the Tecan I’m using, or should I use lh = LiquidHandler(backend=EVO(), deck=EVO150Deck() instead?

Is your deck size not one of EVO100Deck, EVO150Deck or EVO200Deck? Preferably we have PLR definitions for all possible evo decks that exist. If yours is not already here, do you want to add a new definition and PR it? :smiley:

I think I managed to find out why I was able to get it to initialize. I realized today that I had to initialize the Tecan on EVOware before running the set up code for it to work, if not it’ll still be the same error as you had.