Helios diode current: stop the status poll overwriting the setpoint
The current spin box could not hold a typed value: the 1 Hz status poll read LDS and wrote it straight into the spin box, so the operator's number was replaced by the laser's within a second — before Set could be pressed. The spin box is now seeded once on connect and belongs to the operator after that; the poll's reading goes to a read-back label beside the Set button, so the value about to be sent and the value the laser holds are separate readouts. The write itself was also unverified. Section 6 of the operator's manual: "Commands or set values can be discarded by the controller unintentionally. It is recommended to query the set value after the command is entered to confirm the actual value." set_current_ma() wrote LDS and returned True regardless, so a discarded write looked exactly like a good one. _write_verified() now writes, reads back, and retries up to three times; set_current_ma() and set_frequency_hz() use it, and HeliosWorker reports a refusal on the status line instead of echoing the requested value. Also from the manual, recorded but not acted on: LDS accepts 0-7000 mA (the driver's 2000 mA ceiling is this rig's, not the protocol's), LDF has to be re-sent after LDG changes, and the power-monitor mnemonic is HMP — which this laser does not implement, per the operator. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
+32
-5
@@ -399,8 +399,19 @@ class HeliosWorker(PollingQueueWorker):
|
||||
def _do_set_current(self, current_ma: int):
|
||||
if not self._laser:
|
||||
return
|
||||
self._laser.set_current_ma(current_ma)
|
||||
self.current_updated.emit(current_ma)
|
||||
if self._laser.set_current_ma(current_ma):
|
||||
self.current_updated.emit(current_ma)
|
||||
return
|
||||
# The manual warns the controller drops set values unintentionally,
|
||||
# so the driver verifies the write. Say when it did not take: this
|
||||
# used to emit the requested value regardless, and the next poll
|
||||
# then quietly restored the old one.
|
||||
actual = self._laser.get_current_ma()
|
||||
if actual is not None:
|
||||
self.current_updated.emit(actual)
|
||||
self.error_occurred.emit(
|
||||
f"Diode current: controller kept {actual} mA, "
|
||||
f"did not accept {current_ma} mA")
|
||||
|
||||
def _poll_once(self):
|
||||
"""Read the full status set. Individual reads are allowed to fail
|
||||
@@ -982,6 +993,7 @@ class HeliosWindow(QWidget):
|
||||
self._worker = worker
|
||||
# Polling is driven by the worker itself (self-rescheduling), so
|
||||
# there is no timer here to outpace the device.
|
||||
self._seed_current_spin = False
|
||||
self._wire_signals()
|
||||
self._update_controls(False)
|
||||
self._set_emission_indicator(False)
|
||||
@@ -1029,6 +1041,8 @@ class HeliosWindow(QWidget):
|
||||
self._worker.queue_disconnect()
|
||||
|
||||
def _on_connected(self):
|
||||
# Take the setpoint from the laser once, on connect.
|
||||
self._seed_current_spin = True
|
||||
self.helios_connect_toggle.setEnabled(True)
|
||||
self.helios_connect_toggle.setText("Disconnect")
|
||||
self.helios_status_label.setText("Connected")
|
||||
@@ -1077,9 +1091,20 @@ class HeliosWindow(QWidget):
|
||||
self._worker.queue_set_current(self.helios_current_spin.value())
|
||||
|
||||
def _on_current_updated(self, current_ma: int):
|
||||
self.helios_current_spin.blockSignals(True)
|
||||
self.helios_current_spin.setValue(current_ma)
|
||||
self.helios_current_spin.blockSignals(False)
|
||||
"""Show what the laser reports; leave the spin box to the operator.
|
||||
|
||||
The 1 Hz poll used to write its reading straight into the spin box,
|
||||
so a number typed there was overwritten within a second — the
|
||||
setpoint appeared to snap back to the controller's value before it
|
||||
could be sent. The spin box is now seeded once per connection and
|
||||
is the operator's alone after that; the label is the read-back.
|
||||
"""
|
||||
self.helios_current_readback_label.setText(f"laser: {current_ma} mA")
|
||||
if self._seed_current_spin:
|
||||
self._seed_current_spin = False
|
||||
self.helios_current_spin.blockSignals(True)
|
||||
self.helios_current_spin.setValue(current_ma)
|
||||
self.helios_current_spin.blockSignals(False)
|
||||
|
||||
def _reset_temperatures(self):
|
||||
self.helios_temp_diode_label.setText("--- °C")
|
||||
@@ -1101,6 +1126,8 @@ class HeliosWindow(QWidget):
|
||||
self.helios_enable_btn.setText("Enable Laser")
|
||||
self.helios_enable_btn.blockSignals(False)
|
||||
self._set_emission_indicator(False)
|
||||
self._seed_current_spin = False
|
||||
self.helios_current_readback_label.setText("laser: --- mA")
|
||||
self._reset_temperatures()
|
||||
self.helios_ler_label.setText("---")
|
||||
self.helios_lce_label.setText("---")
|
||||
|
||||
Reference in New Issue
Block a user