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
67 stars 39 forks source link

Lumencor Spectra III hardware triggers #182

Open carandraug opened 3 years ago

carandraug commented 3 years ago

I have started to implement support for HIGH and LOW trigger types on the Lumencor Spectra III (at the moment it only supports trigger type SOFTWARE).

However, the Lumencor has one master switch to enable TTL input which means that although each channel is its own LightSource instance, changing that settings in one changes the other channels. Example:

green = spectra.devices['GREEN']
blue = spectra.devices['BLUE']

# set green channel for software trigger (on enable it will emit light)
green.set_trigger(TriggerType.SOFTWARE, TriggerMode.BULB)

# green starts emitting light
green.enable()

# setting blue light for hardware trigger also sets the green
blue.set_trigger(TriggerType.HIGH, TriggerMode.BULB)

# green light is no longer on (although enabled) because it's waiting for hardware trigger

# setting blue light for software also sets the green light for software
blue.set_trigger(TriggerType.SOFTWARE, TriggerMode.BULB)

# the green light is back on because it was never disabled

This complicates the implementation because when we set the trigger on one channel, we always need to know the enabled state of the other channels which means they need a way to share the enabled state between them (I guess this will require a dict shared between them).

dstoychev commented 3 years ago

I think this should be reconsidered. I know we've had discussions about this in the past, but now that I've looked into this in greater detail I think we are better off without it. Too much trouble for something that's changed once and forgotten about. It's much better to assume that the TTL signalling has been preconfigured and leave it to the user to ensure that's the case. This also aligns better with how other light sources work, such as the CoolLED ones (TTL always enabled).

Finally, it would be really awkward to associate this behaviour with each channel separately, so I disagree with David's example if I understand it correctly. There is no way to implement this properly because that's not how the light source works. If we want to provide the user with the ability to control the TTL settings, this should be done on the controller level, not on the channel level. But is this functionality really necessary? This is not like a camera or other device where the trigger type needs to be reconfigured after every power cycle. All of Lumencor's Light Engines work like this -- you set it once and forget about it.

dstoychev commented 3 years ago

The first paragraph from my previous comment is not really true. For the software it's important to define/set the trigger mode because that's how the reaction to enable/disable events is determined. Something along the lines of:

Trigger mode disable() of channel enable() of channel
Software turn off light turn on light
Hardware do nothing do nothing

This should be a bit less awkward than having a shared trigger state between channels. Naturally, upon changing the trigger mode of a channel, its state needs to be re-evaluated.

dstoychev commented 3 years ago

I have a working implementation of this here: https://github.com/dstoychev/microscope/tree/lumencor-le.