Added templated scan and required status updates
This commit is contained in:
parent
1f3ef42a9d
commit
16f033a833
@ -119,6 +119,7 @@ class aa1Tasks(Device):
|
|||||||
it and run it directly on a certain thread. But there's no way to
|
it and run it directly on a certain thread. But there's no way to
|
||||||
retrieve the source code.
|
retrieve the source code.
|
||||||
"""
|
"""
|
||||||
|
SUB_PROGRESS = "progress"
|
||||||
_failure = Component(EpicsSignalRO, "FAILURE", kind=Kind.hinted)
|
_failure = Component(EpicsSignalRO, "FAILURE", kind=Kind.hinted)
|
||||||
errStatus = Component(EpicsSignalRO, "ERRW", auto_monitor=True, kind=Kind.hinted)
|
errStatus = Component(EpicsSignalRO, "ERRW", auto_monitor=True, kind=Kind.hinted)
|
||||||
warnStatus = Component(EpicsSignalRO, "WARNW", auto_monitor=True, kind=Kind.hinted)
|
warnStatus = Component(EpicsSignalRO, "WARNW", auto_monitor=True, kind=Kind.hinted)
|
||||||
@ -139,7 +140,23 @@ class aa1Tasks(Device):
|
|||||||
self._textToExecute = None
|
self._textToExecute = None
|
||||||
self._isConfigured = False
|
self._isConfigured = False
|
||||||
self._isStepConfig = False
|
self._isStepConfig = False
|
||||||
|
self.subscribe(self._progress_update, "progress", run=False)
|
||||||
|
|
||||||
|
def _progress_update(self, value, **kwargs) -> None:
|
||||||
|
"""Progress update on the scan"""
|
||||||
|
value = self.progress()
|
||||||
|
self._run_subs( sub_type=self.SUB_PROGRESS, value=value, max_value=1, done=1, )
|
||||||
|
|
||||||
|
def _progress(self) -> None:
|
||||||
|
"""Progress update on the scan"""
|
||||||
|
if self._currentTaskMonitor is None:
|
||||||
|
return 1
|
||||||
|
else:
|
||||||
|
if self._currentTaskMonitor.status.value in ["Running", 4]:
|
||||||
|
return 0
|
||||||
|
else:
|
||||||
|
return 1
|
||||||
|
|
||||||
def readFile(self, filename: str) -> str:
|
def readFile(self, filename: str) -> str:
|
||||||
""" Read a file from the controller """
|
""" Read a file from the controller """
|
||||||
# Have to use CHAR array due to EPICS LSI bug...
|
# Have to use CHAR array due to EPICS LSI bug...
|
||||||
@ -198,7 +215,8 @@ class aa1Tasks(Device):
|
|||||||
old = self.read_configuration()
|
old = self.read_configuration()
|
||||||
self.taskIndex.set(taskIndex).wait()
|
self.taskIndex.set(taskIndex).wait()
|
||||||
self._textToExecute = None
|
self._textToExecute = None
|
||||||
#self._currentTaskMonitor = aa1TaskState()
|
self._currentTaskMonitor = aa1TaskState(prefix=self.prefix+f"T{taskIndex}:", name="taskmon")
|
||||||
|
self._currentTaskMonitor.wait_for_connection()
|
||||||
|
|
||||||
# Choose the right execution mode
|
# Choose the right execution mode
|
||||||
if (filename is None) and (text not in [None, ""]):
|
if (filename is None) and (text not in [None, ""]):
|
||||||
@ -270,11 +288,22 @@ class aa1Tasks(Device):
|
|||||||
|
|
||||||
def complete(self) -> DeviceStatus:
|
def complete(self) -> DeviceStatus:
|
||||||
""" Execute the script on the configured task"""
|
""" Execute the script on the configured task"""
|
||||||
|
print("Called aa1Task.complete()")
|
||||||
#return self._currentTaskMonitor.complete()
|
#return self._currentTaskMonitor.complete()
|
||||||
status = DeviceStatus(self)
|
#status = DeviceStatus(self)
|
||||||
status.set_finished()
|
#status.set_finished()
|
||||||
|
#return status
|
||||||
|
timestamp_ = 0
|
||||||
|
def notRunning(*args, old_value, value, timestamp, **kwargs):
|
||||||
|
nonlocal timestamp_
|
||||||
|
result = False if (timestamp_== 0) else (value not in ["Running", 4])
|
||||||
|
timestamp_ = timestamp
|
||||||
|
print(result)
|
||||||
|
return result
|
||||||
|
# Subscribe and wait for update
|
||||||
|
status = SubscriptionStatus(self._currentTaskMonitor.status, notRunning, settle_time=0.5)
|
||||||
return status
|
return status
|
||||||
|
|
||||||
def describe_collect(self) -> OrderedDict:
|
def describe_collect(self) -> OrderedDict:
|
||||||
dd = OrderedDict()
|
dd = OrderedDict()
|
||||||
dd['success'] = {'source': "internal", 'dtype': 'integer', 'shape': [], 'units': '', 'lower_ctrl_limit': 0, 'upper_ctrl_limit': 0}
|
dd['success'] = {'source': "internal", 'dtype': 'integer', 'shape': [], 'units': '', 'lower_ctrl_limit': 0, 'upper_ctrl_limit': 0}
|
||||||
@ -300,12 +329,14 @@ class aa1TaskState(Device):
|
|||||||
|
|
||||||
def complete(self) -> StatusBase:
|
def complete(self) -> StatusBase:
|
||||||
""" Bluesky flyer interface"""
|
""" Bluesky flyer interface"""
|
||||||
|
print("Called aa1TaskState.complete()")
|
||||||
# Define wait until the busy flag goes down (excluding initial update)
|
# Define wait until the busy flag goes down (excluding initial update)
|
||||||
timestamp_ = 0
|
timestamp_ = 0
|
||||||
def notRunning(*args, old_value, value, timestamp, **kwargs):
|
def notRunning(*args, old_value, value, timestamp, **kwargs):
|
||||||
nonlocal timestamp_
|
nonlocal timestamp_
|
||||||
result = False if (timestamp_== 0) else (value not in ["Running", 4])
|
result = False if (timestamp_== 0) else (value not in ["Running", 4])
|
||||||
timestamp_ = timestamp
|
timestamp_ = timestamp
|
||||||
|
print(result)
|
||||||
return result
|
return result
|
||||||
|
|
||||||
# Subscribe and wait for update
|
# Subscribe and wait for update
|
||||||
|
@ -0,0 +1,87 @@
|
|||||||
|
// Snap-and-step
|
||||||
|
// Test program for high speed step scanning with individual triggers on PSO output.
|
||||||
|
// The file expects external parameter validation.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
program
|
||||||
|
// External parameters
|
||||||
|
var $fStartPosition as real = {{ scan.startpos }}
|
||||||
|
var $iNumSteps as integer = {{ scan.numsteps }}
|
||||||
|
var $fStepSize as real = {{ scan.stepsize }}
|
||||||
|
var $fExposureTimeSec as real = {{ scan.exptime }}
|
||||||
|
var $fVelJog as real = {{ scan.travel or 200 }}
|
||||||
|
var $fVelScan as real = {{ scan.velocity or 50 }}
|
||||||
|
var $fAcceleration = {{ scan.acceleration or 500 }}
|
||||||
|
|
||||||
|
// Internal
|
||||||
|
var $axis as axis = ROTY
|
||||||
|
var $ii as integer
|
||||||
|
|
||||||
|
// Set acceleration
|
||||||
|
SetupAxisRampType($axis, RampType.Linear)
|
||||||
|
SetupAxisRampValue($axis,0,$fAcceleration)
|
||||||
|
|
||||||
|
// Move to start position before the scan
|
||||||
|
var $fPosNext as real = $fStartPosition
|
||||||
|
MoveAbsolute($axis, $fPosNext, $fVelJog)
|
||||||
|
WaitForInPosition($axis)
|
||||||
|
|
||||||
|
// Configure PSO (to manual event generation)
|
||||||
|
PsoDistanceEventsOff($axis)
|
||||||
|
PsoWindowConfigureEvents($axis, PsoWindowEventMode.None)
|
||||||
|
PsoWaveformConfigurePulseFixedTotalTime($axis, 50)
|
||||||
|
PsoWaveformConfigurePulseFixedOnTime($axis, 20)
|
||||||
|
PsoWaveformConfigurePulseFixedCount($axis, 1)
|
||||||
|
PsoWaveformApplyPulseConfiguration($axis)
|
||||||
|
PsoWaveformConfigureMode($axis, PsoWaveformMode.Pulse)
|
||||||
|
PsoOutputConfigureSource($axis, PsoOutputSource.Waveform)
|
||||||
|
PsoWaveformOn($axis)
|
||||||
|
|
||||||
|
// Configure Drive Data Collection
|
||||||
|
var $iDdcArrayAddr as integer = 8388608
|
||||||
|
var $iDdcArraySize as integer = iMaximum(5000, $iNumSteps)
|
||||||
|
var $iDdcSafeSpace as integer = 4096
|
||||||
|
|
||||||
|
DriveDataCaptureConfigureInput($axis, 0, DriveDataCaptureInput.PrimaryFeedback);
|
||||||
|
DriveDataCaptureConfigureInput($axis, 1, DriveDataCaptureInput.AnalogInput0 );
|
||||||
|
|
||||||
|
DriveDataCaptureConfigureTrigger($axis, 0, DriveDataCaptureTrigger.PsoOutput );
|
||||||
|
DriveDataCaptureConfigureTrigger($axis, 1, DriveDataCaptureTrigger.PsoOutput );
|
||||||
|
|
||||||
|
DriveDataCaptureConfigureArray($axis, 0, $iDdcArrayAddr, $iDdcArraySize);
|
||||||
|
DriveDataCaptureConfigureArray($axis, 1, $iDdcArrayAddr + $iDdcSafeSpace + 8 * $iDdcArraySize, $iDdcArraySize);
|
||||||
|
|
||||||
|
// Directly before scan
|
||||||
|
PsoDistanceCounterOn($axis)
|
||||||
|
DriveDataCaptureOn($axis, 0)
|
||||||
|
DriveDataCaptureOn($axis, 1)
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////
|
||||||
|
// Start the actual scanning
|
||||||
|
///////////////////////////////////////////////////////////
|
||||||
|
for $ii = 0 to ($iNumSteps-1)
|
||||||
|
MoveAbsolute($axis, $fPosNext, $fVelScan)
|
||||||
|
WaitForInPosition($axis)
|
||||||
|
PsoEventGenerateSingle($axis)
|
||||||
|
Dwell($fExposureTimeSec)
|
||||||
|
$fPosNext = $fPosNext + $fStepSize
|
||||||
|
end
|
||||||
|
|
||||||
|
// Directly after scan
|
||||||
|
PsoWaveformOff($axis)
|
||||||
|
DriveDataCaptureOff($axis, 0)
|
||||||
|
DriveDataCaptureOff($axis, 1)
|
||||||
|
end
|
||||||
|
|
||||||
|
// Demonstrates using a switch/case conditional.
|
||||||
|
function iMaximum($A as integer, $B as integer) as integer
|
||||||
|
var $retVal
|
||||||
|
if ($A > $B)
|
||||||
|
$retVal = $A
|
||||||
|
else
|
||||||
|
$retVal = $B
|
||||||
|
end
|
||||||
|
return $retVal
|
||||||
|
end
|
||||||
|
|
Loading…
x
Reference in New Issue
Block a user