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!
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! ![]()