mirror of
https://github.com/bec-project/ophyd_devices.git
synced 2026-02-04 14:18:41 +01:00
refactor(psi-motor): Review signal kinds, add custom limit signal
This commit is contained in:
@@ -22,7 +22,9 @@ class SpmgStates:
|
|||||||
|
|
||||||
|
|
||||||
class EpicsMotor(OphydEpicsMotor):
|
class EpicsMotor(OphydEpicsMotor):
|
||||||
"""Extended EPICS Motor class
|
"""
|
||||||
|
Extended EPICS Motor class for PSI motors.
|
||||||
|
|
||||||
|
|
||||||
Special motor class that exposes additional motor record functionality.
|
Special motor class that exposes additional motor record functionality.
|
||||||
It extends EpicsMotor base class to provide some simple status checks
|
It extends EpicsMotor base class to provide some simple status checks
|
||||||
@@ -32,7 +34,7 @@ class EpicsMotor(OphydEpicsMotor):
|
|||||||
tolerated_alarm = AlarmSeverity.INVALID
|
tolerated_alarm = AlarmSeverity.INVALID
|
||||||
|
|
||||||
motor_deadband = Cpt(
|
motor_deadband = Cpt(
|
||||||
EpicsSignal, ".RDBD", auto_monitor=True, kind=Kind.config, doc="Retry Deadband (EGU)"
|
EpicsSignal, ".RDBD", auto_monitor=True, kind=Kind.omitted, doc="Retry Deadband (EGU)"
|
||||||
)
|
)
|
||||||
motor_mode = Cpt(
|
motor_mode = Cpt(
|
||||||
EpicsSignal,
|
EpicsSignal,
|
||||||
@@ -77,6 +79,34 @@ class EpicsMotor(OphydEpicsMotor):
|
|||||||
return super().move(position, wait, **kwargs)
|
return super().move(position, wait, **kwargs)
|
||||||
|
|
||||||
|
|
||||||
|
class TravelLimitsECMC(EpicsSignal):
|
||||||
|
"""
|
||||||
|
Custom EpicsSignal for ECMC travel limits.
|
||||||
|
"""
|
||||||
|
|
||||||
|
def put(self, value, use_complete: bool = True, **kwargs):
|
||||||
|
"""
|
||||||
|
Override put method to handle travel limits.
|
||||||
|
|
||||||
|
This method allows setting the travel limits for the ECMC motor.
|
||||||
|
It ensures that the value is within the acceptable range before
|
||||||
|
sending it to the EPICS server.
|
||||||
|
"""
|
||||||
|
# Get first the current value
|
||||||
|
old_value = self.get()
|
||||||
|
if not use_complete:
|
||||||
|
use_complete = True
|
||||||
|
self.log.warning(f"Overruling use_complete for {self.pvname} to True")
|
||||||
|
# Set the value with put_complete
|
||||||
|
super().put(value, use_complete=use_complete, **kwargs)
|
||||||
|
# Now check if the PLC layer accepted the value change
|
||||||
|
new_value = self.get(auto_monitor=False)
|
||||||
|
if new_value != value:
|
||||||
|
raise ValueError(
|
||||||
|
f"Failed to set travel limit: {value}. Update was rejected by PLC. Limit remains {new_value}."
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class EpicsMotorEC(EpicsMotor):
|
class EpicsMotorEC(EpicsMotor):
|
||||||
"""Detailed ECMC EPICS motor class
|
"""Detailed ECMC EPICS motor class
|
||||||
|
|
||||||
@@ -90,7 +120,7 @@ class EpicsMotorEC(EpicsMotor):
|
|||||||
EpicsSignalRO,
|
EpicsSignalRO,
|
||||||
"-EnaAct",
|
"-EnaAct",
|
||||||
auto_monitor=True,
|
auto_monitor=True,
|
||||||
kind=Kind.normal,
|
kind=Kind.config,
|
||||||
doc="[ECMC] Reflects whether the axis is enabled in the hardware level.",
|
doc="[ECMC] Reflects whether the axis is enabled in the hardware level.",
|
||||||
)
|
)
|
||||||
motor_enable = Cpt(
|
motor_enable = Cpt(
|
||||||
@@ -99,15 +129,17 @@ class EpicsMotorEC(EpicsMotor):
|
|||||||
write_pv="-EnaCmd",
|
write_pv="-EnaCmd",
|
||||||
put_complete=True,
|
put_complete=True,
|
||||||
auto_monitor=True,
|
auto_monitor=True,
|
||||||
kind=Kind.normal,
|
kind=Kind.omitted,
|
||||||
doc="[ECMC] Send enable/disable command to hardware.",
|
doc="[ECMC] Send enable/disable command to hardware.",
|
||||||
)
|
)
|
||||||
homed = Cpt(EpicsSignalRO, "-Homed", auto_monitor=True, kind=Kind.normal)
|
homed = Cpt(
|
||||||
|
EpicsSignalRO, "-Homed", auto_monitor=True, kind=Kind.omitted, doc="[ECMC] Homed status"
|
||||||
|
)
|
||||||
velocity_readback = Cpt(
|
velocity_readback = Cpt(
|
||||||
EpicsSignalRO,
|
EpicsSignalRO,
|
||||||
"-VelAct",
|
"-VelAct",
|
||||||
auto_monitor=True,
|
auto_monitor=True,
|
||||||
kind=Kind.normal,
|
kind=Kind.config, # I would think this depends on the beamline? normal or config
|
||||||
doc="[ECMC] Velocity readback",
|
doc="[ECMC] Velocity readback",
|
||||||
)
|
)
|
||||||
position_readback = Cpt(
|
position_readback = Cpt(
|
||||||
@@ -121,14 +153,18 @@ class EpicsMotorEC(EpicsMotor):
|
|||||||
EpicsSignalRO, "-PosErr", auto_monitor=True, kind=Kind.normal, doc="[ECMC] Position error"
|
EpicsSignalRO, "-PosErr", auto_monitor=True, kind=Kind.normal, doc="[ECMC] Position error"
|
||||||
)
|
)
|
||||||
# Virtual motor and temperature limits are interlocks
|
# Virtual motor and temperature limits are interlocks
|
||||||
high_interlock = Cpt(EpicsSignalRO, "-SumIlockFwd", auto_monitor=True, kind=Kind.normal)
|
high_interlock = Cpt(EpicsSignalRO, "-SumIlockFwd", auto_monitor=True, kind=Kind.omitted)
|
||||||
low_interlock = Cpt(EpicsSignalRO, "-SumIlockBwd", auto_monitor=True, kind=Kind.normal)
|
low_interlock = Cpt(EpicsSignalRO, "-SumIlockBwd", auto_monitor=True, kind=Kind.omitted)
|
||||||
|
|
||||||
error = Cpt(EpicsSignalRO, "-ErrId", auto_monitor=True, kind=Kind.normal)
|
error = Cpt(
|
||||||
|
EpicsSignalRO, "-ErrId", auto_monitor=True, kind=Kind.omitted, doc="[ECMC] Error ID"
|
||||||
|
)
|
||||||
error_msg = Cpt(
|
error_msg = Cpt(
|
||||||
EpicsSignalRO, "-MsgTxt", auto_monitor=True, kind=Kind.normal, doc="[ECMC] Error message"
|
EpicsSignalRO, "-MsgTxt", auto_monitor=True, kind=Kind.omitted, doc="[ECMC] Error message"
|
||||||
)
|
)
|
||||||
error_reset = Cpt(EpicsSignal, "-ErrRst", put_complete=True, kind=Kind.omitted)
|
error_reset = Cpt(EpicsSignal, "-ErrRst", put_complete=True, kind=Kind.omitted)
|
||||||
|
high_limit_travel = Cpt(TravelLimitsECMC, ".HLM", kind="omitted", auto_monitor=True)
|
||||||
|
low_limit_travel = Cpt(TravelLimitsECMC, ".LLM", kind="omitted", auto_monitor=True)
|
||||||
|
|
||||||
def move(self, position, wait=True, **kwargs) -> MoveStatus:
|
def move(self, position, wait=True, **kwargs) -> MoveStatus:
|
||||||
"""Extended move function with a few sanity checks
|
"""Extended move function with a few sanity checks
|
||||||
@@ -167,5 +203,9 @@ class EpicsMotorEC(EpicsMotor):
|
|||||||
# Reset the error
|
# Reset the error
|
||||||
self.error_reset.set(1, settle_time=0.2).wait()
|
self.error_reset.set(1, settle_time=0.2).wait()
|
||||||
# Check if it disappeared
|
# Check if it disappeared
|
||||||
if self.error.get():
|
error = self.error.get(auto_monitor=False)
|
||||||
raise RuntimeError(f"Failed to reset axis, still in error: '{self.error_msg.get()}'")
|
if error:
|
||||||
|
error_msg = self.error_msg.get(auto_monitor=False)
|
||||||
|
raise RuntimeError(
|
||||||
|
f"Failed to reset axis, still in error with id: '{error}, msg: {error_msg}'"
|
||||||
|
)
|
||||||
|
|||||||
Reference in New Issue
Block a user