Skip to content
Merged
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
2 changes: 1 addition & 1 deletion config/hscal/hscal_hkettherm.yaml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# CAL RED (HK) Etalon SRS PTC10 daemon config
#
# Usage:
# daemons/generic/srstherm -c config/hscal/hscal_hkettherm.yaml
# daemons/hscal/srs_thermal -c config/hscal/hscal_hkettherm.yaml

peer_id: hkettherm
group_id: hscal
Expand Down
2 changes: 1 addition & 1 deletion config/hscal/hscal_yjettherm.yaml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# CAL BLUE (YJ) Etalon SRS PTC10 daemon config
#
# Usage:
# daemons/generic/srstherm -c config/hscal/hscal_yjettherm.yaml
# daemons/hscal/srs_thermal -c config/hscal/hscal_yjettherm.yaml

peer_id: yjettherm
group_id: hscal
Expand Down
64 changes: 51 additions & 13 deletions daemons/generic/srsthermal → daemons/hscal/srs_thermal
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
#!/usr/bin/env python3
"""
Generic Stanford Research Systems PTC10 Thermal control Daemon
Generic Stanford Research Systems model PTC10 Daemon

Exposes the SRS PTC10 Temperature controller commands as libby keywords.
Exposes the SRS PTC10 etalon temperature controller commands as libby keywords.
"""

import argparse
Expand All @@ -12,15 +12,16 @@ from hispec import HispecDaemon
from hispec.driver.srs.ptc10 import PTC10


class SRSThermalDaemon(HispecDaemon): # pylint: disable=W0223,too-many-instance-attributes
"""Daemon for controlling the SRS PTC10 via keywords."""
class SrsDaemon(HispecDaemon): # pylint: disable=W0223,too-many-instance-attributes
"""Daemon for controlling the SRS via keywords."""

def __init__(self):
super().__init__()

self.ip_address = None
self.tcp_port = None
self.units = None
self.units = "C"
self.srs_model = "PTC10"
self.sensors = None
self.heaters = None
self.error = None
Expand All @@ -41,7 +42,8 @@ class SRSThermalDaemon(HispecDaemon): # pylint: disable=W0223,too-many-instance

self.controller = PTC10(log=True)

self.logger.info("Starting %s daemon", self.peer_id)
self.logger.info("Starting %s daemon with for model %s in degrees C",
self.peer_id, self.srs_model)
self.logger.info("Using sensors: %s", self.sensors)
self.logger.info("Using heaters: %s", self.heaters)

Expand All @@ -51,10 +53,13 @@ class SRSThermalDaemon(HispecDaemon): # pylint: disable=W0223,too-many-instance
self.keyword_registry.bool("isconnected",
getter=self.controller.is_connected,
setter=self._set_connected,
description="SRS PTC10 controller is connected.")
description="SRS controller is connected.")
self.keyword_registry.string("error",
getter=self._error_string,
description="Last error from the SRS PTC10 controller.")
description="Last error from the SRS controller.")
self.keyword_registry.string("status",
getter=self._status,
description="Status of the SRS as a (code, message) string.")
self.keyword_registry.trigger("shutdown",
action=self._shutdown,
description="Shutdown the daemon now.")
Expand All @@ -66,6 +71,10 @@ class SRSThermalDaemon(HispecDaemon): # pylint: disable=W0223,too-many-instance
try:
self._connect_hardware()
self.logger.info("Daemon started successfully and connected to hardware")
if self.controller.initialize():
self.logger.info("Hardware successfully initialized")
else:
self.logger.error("Hardware failed to initialize")
except Exception as e: # pylint: disable=W0718
self.logger.error("Failed to connect to hardware: %s", e)
self.error = str(e)
Expand Down Expand Up @@ -97,16 +106,35 @@ class SRSThermalDaemon(HispecDaemon): # pylint: disable=W0223,too-many-instance

self.keyword_registry.float(
keyword,
getter=self._make_setpoint_getter(output),
setter=self._make_setpoint_setter(output),
units=self.units,
description=f"Setpoint for heater output {output}.")
self.keyword_registry.float(
f"{keyword}_output",
getter=self._make_output_getter(output),
units="Amps",
description=f"Output amps of heater output {output}.")
description=f"Heater output in amps: {output}.")

def _make_temperature_getter(self, channel):
"""Return a zero-argument getter reading the temperature at `channel`."""
def getter():
return self.controller.get_atomic_value(channel)
return getter

def _make_setpoint_getter(self, output):
"""Return a zero-argument getter reading the setpoint of heater `output`."""
def getter():
return self.controller.get_setpoint(output)
return getter

def _make_setpoint_setter(self, output):
"""Return a one-argument setter writing the setpoint of heater `output`."""
def setter(value):
if not self.controller.set_setpoint(output, value):
raise RuntimeError(f"Failed to set setpoint for heater output {output}")
return setter

def _make_output_getter(self, output):
"""Return a zero-argument getter reading the power of heater `output`."""
def getter():
Expand All @@ -120,20 +148,30 @@ class SRSThermalDaemon(HispecDaemon): # pylint: disable=W0223,too-many-instance
self.controller.disconnect()
self.request_stop()

def _connected(self) -> bool:
"""True when the driver holds an open session to the SRS controller."""
return self.controller is not None and bool(self.controller.is_connected())

def _status(self):
"""Handles status."""
if not self._connected():
return str((-1, "ERROR: Not connected to hardware"))
return str(self.controller.get_status())

def on_stop(self, libby=None):
"""Cleanup when the daemon shuts down."""
self.logger.info("Shutting down %s daemon", self.peer_id)
if self.controller is None:
return
try:
self.controller.disconnect()
self.logger.info("Disconnected from SRS PTC10 controller")
self.logger.info("Disconnected from SRS controller")
except Exception as e: # pylint: disable=W0718
self.logger.error("Error disconnecting: %s", e)
self.error = str(e)

def _connect_hardware(self):
self.logger.info("Connecting to SRS PTC10 controller at %s:%s",
self.logger.info("Connecting to SRS controller at %s:%s",
self.ip_address, self.tcp_port)
self.controller.connect(host=self.ip_address, port=int(self.tcp_port))
# The drivers signal failure by staying disconnected rather than raising
Expand All @@ -155,7 +193,7 @@ class SRSThermalDaemon(HispecDaemon): # pylint: disable=W0223,too-many-instance

def main():
"""Main entry point for the daemon."""
parser = argparse.ArgumentParser(description='Generic SRS PTC10 Daemon')
parser = argparse.ArgumentParser(description='Generic SRS Daemon')
parser.add_argument('-c', '--config', type=str,
help='Path to config file (YAML or JSON)')

Expand All @@ -166,7 +204,7 @@ def main():
sys.exit(2)

try:
daemon = SRSThermalDaemon.from_config_file(args.config)
daemon = SrsDaemon.from_config_file(args.config)
daemon.serve()
except KeyboardInterrupt:
print("\nDaemon interrupted by user")
Expand Down
6 changes: 3 additions & 3 deletions docs/architecture/daemons.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ their shared `pdu_base.py` base class.
|---|---|---|---|
| `generic/filterwheel` | `thorlabs.fw102c` | Thorlabs FW102C filter wheel | `hsfei_atcfw`, `hscal_hkcalfwheel1/2`, `hscal_hkgcellfwheel`, `hscal_yjcalfwheel1/2` |
| `generic/lakeshore` | `lakeshore.lakeshore` | Lakeshore 336/224 temperature controller | `hsfei_atctherm`, `hscal_gcellheater1/2` |
| `generic/srsthermal` | `srs.ptc10` | SRS PTC10 thermal controller | `hscal_hkettherm`, `hscal_yjettherm` |
| `hscal/srs_thermal` | `srs.ptc10` | SRS PTC10 thermal controller | `hscal_hkettherm`, `hscal_yjettherm` |
| `generic/inficon` | `inficon.inficonvgc502` | Inficon VGC502 vacuum gauge controller | `hsfei_atcpress` |
| `hsfei/pi-daemon` | `pi.PIControllerBase` | PI C-663 / C-863 / E-754 motion controllers | `hsfei_atcl`, `hsfei_atcp`, `hsfei_feipo`, `hsfei_lsm`, `hsfei_ms` |
| `hsfei/adc` | `newport.smc100pp` | Newport SMC100PP ADC prism rotators | `hsfei_adc` |
Expand Down Expand Up @@ -170,10 +170,10 @@ aggregates likewise and one write closes every loop. A single-stage config
registers the bare names directly, so a client that only cares about the
mechanism as a whole uses the same keyword either way.

**Thermal daemons** (`lakeshore`, `srsthermal`) generate their keywords from
**Thermal daemons** (`lakeshore`, `srs_thermal`) generate their keywords from
config. Each entry in `sensors:` produces one read-only temperature keyword
under the name the config chose; each entry in `heaters:` produces a writable
setpoint plus, for the Lakeshore, `<name>_output`, `<name>_status` and one
setpoint and `<name>_output` plus, for the Lakeshore, `<name>_status` and one
keyword per PID term.

**`atccryo`** exposes cryocooler state — `cold_head_temp`, `reject_temp`,
Expand Down
4 changes: 2 additions & 2 deletions docs/operations/systemd.md
Original file line number Diff line number Diff line change
Expand Up @@ -432,8 +432,8 @@ dependencies or `[email protected]` changed. `/opt/hispec` belongs to
| `hscal_gcellheater1` | `hispecserver` | `generic/lakeshore` | `config/hscal/hscal_gcellheater1.yaml` |
| `hscal_gcellheater2` | `hispecserver` | `generic/lakeshore` | `config/hscal/hscal_gcellheater2.yaml` |
| `hsfei_atctherm` | `hispecserver` | `generic/lakeshore` | `config/hsfei/hsfei_atctherm.yaml` |
| `hscal_hkettherm` | `hispecserver` | `generic/srsthermal` | `config/hscal/hscal_hkettherm.yaml` |
| `hscal_yjettherm` | `hispecserver` | `generic/srsthermal` | `config/hscal/hscal_yjettherm.yaml` |
| `hscal_hkettherm` | `hispecserver` | `hscal/srs_thermal` | `config/hscal/hscal_hkettherm.yaml` |
| `hscal_yjettherm` | `hispecserver` | `hscal/srs_thermal` | `config/hscal/hscal_yjettherm.yaml` |
| `hscal_hketatten` | `hispecserver` | `hscal/smc8_attenuator` | `config/hscal/hscal_hketatten.yaml` |
| `hsfei_adc` | `hispecserver` | `hsfei/adc` | `config/hsfei/hsfei_adc.yaml` |
| `hsfei_atccryo` | `hispecserver` | `hsfei/atccryo` | `config/hsfei/hsfei_atccryo.yaml` |
Expand Down
2 changes: 1 addition & 1 deletion src/hispec/driver/srs
Submodule srs updated 1 files
+40 −2 ptc10.py
2 changes: 1 addition & 1 deletion systemd/instances/hscal_hkettherm.env
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,5 @@
# copies this file to /etc/hispec/instances/hscal_hkettherm.env and
# config/hscal/hscal_hkettherm.yaml to /etc/hispec/hscal_hkettherm.yaml, then
# enables and starts the daemon.
HISPEC_DAEMON=generic/srsthermal
HISPEC_DAEMON=hscal/srs_thermal
HISPEC_HOST=hispecserver
2 changes: 1 addition & 1 deletion systemd/instances/hscal_yjettherm.env
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,5 @@
# copies this file to /etc/hispec/instances/hscal_yjettherm.env and
# config/hscal/hscal_yjettherm.yaml to /etc/hispec/hscal_yjettherm.yaml, then
# enables and starts the daemon.
HISPEC_DAEMON=generic/srsthermal
HISPEC_DAEMON=hscal/srs_thermal
HISPEC_HOST=hispecserver
Loading