Response to command R0QWid0006

Hi everyone,

I am new to this forum but have 5+ years of experience with low-cost automation, love coding and have been wrangling my way through the Hamilton Universe for half a year. I am very excited about PyLabRobot’s flexibility and can’t wait to start proper programming for automation on high-end machines.

I ended up being stuck at the setup stage, and would like to ask whether someone has encountered this error and knows a way around it.

Background:

  • Liquid Handling System: Hamilton Microlab STARlet (8-channel, no iSWAP)

  • control: using a separate laptop for PyLabRobot (PLR) to avoid having to switch driver back and forth from VENUS to PLR

  • OS: tried out on both (1) Windows 10 (factory reset for this purpose), (2) MacOS Ventura (M1)

  • Python distribution: miniconda3

  • constructed virtual environment using conda, installed Python 3.10

  • after environment creation instantly installed pylabrobot from source using git (as described in the docs) but also tried out pip installations

The Problem
After running this minimal setup script in a Jupyter Notebook…

%load_ext autoreload
%autoreload 2

from pylabrobot.liquid_handling import LiquidHandler
from pylabrobot.liquid_handling.backends import STAR
from pylabrobot.resources.hamilton import STARLetDeck

backend = STAR()
lh = LiquidHandler(backend=backend, deck=STARLetDeck())

await lh.setup()

…I encounder this complete error message (os.environ[‘PYUSB_DEBUG’] = ‘debug’ to give detailed information about what PyUSB is doing):

2023-12-22 09:32:33,913 INFO:usb.core:find(): using backend "usb.backend.libusb1"
2023-12-22 09:32:33,914 DEBUG:usb.backend.libusb1:_LibUSB.enumerate_devices()
2023-12-22 09:32:33,915 DEBUG:usb.backend.libusb1:_LibUSB.get_device_descriptor(<usb.backend.libusb1._Device object at 0x10ccc23b0>)
2023-12-22 09:32:33,915 DEBUG:usb.backend.libusb1:_LibUSB.get_device_descriptor(<usb.backend.libusb1._Device object at 0x10ccc24a0>)
2023-12-22 09:32:33,916 DEBUG:usb.backend.libusb1:_LibUSB.get_configuration_descriptor(<usb.backend.libusb1._Device object at 0x10ccc23b0>, 0)
2023-12-22 09:32:33,916 DEBUG:usb.backend.libusb1:_LibUSB.open_device(<usb.backend.libusb1._Device object at 0x10ccc23b0>)
2023-12-22 09:32:33,916 DEBUG:usb.backend.libusb1:_LibUSB.set_configuration(<usb.backend.libusb1._DeviceHandle object at 0x103ec6500>, 1)
2023-12-22 09:32:33,917 DEBUG:usb.backend.libusb1:_LibUSB.get_configuration_descriptor(<usb.backend.libusb1._Device object at 0x10ccc23b0>, 0)
2023-12-22 09:32:33,917 DEBUG:usb.backend.libusb1:_LibUSB.get_interface_descriptor(<usb.backend.libusb1._Device object at 0x10ccc23b0>, 0, 0, 0)
2023-12-22 09:32:33,917 DEBUG:usb.backend.libusb1:_LibUSB.get_configuration_descriptor(<usb.backend.libusb1._Device object at 0x10ccc23b0>, 0)
2023-12-22 09:32:33,918 DEBUG:usb.backend.libusb1:_LibUSB.get_endpoint_descriptor(<usb.backend.libusb1._Device object at 0x10ccc23b0>, 0, 0, 0, 0)
2023-12-22 09:32:33,918 DEBUG:usb.backend.libusb1:_LibUSB.get_interface_descriptor(<usb.backend.libusb1._Device object at 0x10ccc23b0>, 0, 0, 0)
2023-12-22 09:32:33,918 DEBUG:usb.backend.libusb1:_LibUSB.get_configuration_descriptor(<usb.backend.libusb1._Device object at 0x10ccc23b0>, 0)
2023-12-22 09:32:33,918 DEBUG:usb.backend.libusb1:_LibUSB.get_endpoint_descriptor(<usb.backend.libusb1._Device object at 0x10ccc23b0>, 1, 0, 0, 0)
2023-12-22 09:32:33,918 DEBUG:usb.backend.libusb1:_LibUSB.get_interface_descriptor(<usb.backend.libusb1._Device object at 0x10ccc23b0>, 0, 0, 0)
2023-12-22 09:32:33,919 DEBUG:usb.backend.libusb1:_LibUSB.get_configuration_descriptor(<usb.backend.libusb1._Device object at 0x10ccc23b0>, 0)
2023-12-22 09:32:33,919 DEBUG:usb.backend.libusb1:_LibUSB.get_endpoint_descriptor(<usb.backend.libusb1._Device object at 0x10ccc23b0>, 0, 0, 0, 0)
2023-12-22 09:32:33,919 DEBUG:usb.backend.libusb1:_LibUSB.get_interface_descriptor(<usb.backend.libusb1._Device object at 0x10ccc23b0>, 0, 0, 0)
2023-12-22 09:32:33,919 DEBUG:usb.backend.libusb1:_LibUSB.get_configuration_descriptor(<usb.backend.libusb1._Device object at 0x10ccc23b0>, 0)
2023-12-22 09:32:33,919 DEBUG:usb.backend.libusb1:_LibUSB.get_configuration_descriptor(<usb.backend.libusb1._Device object at 0x10ccc23b0>, 0)
2023-12-22 09:32:33,919 DEBUG:usb.backend.libusb1:_LibUSB.get_interface_descriptor(<usb.backend.libusb1._Device object at 0x10ccc23b0>, 0, 0, 0)
2023-12-22 09:32:33,920 DEBUG:usb.backend.libusb1:_LibUSB.get_configuration_descriptor(<usb.backend.libusb1._Device object at 0x10ccc23b0>, 0)
2023-12-22 09:32:33,920 DEBUG:usb.backend.libusb1:_LibUSB.get_endpoint_descriptor(<usb.backend.libusb1._Device object at 0x10ccc23b0>, 0, 0, 0, 0)
2023-12-22 09:32:33,920 DEBUG:usb.backend.libusb1:_LibUSB.get_interface_descriptor(<usb.backend.libusb1._Device object at 0x10ccc23b0>, 0, 0, 0)
2023-12-22 09:32:33,920 DEBUG:usb.backend.libusb1:_LibUSB.get_configuration_descriptor(<usb.backend.libusb1._Device object at 0x10ccc23b0>, 0)
2023-12-22 09:32:33,920 DEBUG:usb.backend.libusb1:_LibUSB.claim_interface(<usb.backend.libusb1._DeviceHandle object at 0x103ec6500>, 0)
2023-12-22 09:32:33,921 DEBUG:usb.backend.libusb1:_LibUSB.bulk_read(<usb.backend.libusb1._DeviceHandle object at 0x103ec6500>, 129, 0, array('B', [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]), 3000)
2023-12-22 09:32:37,155 DEBUG:usb.backend.libusb1:_LibUSB.get_configuration_descriptor(<usb.backend.libusb1._Device object at 0x10ccc23b0>, 0)
2023-12-22 09:32:37,157 DEBUG:usb.backend.libusb1:_LibUSB.get_interface_descriptor(<usb.backend.libusb1._Device object at 0x10ccc23b0>, 0, 0, 0)
2023-12-22 09:32:37,158 DEBUG:usb.backend.libusb1:_LibUSB.get_configuration_descriptor(<usb.backend.libusb1._Device object at 0x10ccc23b0>, 0)
2023-12-22 09:32:37,160 DEBUG:usb.backend.libusb1:_LibUSB.get_endpoint_descriptor(<usb.backend.libusb1._Device object at 0x10ccc23b0>, 0, 0, 0, 0)
2023-12-22 09:32:37,161 DEBUG:usb.backend.libusb1:_LibUSB.get_interface_descriptor(<usb.backend.libusb1._Device object at 0x10ccc23b0>, 0, 0, 0)
2023-12-22 09:32:37,162 DEBUG:usb.backend.libusb1:_LibUSB.get_configuration_descriptor(<usb.backend.libusb1._Device object at 0x10ccc23b0>, 0)
2023-12-22 09:32:37,163 DEBUG:usb.backend.libusb1:_LibUSB.get_endpoint_descriptor(<usb.backend.libusb1._Device object at 0x10ccc23b0>, 1, 0, 0, 0)
2023-12-22 09:32:37,164 DEBUG:usb.backend.libusb1:_LibUSB.get_interface_descriptor(<usb.backend.libusb1._Device object at 0x10ccc23b0>, 0, 0, 0)
2023-12-22 09:32:37,165 DEBUG:usb.backend.libusb1:_LibUSB.get_configuration_descriptor(<usb.backend.libusb1._Device object at 0x10ccc23b0>, 0)
2023-12-22 09:32:37,167 DEBUG:usb.backend.libusb1:_LibUSB.bulk_write(<usb.backend.libusb1._DeviceHandle object at 0x103ec6500>, 2, 0, array('B', [67, 48, 82, 84, 105, 100, 48, 48, 48, 49]), 30)
2023-12-22 09:32:37,169 DEBUG:usb.backend.libusb1:_LibUSB.bulk_read(<usb.backend.libusb1._DeviceHandle object at 0x103ec6500>, 129, 0, array('B', [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]), 3000)
2023-12-22 09:32:37,201 DEBUG:usb.backend.libusb1:_LibUSB.bulk_write(<usb.backend.libusb1._DeviceHandle object at 0x103ec6500>, 2, 0, array('B', [67, 48, 81, 77, 105, 100, 48, 48, 48, 50]), 30)
2023-12-22 09:32:37,203 DEBUG:usb.backend.libusb1:_LibUSB.bulk_read(<usb.backend.libusb1._DeviceHandle object at 0x103ec6500>, 129, 0, array('B', [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]), 3000)
2023-12-22 09:32:37,235 DEBUG:usb.backend.libusb1:_LibUSB.bulk_read(<usb.backend.libusb1._DeviceHandle object at 0x103ec6500>, 129, 0, array('B', [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]), 3000)
2023-12-22 09:32:37,237 DEBUG:usb.backend.libusb1:_LibUSB.bulk_read(<usb.backend.libusb1._DeviceHandle object at 0x103ec6500>, 129, 0, array('B', [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]), 3000)
2023-12-22 09:32:37,245 DEBUG:usb.backend.libusb1:_LibUSB.bulk_write(<usb.backend.libusb1._DeviceHandle object at 0x103ec6500>, 2, 0, array('B', [67, 48, 81, 87, 105, 100, 48, 48, 48, 51]), 30)
2023-12-22 09:32:37,247 DEBUG:usb.backend.libusb1:_LibUSB.bulk_read(<usb.backend.libusb1._DeviceHandle object at 0x103ec6500>, 129, 0, array('B', [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]), 3000)
2023-12-22 09:32:37,279 DEBUG:usb.backend.libusb1:_LibUSB.bulk_write(<usb.backend.libusb1._DeviceHandle object at 0x103ec6500>, 2, 0, array('B', [67, 48, 86, 73, 105, 100, 48, 48, 48, 52]), 30)
2023-12-22 09:32:37,282 DEBUG:usb.backend.libusb1:_LibUSB.bulk_read(<usb.backend.libusb1._DeviceHandle object at 0x103ec6500>, 129, 0, array('B', [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]), 3000)
2023-12-22 09:32:38,981 DEBUG:usb.backend.libusb1:_LibUSB.bulk_write(<usb.backend.libusb1._DeviceHandle object at 0x103ec6500>, 2, 0, array('B', [67, 48, 68, 73, 105, 100, 48, 48, 48, 53, 120, 112, 48, 56, 48, 48, 48, 38, 121, 112, 52, 48, 53, 48, 32, 51, 55, 56, 51, 32, 51, 53, 49, 54, 32, 51, 50, 52, 57, 32, 50, 57, 56, 50, 32, 50, 55, 49, 53, 32, 50, 52, 52, 56, 32, 50, 49, 56, 49, 116, 112, 50, 52, 53, 48, 116, 122, 49, 50, 50, 48, 116, 101, 51, 54, 48, 48, 116, 109, 49, 38, 116, 116, 48, 52, 116, 105, 48]), 30)
2023-12-22 09:32:38,984 DEBUG:usb.backend.libusb1:_LibUSB.bulk_read(<usb.backend.libusb1._DeviceHandle object at 0x103ec6500>, 129, 0, array('B', [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]), 3000)
2023-12-22 09:32:42,271 DEBUG:usb.backend.libusb1:_LibUSB.bulk_read(<usb.backend.libusb1._DeviceHandle object at 0x103ec6500>, 129, 0, array('B', [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]), 3000)
2023-12-22 09:32:45,586 DEBUG:usb.backend.libusb1:_LibUSB.bulk_read(<usb.backend.libusb1._DeviceHandle object at 0x103ec6500>, 129, 0, array('B', [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]), 3000)
2023-12-22 09:32:48,892 DEBUG:usb.backend.libusb1:_LibUSB.bulk_read(<usb.backend.libusb1._DeviceHandle object at 0x103ec6500>, 129, 0, array('B', [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]), 3000)
2023-12-22 09:32:52,202 DEBUG:usb.backend.libusb1:_LibUSB.bulk_read(<usb.backend.libusb1._DeviceHandle object at 0x103ec6500>, 129, 0, array('B', [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]), 3000)
2023-12-22 09:32:55,532 DEBUG:usb.backend.libusb1:_LibUSB.bulk_read(<usb.backend.libusb1._DeviceHandle object at 0x103ec6500>, 129, 0, array('B', [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]), 3000)
2023-12-22 09:32:58,901 DEBUG:usb.backend.libusb1:_LibUSB.bulk_read(<usb.backend.libusb1._DeviceHandle object at 0x103ec6500>, 129, 0, array('B', [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]), 3000)
2023-12-22 09:33:02,135 DEBUG:usb.backend.libusb1:_LibUSB.bulk_read(<usb.backend.libusb1._DeviceHandle object at 0x103ec6500>, 129, 0, array('B', [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]), 3000)
2023-12-22 09:33:05,145 DEBUG:usb.backend.libusb1:_LibUSB.bulk_read(<usb.backend.libusb1._DeviceHandle object at 0x103ec6500>, 129, 0, array('B', [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]), 3000)
2023-12-22 09:33:06,088 DEBUG:usb.backend.libusb1:_LibUSB.bulk_read(<usb.backend.libusb1._DeviceHandle object at 0x103ec6500>, 129, 0, array('B', [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]), 3000)
2023-12-22 09:33:06,091 DEBUG:usb.backend.libusb1:_LibUSB.bulk_write(<usb.backend.libusb1._DeviceHandle object at 0x103ec6500>, 2, 0, array('B', [82, 48, 81, 87, 105, 100, 48, 48, 48, 54]), 30)
2023-12-22 09:33:06,093 DEBUG:usb.backend.libusb1:_LibUSB.bulk_read(<usb.backend.libusb1._DeviceHandle object at 0x103ec6500>, 129, 0, array('B', [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]), 3000)
2023-12-22 09:33:08,090 DEBUG:usb.backend.libusb1:_LibUSB.bulk_read(<usb.backend.libusb1._DeviceHandle object at 0x103ec6500>, 129, 0, array('B', [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]), 3000)
2023-12-22 09:33:11,466 DEBUG:usb.backend.libusb1:_LibUSB.bulk_read(<usb.backend.libusb1._DeviceHandle object at 0x103ec6500>, 129, 0, array('B', [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]), 3000)
2023-12-22 09:33:14,778 DEBUG:usb.backend.libusb1:_LibUSB.bulk_read(<usb.backend.libusb1._DeviceHandle object at 0x103ec6500>, 129, 0, array('B', [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]), 3000)
2023-12-22 09:33:18,087 DEBUG:usb.backend.libusb1:_LibUSB.bulk_read(<usb.backend.libusb1._DeviceHandle object at 0x103ec6500>, 129, 0, array('B', [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]), 3000)
2023-12-22 09:33:21,420 DEBUG:usb.backend.libusb1:_LibUSB.bulk_read(<usb.backend.libusb1._DeviceHandle object at 0x103ec6500>, 129, 0, array('B', [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]), 3000)
2023-12-22 09:33:24,708 DEBUG:usb.backend.libusb1:_LibUSB.bulk_read(<usb.backend.libusb1._DeviceHandle object at 0x103ec6500>, 129, 0, array('B', [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]), 3000)
2023-12-22 09:33:28,041 DEBUG:usb.backend.libusb1:_LibUSB.bulk_read(<usb.backend.libusb1._DeviceHandle object at 0x103ec6500>, 129, 0, array('B', [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]), 3000)
2023-12-22 09:33:31,408 DEBUG:usb.backend.libusb1:_LibUSB.bulk_read(<usb.backend.libusb1._DeviceHandle object at 0x103ec6500>, 129, 0, array('B', [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]), 3000)
2023-12-22 09:33:34,712 DEBUG:usb.backend.libusb1:_LibUSB.bulk_read(<usb.backend.libusb1._DeviceHandle object at 0x103ec6500>, 129, 0, array('B', [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]), 3000)
2023-12-22 09:33:38,022 DEBUG:usb.backend.libusb1:_LibUSB.bulk_read(<usb.backend.libusb1._DeviceHandle object at 0x103ec6500>, 129, 0, array('B', [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]), 3000)
---------------------------------------------------------------------------
TimeoutError                              Traceback (most recent call last)
Cell In[3], line 1
----> 1 await lh.setup()

File ~/pylabrobot/pylabrobot/liquid_handling/liquid_handler.py:91, in LiquidHandler.setup(self)
     88 if self.setup_finished:
     89   raise RuntimeError("The setup has already finished. See `LiquidHandler.stop`.")
---> 91 await super().setup()
     93 self.head = {c: TipTracker(thing=f"Channel {c}") for c in range(self.backend.num_channels)}
     95 self.resource_assigned_callback(self.deck)

File ~/pylabrobot/pylabrobot/machine.py:49, in MachineFrontend.setup(self)
     48 async def setup(self):
---> 49   await self.backend.setup()
     50   self._setup_finished = True

File ~/pylabrobot/pylabrobot/liquid_handling/backends/hamilton/STAR.py:1254, in STAR.setup(self)
   1241   y_positions = [4050 - i * dy for i in range(self.num_channels)]
   1243   await self.initialize_pipetting_channels(
   1244     x_positions=[extended_conf["xw"]],  # Tip eject waste X position.
   1245     y_positions=y_positions,
   (...)
   1251     discarding_method=0
   1252   )
-> 1254 iswap_initialized = await self.request_iswap_initialization_status()
   1255 if self.iswap_installed and not iswap_initialized:
   1256   await self.initialize_iswap()

File ~/pylabrobot/pylabrobot/liquid_handling/backends/hamilton/STAR.py:6121, in STAR.request_iswap_initialization_status(self)
   6114 async def request_iswap_initialization_status(self) -> bool:
   6115   """ Request iSWAP initialization status
   6116 
   6117   Returns:
   6118     True if iSWAP is fully initialized
   6119   """
-> 6121   resp = await self.send_command(module="R0", command="QW", fmt="qw#")
   6122   return cast(int, resp["qw"]) == 1

File ~/pylabrobot/pylabrobot/liquid_handling/backends/hamilton/STAR.py:1172, in STAR.send_command(self, module, command, tip_pattern, write_timeout, read_timeout, wait, fmt, **kwargs)
   1158 async def send_command(
   1159   self,
   1160   module: str,
   (...)
   1167   **kwargs
   1168 ):
   1169   """ Send a command to the machine. Parse the response if `fmt != ""`, else return the raw
   1170   response. """
-> 1172   resp = await super().send_command(
   1173     module=module,
   1174     command=command,
   1175     tip_pattern=tip_pattern,
   1176     write_timeout=write_timeout,
   1177     read_timeout=read_timeout,
   1178     wait=wait,
   1179     **kwargs
   1180   )
   1181   if fmt != "":
   1182     parsed = parse_star_fw_string(resp, fmt)

File ~/pylabrobot/pylabrobot/liquid_handling/backends/hamilton/base.py:191, in HamiltonLiquidHandler.send_command(self, module, command, tip_pattern, write_timeout, read_timeout, wait, **kwargs)
    170 """ Send a firmware command to the Hamilton machine.
    171 
    172 Args:
   (...)
    186   A dictionary containing the parsed response, or None if no response was read within `timeout`.
    187 """
    189 cmd, id_ = self._assemble_command(module=module, command=command, tip_pattern=tip_pattern,
    190   **kwargs)
--> 191 return await self._write_and_read_command(id_=id_, cmd=cmd, write_timeout=write_timeout,
    192                 read_timeout=read_timeout, wait=wait)

File ~/pylabrobot/pylabrobot/liquid_handling/backends/hamilton/base.py:215, in HamiltonLiquidHandler._write_and_read_command(self, id_, cmd, write_timeout, read_timeout, wait)
    213 fut = loop.create_future()
    214 self._start_reading(id_, loop, fut, cmd, read_timeout)
--> 215 result = await fut
    216 return cast(dict, result)

TimeoutError: Timeout while waiting for response to command R0QWid0006.

If I understand the error message correctly, the setup was checking for the existence of an iSWAP but instead of returning None, as it was supposed to, it raised a TimeoutError?

This might be a very simple problem but digging into the PLR codebase I couldn’t find the solution.

Thank you for your help.

Hi Camillo and welcome to the forum!

The method crashed when checking if iswap is initialized. Apparently, when no iswap is installed on the machine this command will just time out.

Instead, we should only check the initialization status when iswap is actually installed. I hope the following commit fixes this.

Could you pull and retry? Please let me know if that works!

4 Likes

Hi Rick,

Thank you for the fast response!

The update in the STAR.py file does indeed fix the lh.setup() and it now recognises that we don’t have an iSWAP.

However, testing the basic functions next using…

from pylabrobot.resources import (
    TIP_CAR_480_A00,
    PLT_CAR_L5AC_A00,
    HTF_L,
    TIP_CAR_480BC_SlimTips300ulFilter_A00,
)

# Assign tip carrier and tip racks
tip_car = TIP_CAR_480_A00(name='tip carrier')
tip_car[1] = HTF_L(name='tips_02')
tip_car[2] = HTF_L(name='tips_03')
tip_car[3] = TIP_CAR_480BC_SlimTips300ulFilter_A00(name='tips_04')
lh.deck.assign_child_resource(tip_car, rails=1)
#
tiprack2 = lh.get_resource("tips_02")
tiprack3 = lh.get_resource("tips_03")
tiprack4 = lh.get_resource("tips_04")
#
await lh.pick_up_tips(tiprack3["A1:C1"])

… throws up this error message:

---------------------------------------------------------------------------
STARFirmwareError                         Traceback (most recent call last)
Cell In[3], line 16
     14 tiprack = lh.get_resource("tips_01")
     15 #
---> 16 await lh.pick_up_tips(tiprack["A1:C1"])

File ~/pylabrobot/pylabrobot/machine.py:20, in need_setup_finished.<locals>.wrapper(self, *args, **kwargs)
     18 if not self.setup_finished:
     19   raise RuntimeError("The setup has not finished. See `setup`.")
---> 20 return await func(self, *args, **kwargs)

File ~/pylabrobot/pylabrobot/liquid_handling/liquid_handler.py:364, in LiquidHandler.pick_up_tips(self, tip_spots, use_channels, offsets, **backend_kwargs)
    361   del backend_kwargs[extra]
    363 try:
--> 364   await self.backend.pick_up_tips(ops=pickups, use_channels=use_channels, **backend_kwargs)
    365 except:
    366   for channel, op in zip(use_channels, pickups):

File ~/pylabrobot/pylabrobot/liquid_handling/backends/hamilton/STAR.py:59, in need_iswap_parked.<locals>.wrapper(self, *args, **kwargs)
     56 @functools.wraps(method)
     57 async def wrapper(self, *args, **kwargs):
     58   if not self.iswap_parked:
---> 59     await self.park_iswap()
     61   result = await method(self, *args, **kwargs) # pylint: disable=not-callable
     63   return result

File ~/pylabrobot/pylabrobot/liquid_handling/backends/hamilton/STAR.py:5671, in STAR.park_iswap(self, minimum_traverse_height_at_beginning_of_a_command)
   5659 """ Close gripper
   5660 
   5661 The gripper should be at the position gb+gt+20 before sending this command.
   (...)
   5665             of a command [0.1mm]. Must be between 0 and 3600. Default 3600.
   5666 """
   5668 assert 0 <= minimum_traverse_height_at_beginning_of_a_command <= 3600, \
   5669   "minimum_traverse_height_at_beginning_of_a_command must be between 0 and 3600"
-> 5671 command_output = await self.send_command(
   5672   module="C0",
   5673   command="PG",
   5674   th=minimum_traverse_height_at_beginning_of_a_command
   5675 )
   5677 # Once the command has completed successfully, set _iswap_parked to True
   5678 self._iswap_parked = True

File ~/pylabrobot/pylabrobot/liquid_handling/backends/hamilton/STAR.py:1172, in STAR.send_command(self, module, command, tip_pattern, write_timeout, read_timeout, wait, fmt, **kwargs)
   1158 async def send_command(
   1159   self,
   1160   module: str,
   (...)
   1167   **kwargs
   1168 ):
   1169   """ Send a command to the machine. Parse the response if `fmt != ""`, else return the raw
   1170   response. """
-> 1172   resp = await super().send_command(
   1173     module=module,
   1174     command=command,
   1175     tip_pattern=tip_pattern,
   1176     write_timeout=write_timeout,
   1177     read_timeout=read_timeout,
   1178     wait=wait,
   1179     **kwargs
   1180   )
   1181   if fmt != "":
   1182     parsed = parse_star_fw_string(resp, fmt)

File ~/pylabrobot/pylabrobot/liquid_handling/backends/hamilton/base.py:191, in HamiltonLiquidHandler.send_command(self, module, command, tip_pattern, write_timeout, read_timeout, wait, **kwargs)
    170 """ Send a firmware command to the Hamilton machine.
    171 
    172 Args:
   (...)
    186   A dictionary containing the parsed response, or None if no response was read within `timeout`.
    187 """
    189 cmd, id_ = self._assemble_command(module=module, command=command, tip_pattern=tip_pattern,
    190   **kwargs)
--> 191 return await self._write_and_read_command(id_=id_, cmd=cmd, write_timeout=write_timeout,
    192                 read_timeout=read_timeout, wait=wait)

File ~/pylabrobot/pylabrobot/liquid_handling/backends/hamilton/base.py:215, in HamiltonLiquidHandler._write_and_read_command(self, id_, cmd, write_timeout, read_timeout, wait)
    213 fut = loop.create_future()
    214 self._start_reading(id_, loop, fut, cmd, read_timeout)
--> 215 result = await fut
    216 return cast(dict, result)

File ~/pylabrobot/pylabrobot/liquid_handling/backends/hamilton/base.py:284, in HamiltonLiquidHandler._continuously_read(self)
    282 if response_id == id_:
    283   try:
--> 284     self.check_fw_string_error(resp)
    285   except Exception as e: # pylint: disable=broad-exception-caught
    286     loop.call_soon_threadsafe(fut.set_exception, e)

File ~/pylabrobot/pylabrobot/liquid_handling/backends/hamilton/STAR.py:1156, in STAR.check_fw_string_error(self, resp)
   1147   if error.message == "Unknown parameter":
   1148     # temp. disabled until we figure out how to handle async in parse response (the
   1149     # background thread does not have an event loop, and I'm not sure if it should.)
   (...)
   1152 
   1153     # pylint: disable=unnecessary-dict-index-lookup
   1154     he[module_name].message += " (call lh.backend.request_name_of_last_faulty_parameter)"
-> 1156 raise he

STARFirmwareError: STARFirmwareError(errors={'Master': CommandSyntaxError('Unknown command')}, raw_response=C0PGid0006er01/30)

This was stupid.

2 Likes

Haha, that is quite funny.

Thank you, Rick. I couldn’t test the change today anymore but will let you know after the Christmas break how it went. It seems I am the first person using PLR on a Hamilton that doesn’t have an iSWAP.

I will also open a new thread in PyLabRobot Development on how we could maybe implement CO-RE gripper-based plate movement in PLR and how plate and tip stacking is currently handled.

2 Likes

Yes, very likely :wink:

Thanks to @ben and co at Retro this is already implemented! Just use the use_arm parameter: lh.move_plate(plate, plate_carrier[1], use_arm="core"). (PR: implement CO-RE gripper by ben-ray · Pull Request #42 · PyLabRobot/pylabrobot · GitHub)

Plates can be stacked on top of one another, but I’m not sure about tip racks. Let’s discuss that soon.

I look forward to hearing how it goes after the break!

2 Likes

thanks Rick for the quick fixes

whenever I need to stack plates or tips, I define -z offsets for each layer of the stack & pass these offsets into the tip pickup, aspirate, and co-re commands

1 Like

Thank you, @ben. The CO-RE gripper implementation looks fantastic.

I have a couple more questions regarding CO-RE gripper-based labware movement, and just generated a new discussion for them to separate it from this thread and make it easier to find in the future.

I will update on the no-iSWAP updates here after the break though.

1 Like

Update: PLR works very well now on a Hamilton STARlet without an iSWAP. Thank you for the fast help!

1 Like