Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 19 additions & 0 deletions software/control/laser_engine_widget.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,20 @@ def _engine_summary_label(status: Optional[SquidLaserEngineStatus], connection_l
return "Warming up"


def _is_engine_measured(module) -> bool:
"""Whether this engine actually measures the module's temperature.

Firmware only holds ACTIVE while a channel sits at setpoint: it drops back
to WARMING_UP below -0.5 °C and to CHECK_ERROR at or above the +5 °C error
threshold. A module reporting ACTIVE far outside that band therefore is not
Comment on lines +52 to +54
being regulated here — its TEC controller is wired to something else — and
its temperature/ΔT columns are floor readings rather than measurements.
"""
if module.state != LaserChannelState.ACTIVE:
return True
return -0.5 < module.setpoint_diff_c < 5.0


def _format_temp(info) -> str:
return "/".join(f"{m.temperature_c:.1f}" for m in info.modules) + " °C"

Expand Down Expand Up @@ -116,6 +130,11 @@ def _refresh_channel_lines(self) -> None:
continue
state = info.display_state
on_off = "ON" if info.laser_ttl_on else "OFF"
if not any(_is_engine_measured(m) for m in info.modules):
# Showing the floor readings here would look like an ACTIVE
# channel sitting far below setpoint. Report the state only.
self._channel_lines[key].setText(f"{key:>4} {on_off:<3} {state.name:<14} TEC not engine-controlled")
continue
Comment on lines +133 to +137
self._channel_lines[key].setText(
f"{key:>4} {on_off:<3} {state.name:<14} {_format_temp(info)} ΔT {_format_diff(info)}"
)
Expand Down
45 changes: 45 additions & 0 deletions software/tests/control/test_laser_engine_widget.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
"""Unit tests for the Laser Engine tab's display rules."""

from control.laser_engine_widget import _is_engine_measured
from control.squid_laser_engine import LaserChannelState, TcmModuleInfo


def _module(state, setpoint_diff_c, temperature_c=25.0):
return TcmModuleInfo(
module_index=0,
state=state,
temperature_c=temperature_c,
setpoint_c=temperature_c - setpoint_diff_c,
setpoint_diff_c=setpoint_diff_c,
tec_voltage=0.0,
tec_current=0.0,
hi_temp_setpoint_c=30.0,
)


class TestIsEngineMeasured:
def test_active_at_setpoint_is_measured(self):
assert _is_engine_measured(_module(LaserChannelState.ACTIVE, 0.0))

def test_active_within_band_is_measured(self):
# Firmware tolerates ACTIVE anywhere in (-0.5, +5.0).
assert _is_engine_measured(_module(LaserChannelState.ACTIVE, -0.4))
assert _is_engine_measured(_module(LaserChannelState.ACTIVE, 4.9))

def test_active_far_below_setpoint_is_not_measured(self):
# A channel the engine regulates cannot hold ACTIVE here; it would have
# dropped to WARMING_UP. So this reading is a floor value, not a
# measurement. Matches 638/730 on hardware: 0.4 C with dT -24.6.
assert not _is_engine_measured(_module(LaserChannelState.ACTIVE, -24.6, temperature_c=0.4))

def test_active_at_error_threshold_is_not_measured(self):
assert not _is_engine_measured(_module(LaserChannelState.ACTIVE, 5.0))

def test_warming_up_far_from_setpoint_is_measured(self):
# Genuinely warming: far from setpoint is expected and the numbers are
# real, so they must still be shown.
assert _is_engine_measured(_module(LaserChannelState.WARMING_UP, -66.9, temperature_c=27.2))

def test_sleep_is_measured(self):
# A sleeping channel drifts away from setpoint; still a real reading.
assert _is_engine_measured(_module(LaserChannelState.SLEEP, -42.3, temperature_c=51.8))
Loading