Simplesequence posneg triggers correctly

This commit is contained in:
gac-x05la
2024-10-16 11:21:09 +02:00
parent 22c57aacd9
commit 08ca35d270
3 changed files with 80 additions and 97 deletions
@@ -3,6 +3,10 @@
// The file expects external parameter validation
// The PSO locations arrays are set externally from EPICS PV
//
#define DDC_ADDR 0x800000
#define PSO_ADDR 0x0
enum ScanType
POS = 0
@@ -16,7 +20,7 @@ program
//////////////////////////////////////////////////////////////////////////
// External parameters - USE THEESE
var $fStartPosition as real = {{ scan.startpos }}
var $fScanRange as real = $fStartPosition + {{ scan.scanrange }}
var $fScanRange as real = {{ scan.scanrange }}
var $iNumRepeat as integer = {{ scan.nrepeat }}
var $eScanType as ScanType = ScanType.{{ scan.scandir or 'POS' }}
var $iNumDdcRead as integer = {{ scan.npoints }}
@@ -25,7 +29,8 @@ program
var $fVelScan as real = {{ scan.scanvel }}
var $fAcceleration = {{ scan.scanacc }}
var $fAccDistance as real = {{ scan.accdist }}
var $eDdcTrigger as DriveDataCaptureTrigger = DriveDataCaptureTrigger.{{ scan.psotrigger }}
//////////////////////////////////////////////////////////////////////////
// Internal parameters - dont use
var $axis as axis = ROTY
@@ -34,7 +39,7 @@ program
// Set acceleration
SetupAxisRampType($axis, RampType.Linear)
SetupAxisRampValue($axis,0,$fAcceleration)
SetupAxisRampValue($axis, 0, $fAcceleration)
// set the actual scan range
var $fPosStart as real
@@ -57,36 +62,48 @@ program
MoveAbsolute($axis, $fPosStart, $fVelJog)
WaitForInPosition($axis)
// Set globals for feedback
$rglobal[2] = $fPosStart
$rglobal[3] = $fPosEnd
// Configure PSO
// FIXME : When the controller is restarted
PsoDistanceConfigureInputs($axis, [PsoDistanceInput.XC4PrimaryFeedback])
PsoDistanceCounterOff($axis)
PsoDistanceEventsOff($axis)
PsoWindowConfigureEvents($axis, PsoWindowEventMode.None)
PsoWaveformOff($axis)
PsoOutputConfigureSource($axis, PsoOutputSource.Waveform)
var $iPsoArrayAddr as integer = 0
var $iPsoArrayPosAddr as integer = PSO_ADDR
// Simple PSO trigger pattern
var $iPsoArrayPos[] as real = [{% for psoDist in scan.psoBoundsPos[:-1] %} UnitsToCounts($axis, psoDist), {% endfor %}]
var $iPsoArrayNeg[] as real = [{% for psoDist in scan.psoBoundsNeg[:-1] %} UnitsToCounts($axis, psoDist), {% endfor %}]
var $iPsoArrayPos[] as real = [{% for psoDist in scan.psoBoundsPos[:-1] %} UnitsToCounts($axis, {{ psoDist }}), {% endfor %} UnitsToCounts($axis, {{ scan.psoBoundsPos[-1] }}) ]
var $iPsoArrayNeg[] as real = [{% for psoDist in scan.psoBoundsNeg[:-1] %} UnitsToCounts($axis, {{ psoDist }}), {% endfor %} UnitsToCounts($axis, {{ scan.psoBoundsNeg[-1] }}) ]
var $iPsoArrayPosSize as integer = {{ scan.psoBoundsPosSize }}
var $iPsoArrayNegSize as integer = {{ scan.psoBoundsNegSize }}
// Calculate negative array offset (in bytes)
var $iPsoArrayNegAddr as integer = ($iPsoArrayPosAddr + length($iPsoArrayPos)) * 4
DriveArrayWrite($axis, $iPsoArrayPos, $iPsoArrayAddr, length($iPsoArrayPos), DriveArrayType.PsoDistanceEventDistances)
PsoDistanceConfigureArrayDistances($axis, $iPsoArrayAddr, length($iPsoArrayPos), 0)
DriveArrayWrite($axis, $iPsoArrayPos, $iPsoArrayPosAddr, length($iPsoArrayPos), DriveArrayType.PsoDistanceEventDistances)
DriveArrayWrite($axis, $iPsoArrayNeg, $iPsoArrayNegAddr, length($iPsoArrayNeg), DriveArrayType.PsoDistanceEventDistances)
PsoDistanceConfigureArrayDistances($axis, $iPsoArrayPosAddr, length($iPsoArrayPos), 0)
PsoDistanceCounterOn($axis)
PsoDistanceEventsOn($axis)
PsoWaveformConfigureMode($axis, PsoWaveformMode.Toggle)
PsoWaveformOn($axis)
PsoWaveformOn($axis)
PsoOutputConfigureSource($axis, PsoOutputSource.Waveform)
// Configure Drive Data Collection
var $iDdcArrayAddr as integer = 8388608
var $iDdcArraySize as integer = $iNumDdcRead
DriveDataCaptureConfigureInput($axis, 0, DriveDataCaptureInput.PrimaryFeedback);
DriveDataCaptureConfigureInput($axis, 1, DriveDataCaptureInput.AnalogInput0 );
DriveDataCaptureConfigureTrigger($axis, 0, DriveDataCaptureTrigger.PsoOutput );
DriveDataCaptureConfigureTrigger($axis, 1, DriveDataCaptureTrigger.PsoOutput );
DriveDataCaptureConfigureTrigger($axis, 0, $eDdcTrigger );
DriveDataCaptureConfigureTrigger($axis, 1, $eDdcTrigger );
DriveDataCaptureConfigureArray($axis, 0, $iDdcArrayAddr, $iDdcArraySize);
DriveDataCaptureConfigureArray($axis, 1, $iDdcArrayAddr + $iDdcSafeSpace + 8 * $iDdcArraySize, $iDdcArraySize);
DriveDataCaptureConfigureArray($axis, 0, DDC_ADDR, $iDdcArraySize);
DriveDataCaptureConfigureArray($axis, 1, DDC_ADDR + $iDdcSafeSpace + 8 * $iDdcArraySize, $iDdcArraySize);
// Directly before scan
PsoDistanceCounterOn($axis)
@@ -97,31 +114,38 @@ program
// Start the actual scanning
///////////////////////////////////////////////////////////
for $ii = 0 to ($iNumRepeat-1)
PsoDistanceConfigureArrayDistances($axis, $iPsoArrayAddr, length($iPsoArrayPos), 0)
// Feedback on progress
$rglobal[4] = $ii
if $eScanType == ScanType.POS
PsoDistanceConfigureArrayDistances($axis, $iPsoArrayPosAddr, $iPsoArrayPosSize, 0)
MoveAbsolute($axis, $fPosEnd, $fVelScan)
WaitForInPosition($axis)
MoveAbsolute($axis, $fPosStart, $fVelScan)
WaitForInPosition($axis)
elseif $eScanType == ScanType.NEG
elseif $eScanType == ScanType.NEG
PsoDistanceConfigureArrayDistances($axis, $iPsoArrayPosAddr, $iPsoArrayPosSize, 0)
MoveAbsolute($axis, $fPosEnd, $fVelScan)
WaitForInPosition($axis)
MoveAbsolute($axis, $fPosStart, $fVelScan)
WaitForInPosition($axis)
elseif $eScanType == ScanType.POSNEG
elseif $eScanType == ScanType.POSNEG
if ($ii % 2) == 0
PsoDistanceConfigureArrayDistances($axis, $iPsoArrayPosAddr, $iPsoArrayPosSize, 0)
MoveAbsolute($axis, $fPosEnd, $fVelScan)
WaitForInPosition($axis)
elseif ($ii % 2) == 1
PsoDistanceConfigureArrayDistances($axis, $iPsoArrayNegAddr, $iPsoArrayNegSize, 0)
MoveAbsolute($axis, $fPosStart, $fVelScan)
WaitForInPosition($axis)
end
elseif $eScanType == ScanType.NEGPOS
if ($ii % 2) == 0
PsoDistanceConfigureArrayDistances($axis, $iPsoArrayPosAddr, $iPsoArrayPosSize, 0)
MoveAbsolute($axis, $fPosEnd, $fVelScan)
WaitForInPosition($axis)
elseif ($ii % 2) == 1
PsoDistanceConfigureArrayDistances($axis, $iPsoArrayNegAddr, $iPsoArrayNegSize, 0)
MoveAbsolute($axis, $fPosStart, $fVelScan)
WaitForInPosition($axis)
end
+32 -33
View File
@@ -363,7 +363,7 @@ class SnapAndStepScanBase(TemplatedScanBase):
# Aerotech DDC settings: Internal event trigger: PsoEvent = 1
if isinstance(sync, str):
t_modes = {'event': 1, 'pso': 2, 'inp0': 3, 'inp1': 1}
t_modes = {'pso': 0, 'event': 1, 'inp0': 2, 'inp1': 4}
daq_trigger = t_modes[sync]
else:
daq_trigger = int(sync)
@@ -436,7 +436,6 @@ class SequenceScanBase(TemplatedScanBase):
self.scan_repmode = repmode
self.exp_time = exp_time
self.exp_frames = exp_frames
self.acc_dist = 42
# Synthetic values
self.scan_velocity = gate_high / (exp_time * exp_frames)
@@ -444,28 +443,36 @@ class SequenceScanBase(TemplatedScanBase):
self.scan_safedistance = 10
self.scan_accdistance = self.scan_safedistance + 0.5* self.scan_velocity * self.scan_velocity / self.scan_acceleration
self.scan_ntotal = exp_frames * repeats
if repmode.lower() in ("pos", "neg"):
self.scan_range = gate_high + gate_low
elif repmode.lower() in ("posneg", "negpos"):
self.scan_range = repeats *(gate_high + gate_low)
if repmode.upper() in ("POS", "NEG"):
self.scan_range = repeats *(gate_high + gate_low)
elif repmode.upper() in ("POSNEG", "NEGPOS"):
self.scan_range = gate_high + gate_low
else:
raise RuntimeError(f"Unsupported repetition mode: {repmode}")
# Aerotech DDC settings: Internal event trigger: PsoEvent = 1
t_modes = {'pso': 0, 'event': 1, 'inp0': 2, 'inp1': 4}
p_modes = {'pso': 'PsoOutput', 'event': 'PsoEvent', 'inp0': 'HighSpeedInput0RisingEdge', 'inp1': 'HighSpeedInput1RisingEdge'}
daq_trigger = t_modes[sync]
pso_trigger = p_modes[sync]
# AeroScript substitutions
filename = "AerotechSimpleSequenceTemplate.ascript"
filesubs = {
'startpos': self.scan_start,
'scanrange': self.scan_range,
'nrepeat': self.scan_repnum,
'scanvel': self.scan_velocity,
'scanacc': self.scan_acceleration,
'accdist': self.scan_accdistance,
'npoints' : self.scan_ntotal,
'scandir' : self.scan_repmode.upper()
'scandir' : self.scan_repmode.upper(),
'psotrigger': pso_trigger
}
# Aerotech DDC settings: Internal event trigger: PsoEvent = 1
if isinstance(sync, str):
t_modes = {'event': 1, 'pso': 2, 'inp0': 3, 'inp1': 1}
daq_trigger = t_modes[sync]
else:
daq_trigger = int(sync)
print(filesubs)
# Drice data collection config
# FIXME: The data sources need to be set to same as the script
daqname = "es1_ddaq"
daqcfg = {'ntotal': self.scan_ntotal, 'trigger': daq_trigger}
# Gigafrost config
@@ -497,34 +504,26 @@ class SequenceScanBase(TemplatedScanBase):
self.psoBoundsPos = []
self.psoBoundsNeg = []
if self.scan_repmode in ("pos", "Pos"):
self.psoBoundsPos.append(self.acc_dist)
self.psoBoundsPos.append(self.scan_accdistance)
for ii in range(self.scan_repnum):
self.psoBoundsPos += [self.gate_high, self.gate_low]
self.psoBoundsPos[-1] = 10* (self.acc_dist+self.gate_low)
# self.psoBoundsPos[-1] = 10* (self.scan_accdistance+self.gate_low)
if self.scan_repmode in ("neg", "Neg"):
self.psoBoundsNeg.append(self.acc_dist)
self.psoBoundsNeg.append(self.scan_accdistance)
for ii in range(self.scan_repnum):
self.psoBoundsNeg += [self.gate_high, self.gate_low]
self.psoBoundsNeg[-1] = 10* (self.acc_dist+self.gate_low)
# self.psoBoundsNeg[-1] = 10* (self.scan_accdistance+self.gate_low)
if self.scan_repmode in ("posneg", "PosNeg"):
self.psoBoundsPos.append(self.acc_dist)
self.psoBoundsNeg.append(self.acc_dist + self.gate_low)
for ii in range(self.scan_repnum // 2):
self.psoBoundsPos += [self.gate_high, self.gate_low]
self.psoBoundsNeg += [self.gate_high, self.gate_low]
self.psoBoundsPos[-1] = 10* (self.acc_dist+self.gate_low)
self.psoBoundsNeg[-1] = 10* (self.acc_dist+self.gate_low)
self.psoBoundsPos = [self.scan_accdistance, self.gate_high]
self.psoBoundsNeg = [self.scan_accdistance + self.gate_low, self.gate_high]
if self.scan_repmode in ("negpos", "NegPos"):
self.psoBoundsPos.append(self.acc_dist + self.gate_low)
self.psoBoundsNeg.append(self.acc_dist)
for ii in range(self.scan_repnum // 2):
self.psoBoundsPos += [self.gate_high, self.gate_low]
self.psoBoundsNeg += [self.gate_high, self.gate_low]
self.psoBoundsPos[-1] = 10* (self.acc_dist+self.gate_low)
self.psoBoundsNeg[-1] = 10* (self.acc_dist+self.gate_low)
self.psoBoundsNeg = [self.scan_accdistance, self.gate_high]
self.psoBoundsPos = [self.scan_accdistance + self.gate_low, self.gate_high]
self.filesubs['psoBoundsPos'] = self.psoBoundsPos
self.filesubs['psoBoundsNeg'] = self.psoBoundsNeg
self.filesubs['psoBoundsPosSize'] = len(self.psoBoundsPos)
self.filesubs['psoBoundsNegSize'] = len(self.psoBoundsNeg)
# Call super() to do the substitutions
yield from super().prepare_positions()
+6 -46
View File
@@ -24,7 +24,7 @@ def demostepscan(scan_start, scan_end, steps, exp_time=0.005, burst_at_each_poin
scan_ntotal = burst_at_each_point * (steps + 1)
# Move to start position
t_modes = {'event': 1, 'pso': 2, 'inp0': 3, 'inp1': 1}
t_modes = {'pso': 0, 'event': 1, 'inp0': 2, 'inp1': 4}
cfg = {'ntotal': scan_ntotal, 'trigger': t_modes[sync]}
dev.es1_ddaq.configure(d=cfg)
# Configure gigafrost
@@ -50,62 +50,22 @@ def demostepscan(scan_start, scan_end, steps, exp_time=0.005, burst_at_each_poin
def demosequencescan(scan_start, gate_high, gate_low, repeats=1, repmode="PosNeg",
exp_time=0.005, exp_frames=180, sync='pso'):
""" Demo sequence scan with GigaFrost
This is a small BEC user-space sequence scan at the microXAS testbench
triggering the gigafrost in gate-enable mode. It tries to do everything
through BEC, so while still setting up the environment.
triggering a customized scripted scan on the controller. The scan uses
a pre-written custom low-level sequence scan, so it is really minimal.
NOTE: It's not exactlythe same as the AeroScript template version.
NOTE: It calls the AeroScript template version.
Example:
--------
demostepscan(scan_start=-32, scan_end=148, steps=180, exp_time=0.005, burst_at_each_point=5)
>>> demosequencescan(33, 180, 180, exp_time=0.005, exp_frames=1800, repeats=10)
"""
if not bl_check_beam():
raise RuntimeError("Beamline is not in ready state")
# Synthetic values
scan_velocity = gate_high / (exp_time * exp_frames)
scan_acceleration = 500
scan_safedistance = 10
scan_accdistance = scan_safedistance + 0.5* scan_velocity * scan_velocity / scan_acceleration
scan_ntotal = exp_frames * repeats
# Move to start position
t_modes = {'event': 1, 'pso': 2, 'inp0': 3, 'inp1': 1}
cfg = {'ntotal': scan_ntotal, 'trigger': t_modes[sync]}
dev.es1_ddaq.configure(d=cfg)
# Configure gigafrost
cfg = {
"ntotal": scan_ntotal, "nimages": exp_frames,
"exposure": 1000*exp_time, "period": 2000*exp_time}
dev.gfclient.configure(d=cfg)
# Fill PSO vectors according to scan direction
psoBounds = []
if repmode in ("pos", "Pos"):
psoBounds.append(scan_accdistance)
for ii in range(repeats):
psoBounds += [gate_high, gate_low]
psoBounds[-1] = 10* (scan_accdistance+gate_low)
dev.es1_psod.configure(d={'distance': psoBounds, 'wmode': 'toggle'})
# Explicitly arm trigger (and detector in future)
dev.es1_psod.prepare()
print("Handing over to 'scans.line_scan'")
wait_time = 0.1 + 2*exp_time * burst_at_each_point
scans.line_scan(
dev.es1_roty, scan_start, scan_end,
steps=steps, exp_time=wait_time, relative=False, settling_time=settling_time)
# Cleanup: disable SW trigger
dev.es1_psod.software_trigger = False
scans.sequencescan(scan_start, gate_high, gate_low, exp_time=exp_time, exp_frames=exp_frames, repeats=repeats, repmode=repmode)