Synergy H1 Backend

Hello everyone,

I have made a pleasant discovery today. My lab has an Agilent BioTek Synergy H1 plate reader that is controlled by the Gen5 software, much like the Cytation 1 and 2. So I did a small test and used the Cytation5 backend to see how that goes.

The good news is that the open and close door functions worked! :partying_face: The unfortunate (and expected) news is that when it came to the read absorbance function, while the plate reader did start to read the plate (based on the noise inside), my script terminated before I could get the data due to what I believe is a read error at a first glance…? I will put the error below as a reference.

Firmware Version: 1.01
Closing door...
Reading absorbance at 600 nm...
Traceback (most recent call last):
  File "/Users/nathaliarodriguez/Documents/GitHub/PLR_projects/SynergyH1/script/synergy_test.py", line 47, in <module>
    asyncio.run(test_cytation())
    ~~~~~~~~~~~^^^^^^^^^^^^^^^^^
  File "/opt/homebrew/Cellar/python@3.13/3.13.7/Frameworks/Python.framework/Versions/3.13/lib/python3.13/asyncio/runners.py", line 195, in run
    return runner.run(main)
           ~~~~~~~~~~^^^^^^
  File "/opt/homebrew/Cellar/python@3.13/3.13.7/Frameworks/Python.framework/Versions/3.13/lib/python3.13/asyncio/runners.py", line 118, in run
    return self._loop.run_until_complete(task)
           ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^
  File "/opt/homebrew/Cellar/python@3.13/3.13.7/Frameworks/Python.framework/Versions/3.13/lib/python3.13/asyncio/base_events.py", line 725, in run_until_complete
    return future.result()
           ~~~~~~~~~~~~~^^
  File "/Users/nathaliarodriguez/Documents/GitHub/PLR_projects/SynergyH1/script/synergy_test.py", line 37, in test_cytation
    data = await pr.read_absorbance(wavelength=600)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/nathaliarodriguez/Documents/GitHub/PLR_projects/pylabrobot/pylabrobot/machines/machine.py", line 35, in wrapper
    return await func(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/nathaliarodriguez/Documents/GitHub/PLR_projects/pylabrobot/pylabrobot/plate_reading/plate_reader.py", line 135, in read_absorbance
    result = await self.backend.read_absorbance(
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    ...<4 lines>...
    )
    ^
  File "/Users/nathaliarodriguez/Documents/GitHub/PLR_projects/pylabrobot/pylabrobot/plate_reading/biotek_backend.py", line 723, in read_absorbance
    body = await self._read_until(b"\x03", timeout=60 * 3)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/nathaliarodriguez/Documents/GitHub/PLR_projects/pylabrobot/pylabrobot/plate_reading/biotek_backend.py", line 521, in _read_until
    x = await self.io.read(1)
        ^^^^^^^^^^^^^^^^^^^^^
  File "/Users/nathaliarodriguez/Documents/GitHub/PLR_projects/pylabrobot/pylabrobot/io/ftdi.py", line 160, in read
    data = self.dev.read(num_bytes)
  File "/Users/nathaliarodriguez/Documents/GitHub/PLR_projects/SynergyH1/synergy/lib/python3.13/site-packages/pylibftdi/device.py", line 424, in read
    byte_data = self._read(length)
  File "/Users/nathaliarodriguez/Documents/GitHub/PLR_projects/SynergyH1/synergy/lib/python3.13/site-packages/pylibftdi/device.py", line 395, in _read
    raise FtdiError(self.get_error_string())
pylibftdi._base.FtdiError: b'usb bulk read failed'

I am no expert, but I expect that the bytes returned from the device are what is causing the error, since the Synergy H1 is obviously different from the Cytation 1 and 5. So the bytes would most likely be different in some ways. How? I am not sure yet, but either way, I am interested in creating a backend for the Synergy H1! :blush:

2 Likes

does a cytation2 exist? do you have one?

I actually was working with another PLR user on integrating this. they sent me a pcap last week, which I have analyzed a little bit but not finished. it’s super similar to the cytation though so should not be too difficult

Pardon for my mistypo, but I meant to say Cytation 1 and 5, not 2 :sweat_smile:

1 Like