diff --git a/socs/agents/scpi_psu/agent.py b/socs/agents/scpi_psu/agent.py index f89a352fb..11e235f90 100644 --- a/socs/agents/scpi_psu/agent.py +++ b/socs/agents/scpi_psu/agent.py @@ -1,6 +1,7 @@ import argparse import socket import time +from typing import Optional from ocs import ocs_agent, site_config from ocs.ocs_twisted import TimeoutLock @@ -19,7 +20,7 @@ def __init__(self, agent, ip_address, gpib_slot): self.gpib_slot = gpib_slot self.monitor = False - self.psu = None + self.psu: Optional[ScpiPsuAgent] = None # Registers Temperature and Voltage feeds agg_params = { @@ -41,16 +42,25 @@ def init(self, session, params=None): if not acquired: return False, "Could not acquire lock" - try: - self.psu = PsuInterface(self.ip_address, self.gpib_slot) - self.idn = self.psu.identify() - except socket.timeout as e: - self.log.error(f"PSU timed out during connect: {e}") - return False, "Timeout" - self.log.info("Connected to psu: {}".format(self.idn)) - + while not self._initialize_module(): + time.sleep(5) return True, 'Initialized PSU.' + def _initialize_module(self): + """Initialize the ScpiPsu module.""" + try: + self.psu = PsuInterface(self.ip_address, self.gpib_slot) + except (socket.timeout, OSError) as e: + self.log.warn(f"Error establishing connection: {e}") + self.psu = None + return False + + self.idn = self.psu.identify() + self.log.info("Connected to psu: {}".format(self.idn)) + self.log.info("Clearing event registers and error queue") + self.psu.clear() + return True + @ocs_agent.param('wait', type=float, default=1) @ocs_agent.param('channels', type=list, default=[1, 2, 3]) @ocs_agent.param('test_mode', type=bool, default=False) @@ -71,29 +81,36 @@ def monitor_output(self, session, params=None): self.monitor = True while self.monitor: + time.sleep(params['wait']) with self.lock.acquire_timeout(1) as acquired: - if acquired: - data = { - 'timestamp': time.time(), - 'block_name': 'output', - 'data': {} - } + if not acquired: + self.log.warn("Could not acquire in monitor_current") + continue + + if not self.psu: + self._initialize_module() + continue + data = { + 'timestamp': time.time(), + 'block_name': 'output', + 'data': {} + } + + try: for chan in params['channels']: data['data']["Voltage_{}".format(chan)] = self.psu.get_volt(chan) data['data']["Current_{}".format(chan)] = self.psu.get_curr(chan) + except socket.timeout as e: + self.log.warn(f"TimeoutError: {e}") + self.log.info("Attempting to reconnect") + self.psu = None + continue - # self.log.info(str(data)) - # print(data) - self.agent.publish_to_feed('psu_output', data) - - # Allow this process to be queried to return current data - session.data = data + self.agent.publish_to_feed('psu_output', data) - else: - self.log.warn("Could not acquire in monitor_current") - - time.sleep(params['wait']) + # Allow this process to be queried to return current data + session.data = data if params['test_mode']: break diff --git a/socs/agents/scpi_psu/drivers.py b/socs/agents/scpi_psu/drivers.py index 64a1dbead..e986e43d0 100644 --- a/socs/agents/scpi_psu/drivers.py +++ b/socs/agents/scpi_psu/drivers.py @@ -80,3 +80,9 @@ def get_curr(self, ch): self.write('MEAS:CURR? CH' + str(ch)) current = float(self.read()) return current + + def clear(self): + # Clear all the event registers and error queue, using a query such as *ESR? or MEAS:X? + # instead of *CLS can confuse the PSU + self.write('*CLS') + return True