python-microscope / microscope

Python library for control of microscope devices, supporting hardware triggers and distribution of devices over the network for performance and flexibility.
https://www.python-microscope.org
GNU General Public License v3.0
73 stars 42 forks source link

Failed to control Cobolt laser #234

Closed jacopoabramo closed 2 years ago

jacopoabramo commented 2 years ago

I have a Cobolt laser in my setup which I'm trying to control via microscope.

This is the snippet code which I used to test it out:

from microscope.lights.cobolt import CoboltLaser

laser = CoboltLaser("COM4")

laser.enable()
laser.power = 1
print("Press any key to stop...")
input()
laser.power = 0
laser.disable()

I get the following error:

Traceback (most recent call last):
  File "C:\git\sandbox\sandbox.py", line 16, in <module>
    laser = CoboltLaser("COM4")
  File "C:\Users\iScat_Lab\AppData\Local\Programs\Python\Python39\lib\site-packages\microscope\lights\cobolt.py", line 65, in __init__
    self._max_power_mw = float(self.send(b"gmlp?"))
ValueError: could not convert string to float: b'OK'

From the looks of it I assume it's expecting a string formatted as a float but it's failing to do so. Any thoughts?

carandraug commented 2 years ago

I don't have access to a Cobolt laser anymore but from the error message, it's expecting to get back the laser power but is getting the message OK instead. I'd guess that that OK refers to another command, possibly from the previous command. But the reply from the previous command should have been already read so maybe your laser has echo enabled.

First thing, are you sure you don't have some other thread, or maybe even process, controlling the laser?

Assuming you do not, can you patch the source code of cobalt to print to stdout what is happening there. Something like the following should work wonders:

index 663fd91..8e33f7c 100644
--- a/microscope/lights/cobolt.py
+++ b/microscope/lights/cobolt.py
@@ -72,11 +72,13 @@ class CoboltLaser(
         while not success:
             self._write(command)
             response = self._readline()
+            print('command:', command, " response:", response)
             # Catch zero-length responses to queries and retry.
             if not command.endswith(b"?"):
                 success = True
             elif len(response) > 0:
                 success = True
+        print("send success")
         return response

     @microscope.abc.SerialDeviceMixin.lock_comms
jacopoabramo commented 2 years ago

Hi @carandraug, I applied your patch and this is what I get:

command: b'sn?'  response: b'15985'
command: b'@cobas 0'  response: b''
command: b'gmlp?'  response: b''
command: b'gmlp?'  response: b''
command: b'gmlp?'  response: b''
command: b'gmlp?'  response: b''
command: b'gmlp?'  response: b'OK'
Traceback (most recent call last):
  File "C:\git\sandbox\sandbox.py", line 3, in <module>
    laser = CoboltLaser("COM4")
  File "C:\Users\iScat_Lab\AppData\Local\Programs\Python\Python39\lib\site-packages\microscope\lights\cobolt.py", line 65, in __init__
    self._max_power_mw = float(self.send(b"gmlp?"))
ValueError: could not convert string to float: b'OK'
command: b'l0'  response: b'OK'
command: b'l0'  response: b'OK'
command: b'@cob0'  response: b'OK'

To answer your question I do not have any other thread or process controlling the laser. This is still obtained using the code snippet I showed above, it's not within ImSwitch yet.

carandraug commented 2 years ago

From your output, I think that gmlp? is getting the reply from the @cobas 0 command. My guess is that the timeout is too short on your system. Can you check if it works if you increase it to 1 second, i.e., construct the CoboltLaser instance like so:

laser = CoboltLaser("COM4", timeout=1)
jacopoabramo commented 2 years ago

Hi,

this is what I get after adding the timeout (0.1 seems to be sufficient). Now the laser seems to be responding but when trying to set laser.power = 1 I see no output from the laser.

command: sn?  response: 15985
command: @cobas 0  response: OK
command: gmlp?  response: 220.0
command: @cobasdr 0  response: Syntax error: illegal command
command: @cob1  response: OK
command: l1  response: OK
command: l?  response: 1
command: @cobasp 0.2200  response: OK
Press any key to stop...

command: @cobasp 0.0000  response: OK
command: l0  response: OK
command: l0  response: OK
command: l0  response: OK
command: @cob0  response: OK
command: l0  response: OK
command: l0  response: OK
command: @cob0  response: OK
carandraug commented 2 years ago

What model are you controlling exactly? I noticed that your laser does not have direct control (the @cobasdr command is erroring) so it's already different from the one where this code was developed on. Maybe your Cobolt laser has some other specifics. I'm assuming the interlock is not open. What does laser.get_status() return? Do you know what do you need if you were to controlling via serial commands directly?

jacopoabramo commented 2 years ago

Hi @carandraug ,

['Emission on? 1', 'Target power: 0.2200', 'Measured power: 0.0000', 'Fault? 0', 'Head operating hours: 109.36', 'Interlock state: 0']

EDIT: Interlock state: 0 means, from reading the laser manual, that the interlock is not open.

carandraug commented 2 years ago

I see that that the 06-MLD supports analog modulation. Maybe it's set for that? What do the following commands return:

gam? gom? gdmes? glmp?

jacopoabramo commented 2 years ago

From the manual I cannot find the definition of the gam? command but I assume that it refers to the analog modulation support. Here's the output of the commands:

'Analog modulation: 1', 'Operating mode: 1', 'Digital modulation state: 0', 'Laser modulation setpoint: 200.0'

Analog modulation - 1 -> (Enabled?) Operating mode - 1 -> Waiting for key Digital modulation state - 0 -> disabled

carandraug commented 2 years ago

Since the mode returns it's waiting for key, do you have the key control box connected and is the key switch on?

jacopoabramo commented 2 years ago

Ok, apparently the key was turned off. That did it.

Apparently the key control is bypassed by ImSwitch though, which is weird. I can close the issue.

carandraug commented 2 years ago

Apparently the key control is bypassed by ImSwitch though, which is weird. I can close the issue.

The key control seems required for CDRH compliance. This is a safety issue, I don't think this should be done. I'm still interested in knowing how ImSwitch does it.

carandraug commented 2 years ago

Also, I bumped the default timeout for Cobol to 0.1 seconds (which was the original issue report here).