Skip to content

Commit

Permalink
#86 EpicsMotorShutter
Browse files Browse the repository at this point in the history
  • Loading branch information
prjemian committed Feb 13, 2019
1 parent 03e367e commit a27fa02
Showing 1 changed file with 45 additions and 86 deletions.
131 changes: 45 additions & 86 deletions apstools/devices.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@
~ApsPssShutterWithStatus
~EpicsMotorShutter
~EpicsOnOffShutter
~OneSignalShutter
synApps records
Expand Down Expand Up @@ -1111,15 +1112,42 @@ class myEpicsMotor(EpicsMotorRawMixin, EpicsMotor): pass
# """


class EpicsMotorShutter(Device):
class EpicsOnOffShutter(OneSignalShutter):
"""
a shutter using a single EPICS PV moved between two positions
Use for a shutter controlled by a single PV which takes a
value for the close command and a different value for the open command.
The current position is determined by comparing the value of the control
with the expected open and close values.
EXAMPLE::
bit_shutter = EpicsOnOffShutter("2bma:bit1", name="bit_shutter")
bit_shutter.closed_position = 0 # default
bit_shutter.open_position = 1 # default
bit_shutter.open()
bit_shutter.close()
# or, when used in a plan
def planA():
yield from mv(bit_shutter, "open")
yield from mv(bit_shutter, "close")
"""
signal = Component(EpicsSignal, "")


class EpicsMotorShutter(EpicsOnOffShutter):
"""
a shutter, implemented with an EPICS motor moved between two positions
EXAMPLE::
tomo_shutter = EpicsMotorShutter("2bma:m23", name="tomo_shutter")
tomo_shutter.closed_position = 1.0 # default
tomo_shutter.open_position = 0.0 # default
tomo_shutter.close_value = 1.0 # default
tomo_shutter.open_value = 0.0 # default
tomo_shutter.tolerance = 0.01 # default
tomo_shutter.open()
tomo_shutter.close()
Expand All @@ -1137,96 +1165,27 @@ def planA():
yield from mv(tomo_shutter, "close")
"""
motor = Component(EpicsMotor, "")
closed_position = 1.0
open_position = 0.0
_tolerance = 0.01

@property
def isOpen(self):
" "
return abs(self.motor.position - self.open_position) <= self._tolerance

signal = Component(EpicsMotor, "")
tolerance = 0.01 # how close is considered in-position?

@property
def isClosed(self):
" "
return abs(self.motor.position - self.closed_position) <= self._tolerance
def state(self):
"""is shutter "open", "close", or "unknown"?"""
if abs(self.signal.position - self.open_value) <= self.tolerance:
result = self.valid_open_values[0]
elif abs(self.signal.position - self.close_value) <= self.tolerance:
result = self.valid_close_values[0]
else:
result = self.unknown_state
return result

def open(self):
"""move motor to BEAM NOT BLOCKED position, interactive use"""
self.motor.move(self.open_position)
self.signal.move(self.open_value)

def close(self):
"""move motor to BEAM BLOCKED position, interactive use"""
self.motor.move(self.closed_position)

def set(self, value, *, timeout=None, settle_time=None):
"""
`set()` is like `put()`, but used in BlueSky plans
PARAMETERS
value : "open" or "close"
timeout : float, optional
Maximum time to wait. Note that set_and_wait does not support
an infinite timeout.
settle_time: float, optional
Delay after the set() has completed to indicate completion
to the caller
RETURNS
status : DeviceStatus
"""

# using put completion:
# timeout and settle time is handled by the status object.
status = DeviceStatus(
self, timeout=timeout, settle_time=settle_time)

def put_callback(**kwargs):
status._finished(success=True)

if value.lower() == "open":
pos = self.open_position
elif value.lower() == "close":
pos = self.closed_position
else:
msg = "value should be either open or close"
msg + " : received " + str(value)
raise ValueError(msg)
self.motor.user_setpoint.put(
pos, use_complete=True, callback=put_callback)

return status


class EpicsOnOffShutter(OneSignalShutter):
"""
a shutter using a single EPICS PV moved between two positions
Use for a shutter controlled by a single PV which takes a
value for the close command and a different value for the open command.
The current position is determined by comparing the value of the control
with the expected open and close values.
EXAMPLE::
bit_shutter = EpicsOnOffShutter("2bma:bit1", name="bit_shutter")
bit_shutter.closed_position = 0 # default
bit_shutter.open_position = 1 # default
bit_shutter.open()
bit_shutter.close()
# or, when used in a plan
def planA():
yield from mv(bit_shutter, "open")
yield from mv(bit_shutter, "close")
"""
signal = Component(EpicsSignal, "")
self.signal.move(self.close_value)


class DualPf4FilterBox(Device):
Expand Down

0 comments on commit a27fa02

Please sign in to comment.