From 008134844d549b6a9a879465d9531dd4fc386bd2 Mon Sep 17 00:00:00 2001 From: Kai Chappell Date: Sun, 4 May 2025 19:34:48 +0000 Subject: [PATCH] Implement thermal chamber SCPI commands MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - TEMP:SETPOINT: Set/query target temperature - TEMP:ACTUAL?: Query actual chamber temperature from physics engine - TEMP:STAB?: Query temperature stability (within 0.5°C threshold) --- src/py_dvt_ate/simulation/virtual/chamber.py | 54 ++++++++++++++++++-- 1 file changed, 51 insertions(+), 3 deletions(-) diff --git a/src/py_dvt_ate/simulation/virtual/chamber.py b/src/py_dvt_ate/simulation/virtual/chamber.py index c682f6c..a10d300 100644 --- a/src/py_dvt_ate/simulation/virtual/chamber.py +++ b/src/py_dvt_ate/simulation/virtual/chamber.py @@ -69,8 +69,27 @@ class ThermalChamberSim(BaseInstrument): Returns: Setpoint value for query, empty string for set command. + + Raises: + ValueError: If setpoint argument is invalid. """ - raise NotImplementedError("TEMP:SETPOINT not yet implemented") + if command.is_query: + return f"{self._setpoint:.2f}" + + # Set command requires one argument + if not command.arguments: + raise ValueError("TEMP:SETPOINT requires a value") + + try: + setpoint = float(command.arguments[0]) + except ValueError: + raise ValueError(f"Invalid temperature value: {command.arguments[0]}") + + self._setpoint = setpoint + if self._physics_engine is not None: + self._physics_engine.set_chamber_setpoint(setpoint) + + return "" def _handle_temp_actual(self, command: SCPICommand) -> str: """Handle TEMP:ACTUAL? query. @@ -80,16 +99,45 @@ class ThermalChamberSim(BaseInstrument): Returns: Actual chamber temperature. + + Raises: + ValueError: If used as command (not query). """ - raise NotImplementedError("TEMP:ACTUAL? not yet implemented") + if not command.is_query: + raise ValueError("TEMP:ACTUAL is query only") + + if self._physics_engine is None: + # Return setpoint if no physics engine connected + return f"{self._setpoint:.2f}" + + thermal_state = self._physics_engine.get_thermal_state() + return f"{thermal_state.chamber_temperature:.2f}" def _handle_temp_stab(self, command: SCPICommand) -> str: """Handle TEMP:STAB? stability query. + Temperature is considered stable when the actual chamber temperature + is within STABILITY_THRESHOLD of the setpoint. + Args: command: Parsed SCPI command. Returns: "1" if stable, "0" if settling. + + Raises: + ValueError: If used as command (not query). """ - raise NotImplementedError("TEMP:STAB? not yet implemented") + if not command.is_query: + raise ValueError("TEMP:STAB is query only") + + if self._physics_engine is None: + # Assume stable if no physics engine connected + return "1" + + thermal_state = self._physics_engine.get_thermal_state() + error = abs(thermal_state.chamber_temperature - self._setpoint) + + if error <= self.STABILITY_THRESHOLD: + return "1" + return "0"