This commit is contained in:
mohacsi_i 2024-03-12 10:56:30 +01:00
parent 7baf9ec118
commit 4b5a270071
2 changed files with 828 additions and 570 deletions

View File

@ -8,67 +8,109 @@ import time
try:
from .AerotechAutomation1Enums import *
from .AerotechAutomation1Enums import (DataCollectionMode, DataCollectionFrequency,
AxisDataSignal, PsoWindowInput, DriveDataCaptureInput, DriveDataCaptureTrigger,
TaskDataSignal, SystemDataSignal, TomcatSequencerState)
from .AerotechAutomation1Enums import (
DataCollectionMode,
DataCollectionFrequency,
AxisDataSignal,
PsoWindowInput,
DriveDataCaptureInput,
DriveDataCaptureTrigger,
TaskDataSignal,
SystemDataSignal,
TomcatSequencerState,
)
except:
from AerotechAutomation1Enums import *
from AerotechAutomation1Enums import (DataCollectionMode, DataCollectionFrequency,
AxisDataSignal, PsoWindowInput, DriveDataCaptureInput, DriveDataCaptureTrigger,
TaskDataSignal, SystemDataSignal, TomcatSequencerState)
from AerotechAutomation1Enums import (
DataCollectionMode,
DataCollectionFrequency,
AxisDataSignal,
PsoWindowInput,
DriveDataCaptureInput,
DriveDataCaptureTrigger,
TaskDataSignal,
SystemDataSignal,
TomcatSequencerState,
)
from typing import Union
from collections import OrderedDict
class EpicsMotorX(EpicsMotor):
""" Special motor class that provides flyer interface and progress bar.
"""
SUB_PROGRESS = "progress"
def __init__(self, prefix="", *, name, kind=None, read_attrs=None, configuration_attrs=None, parent=None, **kwargs):
super().__init__(prefix=prefix, name=name, kind=kind, read_attrs=read_attrs, configuration_attrs=configuration_attrs, parent=parent, **kwargs)
def __init__(
self,
prefix="",
*,
name,
kind=None,
read_attrs=None,
configuration_attrs=None,
parent=None,
**kwargs,
):
super().__init__(
prefix=prefix,
name=name,
kind=kind,
read_attrs=read_attrs,
configuration_attrs=configuration_attrs,
parent=parent,
**kwargs,
)
self._startPosition = None
self._targetPosition = None
self.subscribe(self._progress_update, run=False)
def configure(self, d: dict):
if "target" in d:
self._targetPosition = d['target']
del d['target']
self._targetPosition = d["target"]
del d["target"]
if "position" in d:
self._targetPosition = d['position']
del d['position']
self._targetPosition = d["position"]
del d["position"]
return super().configure(d)
def kickoff(self):
self._startPosition = float( self.position)
self._startPosition = float(self.position)
return self.move(self._targetPosition, wait=False)
def move(self, position, wait=True, **kwargs):
self._startPosition = float( self.position)
self._startPosition = float(self.position)
return super().move(position, wait, **kwargs)
def _progress_update(self, value, **kwargs) -> None:
"""Progress update on the scan"""
if (self._startPosition is None) or (self._targetPosition is None) or (not self.moving):
self._run_subs( sub_type=self.SUB_PROGRESS, value=1, max_value=1, done=1, )
self._run_subs(
sub_type=self.SUB_PROGRESS, value=1, max_value=1, done=1,
)
return
progress = np.abs( (value-self._startPosition)/(self._targetPosition-self._startPosition) )
progress = np.abs(
(value - self._startPosition) / (self._targetPosition - self._startPosition)
)
max_value = 100
self._run_subs(
sub_type=self.SUB_PROGRESS,
value=int(100*progress), max_value=max_value, done=int(np.isclose(max_value, progress, 1e-3)), )
value=int(100 * progress),
max_value=max_value,
done=int(np.isclose(max_value, progress, 1e-3)),
)
class EpicsPassiveRO(EpicsSignalRO):
""" Small helper class to read PVs that need to be processed first.
"""
def __init__(self, read_pv, *, string=False, name=None, **kwargs):
super().__init__(read_pv, string=string, name=name, **kwargs)
self._proc = EpicsSignal(read_pv+".PROC", kind=Kind.omitted, put_complete=True)
self._proc = EpicsSignal(read_pv + ".PROC", kind=Kind.omitted, put_complete=True)
def wait_for_connection(self, *args, **kwargs):
super().wait_for_connection(*args, **kwargs)
@ -83,10 +125,9 @@ class EpicsPassiveRO(EpicsSignalRO):
return super().value
class aa1Controller(Device):
"""Ophyd proxy class for the Aerotech Automation 1's core controller functionality"""
controllername = Component(EpicsSignalRO, "NAME", kind=Kind.config)
serialnumber = Component(EpicsSignalRO, "SN", kind=Kind.config)
apiversion = Component(EpicsSignalRO, "API_VERSION", kind=Kind.config)
@ -94,8 +135,28 @@ class aa1Controller(Device):
taskcount = Component(EpicsSignalRO, "TASKCOUNT", kind=Kind.config)
fastpoll = Component(EpicsSignalRO, "POLLTIME", auto_monitor=True, kind=Kind.hinted)
slowpoll = Component(EpicsSignalRO, "DRVPOLLTIME", auto_monitor=True, kind=Kind.hinted)
def __init__(self, prefix="", *, name, kind=None, read_attrs=None, configuration_attrs=None, parent=None, **kwargs):
super().__init__(prefix=prefix, name=name, kind=kind, read_attrs=read_attrs, configuration_attrs=configuration_attrs, parent=parent, **kwargs)
def __init__(
self,
prefix="",
*,
name,
kind=None,
read_attrs=None,
configuration_attrs=None,
parent=None,
**kwargs,
):
super().__init__(
prefix=prefix,
name=name,
kind=kind,
read_attrs=read_attrs,
configuration_attrs=configuration_attrs,
parent=parent,
**kwargs,
)
class aa1Tasks(Device):
""" Task management API
@ -127,6 +188,7 @@ class aa1Tasks(Device):
'''
"""
SUB_PROGRESS = "progress"
_failure = Component(EpicsSignalRO, "FAILURE", auto_monitor=True, kind=Kind.hinted)
errStatus = Component(EpicsSignalRO, "ERRW", auto_monitor=True, kind=Kind.hinted)
@ -134,17 +196,37 @@ class aa1Tasks(Device):
taskStates = Component(EpicsSignalRO, "STATES-RBV", auto_monitor=True, kind=Kind.hinted)
taskIndex = Component(EpicsSignal, "TASKIDX", kind=Kind.config, put_complete=True)
switch = Component(EpicsSignal, "SWITCH", kind=Kind.config, put_complete=True)
_execute = Component(EpicsSignal, "EXECUTE", string=True, kind=Kind.config, put_complete=True)
_executeMode = Component(EpicsSignal, "EXECUTE-MODE", kind=Kind.config, put_complete=True)
_execute = Component(EpicsSignal, "EXECUTE", string=True, kind=Kind.config, put_complete=True)
_executeMode = Component(EpicsSignal, "EXECUTE-MODE", kind=Kind.config, put_complete=True)
_executeReply = Component(EpicsSignalRO, "EXECUTE_RBV", string=True, auto_monitor=True)
fileName = Component(EpicsSignal, "FILENAME", string=True, kind=Kind.omitted, put_complete=True)
_fileRead = Component(EpicsPassiveRO, "FILEREAD", string=True, kind=Kind.omitted)
_fileWrite = Component(EpicsSignal, "FILEWRITE", string=True, kind=Kind.omitted, put_complete=True)
_fileWrite = Component(
EpicsSignal, "FILEWRITE", string=True, kind=Kind.omitted, put_complete=True
)
def __init__(self, prefix="", *, name, kind=None, read_attrs=None, configuration_attrs=None, parent=None, **kwargs):
def __init__(
self,
prefix="",
*,
name,
kind=None,
read_attrs=None,
configuration_attrs=None,
parent=None,
**kwargs,
):
""" __init__ MUST have a full argument list"""
super().__init__(prefix=prefix, name=name, kind=kind, read_attrs=read_attrs, configuration_attrs=configuration_attrs, parent=parent, **kwargs)
super().__init__(
prefix=prefix,
name=name,
kind=kind,
read_attrs=read_attrs,
configuration_attrs=configuration_attrs,
parent=parent,
**kwargs,
)
self._currentTask = None
self._textToExecute = None
self._isConfigured = False
@ -154,7 +236,9 @@ class aa1Tasks(Device):
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, )
self._run_subs(
sub_type=self.SUB_PROGRESS, value=value, max_value=1, done=1,
)
def _progress(self) -> None:
"""Progress update on the scan"""
@ -172,7 +256,7 @@ class aa1Tasks(Device):
self.fileName.set(filename).wait()
filebytes = self._fileRead.get()
# C-strings terminate with trailing zero
if filebytes[-1]==0:
if filebytes[-1] == 0:
filebytes = filebytes[:-1]
filetext = filebytes
return filetext
@ -182,19 +266,19 @@ class aa1Tasks(Device):
self.fileName.set(filename).wait()
self._fileWrite.set(filetext).wait()
def runScript(self, filename: str, taskIndex: int==2, filetext=None, settle_time=0.5) -> None:
def runScript(self, filename: str, taskIndex: int == 2, filetext=None, settle_time=0.5) -> None:
""" Run a script file that either exists, or is newly created and compiled"""
self.configure({'text': filetext, 'filename': filename, 'taskIndex': taskIndex})
self.configure({"text": filetext, "filename": filename, "taskIndex": taskIndex})
print("Runscript configured")
self.trigger().wait()
print("Runscript waited")
def execute(self, text: str, taskIndex: int=3, mode: str=0, settle_time=0.5):
def execute(self, text: str, taskIndex: int = 3, mode: str = 0, settle_time=0.5):
""" Run a short text command on the Automation1 controller"""
print(f"Executing program on task: {taskIndex}")
self.configure({'text': text, 'taskIndex': taskIndex, 'mode': mode})
self.configure({"text": text, "taskIndex": taskIndex, "mode": mode})
self.kickoff().wait()
if mode in [0, "None", None]:
@ -203,16 +287,16 @@ class aa1Tasks(Device):
raw = self._executeReply.get()
return raw
def configure(self, d: dict={}) -> tuple:
def configure(self, d: dict = {}) -> tuple:
""" Configuration interface for flying
"""
# Unrolling the configuration dict
text = str(d['text']) if 'text' in d else None
filename = str(d['filename']) if 'filename' in d else None
taskIndex = int(d['taskIndex']) if 'taskIndex' in d else 4
settle_time = float(d['settle_time']) if 'settle_time' in d else None
mode = d['mode'] if 'mode' in d else None
self._isStepConfig = d['stepper'] if 'stepper' in d else False
text = str(d["text"]) if "text" in d else None
filename = str(d["filename"]) if "filename" in d else None
taskIndex = int(d["taskIndex"]) if "taskIndex" in d else 4
settle_time = float(d["settle_time"]) if "settle_time" in d else None
mode = d["mode"] if "mode" in d else None
self._isStepConfig = d["stepper"] if "stepper" in d else False
# Validation
if taskIndex < 1 or taskIndex > 31:
@ -302,6 +386,7 @@ class aa1Tasks(Device):
print("Called aa1Task.complete()")
timestamp_ = 0
taskIdx = int(self.taskIndex.get())
def notRunning2(*args, old_value, value, timestamp, **kwargs):
nonlocal timestamp_
result = False if value[taskIdx] in ["Running", 4] else True
@ -315,7 +400,14 @@ class aa1Tasks(Device):
def describe_collect(self) -> 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,
}
return {self.name: dd}
def collect(self) -> OrderedDict:
@ -331,6 +423,7 @@ class aa1TaskState(Device):
This is the task state monitoring interface for Automation1 tasks. It
does not launch execution, but can wait for the execution to complete.
"""
index = Component(EpicsSignalRO, "INDEX", kind=Kind.config)
status = Component(EpicsSignalRO, "STATUS", auto_monitor=True, kind=Kind.hinted)
errorCode = Component(EpicsSignalRO, "ERROR", auto_monitor=True, kind=Kind.hinted)
@ -341,9 +434,10 @@ class aa1TaskState(Device):
print("Called aa1TaskState.complete()")
# Define wait until the busy flag goes down (excluding initial update)
timestamp_ = 0
def notRunning(*args, old_value, value, timestamp, **kwargs):
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
print(result)
return result
@ -359,7 +453,14 @@ class aa1TaskState(Device):
def describe_collect(self) -> 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,
}
return dd
def collect(self) -> OrderedDict:
@ -381,14 +482,15 @@ class aa1DataAcquisition(Device):
3. Start your data collection
4. Read back the recorded data with "readback"
"""
# Status monitoring
status = Component(EpicsSignalRO, "RUNNING", auto_monitor=True, kind=Kind.hinted)
points_max = Component(EpicsSignal, "MAXPOINTS", kind=Kind.config, put_complete=True)
signal_num = Component(EpicsSignalRO, "NITEMS", kind=Kind.config)
points_max = Component(EpicsSignal, "MAXPOINTS", kind=Kind.config, put_complete=True)
signal_num = Component(EpicsSignalRO, "NITEMS", kind=Kind.config)
points_total = Component(EpicsSignalRO, "NTOTAL", auto_monitor=True, kind=Kind.hinted)
points_collected = Component(EpicsSignalRO, "NCOLLECTED", auto_monitor=True, kind=Kind.hinted)
points_retrieved= Component(EpicsSignalRO, "NRETRIEVED", auto_monitor=True, kind=Kind.hinted)
points_retrieved = Component(EpicsSignalRO, "NRETRIEVED", auto_monitor=True, kind=Kind.hinted)
overflow = Component(EpicsSignalRO, "OVERFLOW", auto_monitor=True, kind=Kind.hinted)
runmode = Component(EpicsSignalRO, "MODE_RBV", auto_monitor=True, kind=Kind.hinted)
# DAQ setup
@ -448,7 +550,7 @@ class aa1DataAcquisition(Device):
self._switch.set("START").wait()
# Wait for finishing acquisition
# Note: this is very bad blocking sleep
while self.status.value!=0:
while self.status.value != 0:
sleep(0.1)
sleep(0.1)
@ -456,7 +558,7 @@ class aa1DataAcquisition(Device):
data = self.data_rb.get()
rows = self.data_rows.get()
cols = self.data_cols.get()
if len(data)==0 or rows==0 or cols==0:
if len(data) == 0 or rows == 0 or cols == 0:
sleep(0.5)
data = self.data_rb.get()
rows = self.data_rows.get()
@ -476,7 +578,7 @@ class aa1DataAcquisition(Device):
data = self.data_rb.get()
rows = self.data_rows.get()
cols = self.data_cols.get()
if len(data)==0 or rows==0 or cols==0:
if len(data) == 0 or rows == 0 or cols == 0:
sleep(0.2)
data = self.data_rb.get()
rows = self.data_rows.get()
@ -486,7 +588,6 @@ class aa1DataAcquisition(Device):
return data
class aa1GlobalVariables(Device):
""" Global variables
@ -505,10 +606,11 @@ class aa1GlobalVariables(Device):
ret_arr = var.readFloat(1000, 1024)
"""
# Status monitoring
num_real = Component(EpicsSignalRO, "NUM-REAL_RBV", kind=Kind.config)
num_int = Component(EpicsSignalRO, "NUM-INT_RBV", kind=Kind.config)
num_string = Component(EpicsSignalRO, "NUM-STRING_RBV", kind=Kind.config)
num_int = Component(EpicsSignalRO, "NUM-INT_RBV", kind=Kind.config)
num_string = Component(EpicsSignalRO, "NUM-STRING_RBV", kind=Kind.config)
integer_addr = Component(EpicsSignal, "INT-ADDR", kind=Kind.omitted, put_complete=True)
integer_size = Component(EpicsSignal, "INT-SIZE", kind=Kind.omitted, put_complete=True)
@ -528,7 +630,7 @@ class aa1GlobalVariables(Device):
string = Component(EpicsSignal, "STRING", string=True, kind=Kind.omitted, put_complete=True)
string_rb = Component(EpicsPassiveRO, "STRING-RBV", string=True, kind=Kind.omitted)
def readInt(self, address: int, size: int=None) -> int:
def readInt(self, address: int, size: int = None) -> int:
""" Read a 64-bit integer global variable """
if address > self.num_int.get():
raise RuntimeError("Integer address {address} is out of range")
@ -559,8 +661,7 @@ class aa1GlobalVariables(Device):
else:
raise RuntimeError("Unsupported integer value type: {type(value)}")
def readFloat(self, address: int, size: int=None) -> float:
def readFloat(self, address: int, size: int = None) -> float:
""" Read a 64-bit double global variable """
if address > self.num_real.get():
raise RuntimeError("Floating point address {address} is out of range")
@ -613,7 +714,6 @@ class aa1GlobalVariables(Device):
raise RuntimeError("Unsupported string value type: {type(value)}")
class aa1GlobalVariableBindings(Device):
""" Polled global variables
@ -621,30 +721,124 @@ class aa1GlobalVariableBindings(Device):
on the Automation1 controller. These variables are continuously polled
and are thus a convenient way to interface scripts with the outside word.
"""
int0 = Component(EpicsSignalRO, "INT0_RBV", auto_monitor=True, name="int0", kind=Kind.hinted)
int1 = Component(EpicsSignalRO, "INT1_RBV", auto_monitor=True, name="int1", kind=Kind.hinted)
int2 = Component(EpicsSignalRO, "INT2_RBV", auto_monitor=True, name="int2", kind=Kind.hinted)
int3 = Component(EpicsSignalRO, "INT3_RBV", auto_monitor=True, name="int3", kind=Kind.hinted)
int8 = Component(EpicsSignal, "INT8_RBV", put_complete=True, write_pv="INT8", auto_monitor=True, name="int8", kind=Kind.hinted)
int9 = Component(EpicsSignal, "INT9_RBV", put_complete=True, write_pv="INT9", auto_monitor=True, name="int9", kind=Kind.hinted)
int10 = Component(EpicsSignal, "INT10_RBV", put_complete=True, write_pv="INT10", auto_monitor=True, name="int10", kind=Kind.hinted)
int11 = Component(EpicsSignal, "INT11_RBV", put_complete=True, write_pv="INT11", auto_monitor=True, name="int11", kind=Kind.hinted)
int8 = Component(
EpicsSignal,
"INT8_RBV",
put_complete=True,
write_pv="INT8",
auto_monitor=True,
name="int8",
kind=Kind.hinted,
)
int9 = Component(
EpicsSignal,
"INT9_RBV",
put_complete=True,
write_pv="INT9",
auto_monitor=True,
name="int9",
kind=Kind.hinted,
)
int10 = Component(
EpicsSignal,
"INT10_RBV",
put_complete=True,
write_pv="INT10",
auto_monitor=True,
name="int10",
kind=Kind.hinted,
)
int11 = Component(
EpicsSignal,
"INT11_RBV",
put_complete=True,
write_pv="INT11",
auto_monitor=True,
name="int11",
kind=Kind.hinted,
)
float0 = Component(EpicsSignalRO, "REAL0_RBV", auto_monitor=True, name="float0", kind=Kind.hinted)
float1 = Component(EpicsSignalRO, "REAL1_RBV", auto_monitor=True, name="float1", kind=Kind.hinted)
float2 = Component(EpicsSignalRO, "REAL2_RBV", auto_monitor=True, name="float2", kind=Kind.hinted)
float3 = Component(EpicsSignalRO, "REAL3_RBV", auto_monitor=True, name="float3", kind=Kind.hinted)
float16 = Component(EpicsSignal, "REAL16_RBV", write_pv="REAL16", put_complete=True, auto_monitor=True, name="float16", kind=Kind.hinted)
float17 = Component(EpicsSignal, "REAL17_RBV", write_pv="REAL17", put_complete=True, auto_monitor=True, name="float17", kind=Kind.hinted)
float18 = Component(EpicsSignal, "REAL18_RBV", write_pv="REAL18", put_complete=True, auto_monitor=True, name="float18", kind=Kind.hinted)
float19 = Component(EpicsSignal, "REAL19_RBV", write_pv="REAL19", put_complete=True, auto_monitor=True, name="float19", kind=Kind.hinted)
float0 = Component(
EpicsSignalRO, "REAL0_RBV", auto_monitor=True, name="float0", kind=Kind.hinted
)
float1 = Component(
EpicsSignalRO, "REAL1_RBV", auto_monitor=True, name="float1", kind=Kind.hinted
)
float2 = Component(
EpicsSignalRO, "REAL2_RBV", auto_monitor=True, name="float2", kind=Kind.hinted
)
float3 = Component(
EpicsSignalRO, "REAL3_RBV", auto_monitor=True, name="float3", kind=Kind.hinted
)
float16 = Component(
EpicsSignal,
"REAL16_RBV",
write_pv="REAL16",
put_complete=True,
auto_monitor=True,
name="float16",
kind=Kind.hinted,
)
float17 = Component(
EpicsSignal,
"REAL17_RBV",
write_pv="REAL17",
put_complete=True,
auto_monitor=True,
name="float17",
kind=Kind.hinted,
)
float18 = Component(
EpicsSignal,
"REAL18_RBV",
write_pv="REAL18",
put_complete=True,
auto_monitor=True,
name="float18",
kind=Kind.hinted,
)
float19 = Component(
EpicsSignal,
"REAL19_RBV",
write_pv="REAL19",
put_complete=True,
auto_monitor=True,
name="float19",
kind=Kind.hinted,
)
# BEC LiveTable crashes on non-numeric values
str0 = Component(EpicsSignalRO, "STR0_RBV", auto_monitor=True, string=True, name="str0", kind=Kind.config)
str1 = Component(EpicsSignalRO, "STR1_RBV", auto_monitor=True, string=True, name="str1", kind=Kind.config)
str4 = Component(EpicsSignal, "STR4_RBV", put_complete=True, string=True, auto_monitor=True, write_pv="STR4", name="str4", kind=Kind.config)
str5 = Component(EpicsSignal, "STR5_RBV", put_complete=True, string=True, auto_monitor=True, write_pv="STR5", name="str5", kind=Kind.config)
str0 = Component(
EpicsSignalRO, "STR0_RBV", auto_monitor=True, string=True, name="str0", kind=Kind.config
)
str1 = Component(
EpicsSignalRO, "STR1_RBV", auto_monitor=True, string=True, name="str1", kind=Kind.config
)
str4 = Component(
EpicsSignal,
"STR4_RBV",
put_complete=True,
string=True,
auto_monitor=True,
write_pv="STR4",
name="str4",
kind=Kind.config,
)
str5 = Component(
EpicsSignal,
"STR5_RBV",
put_complete=True,
string=True,
auto_monitor=True,
write_pv="STR5",
name="str5",
kind=Kind.config,
)
class aa1AxisIo(Device):
@ -655,6 +849,7 @@ class aa1AxisIo(Device):
should be done in AeroScript. Only one pin can be writen directly but
several can be polled!
"""
polllvl = Component(EpicsSignal, "POLLLVL", put_complete=True, kind=Kind.config)
ai0 = Component(EpicsSignalRO, "AI0-RBV", auto_monitor=True, kind=Kind.hinted)
ai1 = Component(EpicsSignalRO, "AI1-RBV", auto_monitor=True, kind=Kind.hinted)
@ -692,7 +887,6 @@ class aa1AxisIo(Device):
self.do.set(value, settle_time=settle_time).wait()
class aa1AxisPsoBase(Device):
""" Position Sensitive Output - Base class
@ -708,23 +902,26 @@ class aa1AxisPsoBase(Device):
Specific operation modes should be implemented in child classes.
"""
# ########################################################################
# General module status
status = Component(EpicsSignalRO, "STATUS", auto_monitor=True, kind=Kind.hinted)
output = Component(EpicsSignalRO, "OUTPUT-RBV", auto_monitor=True, kind=Kind.hinted)
_eventSingle = Component(EpicsSignal, "EVENT:SINGLE", put_complete=True, kind=Kind.omitted)
_eventSingle = Component(EpicsSignal, "EVENT:SINGLE", put_complete=True, kind=Kind.omitted)
_reset = Component(EpicsSignal, "RESET", put_complete=True, kind=Kind.omitted)
posInput = Component(EpicsSignal, "DIST:INPUT", put_complete=True, kind=Kind.omitted)
posInput = Component(EpicsSignal, "DIST:INPUT", put_complete=True, kind=Kind.omitted)
# ########################################################################
# PSO Distance event module
dstEventsEna = Component(EpicsSignal, "DIST:EVENTS", put_complete=True, kind=Kind.omitted)
dstEventsEna = Component(EpicsSignal, "DIST:EVENTS", put_complete=True, kind=Kind.omitted)
dstCounterEna = Component(EpicsSignal, "DIST:COUNTER", put_complete=True, kind=Kind.omitted)
dstCounterVal = Component(EpicsSignalRO, "DIST:CTR0_RBV", auto_monitor=True, kind=Kind.hinted)
dstArrayIdx = Component(EpicsSignalRO, "DIST:IDX_RBV", auto_monitor=True, kind=Kind.hinted)
dstArrayDepleted = Component(EpicsSignalRO, "DIST:ARRAY-DEPLETED-RBV", auto_monitor=True, kind=Kind.hinted)
dstArrayDepleted = Component(
EpicsSignalRO, "DIST:ARRAY-DEPLETED-RBV", auto_monitor=True, kind=Kind.hinted
)
dstDirection = Component(EpicsSignal, "DIST:EVENTDIR", put_complete=True, kind=Kind.omitted)
dstDirection = Component(EpicsSignal, "DIST:EVENTDIR", put_complete=True, kind=Kind.omitted)
dstDistance = Component(EpicsSignal, "DIST:DISTANCE", put_complete=True, kind=Kind.hinted)
dstDistanceArr = Component(EpicsSignal, "DIST:DISTANCES", put_complete=True, kind=Kind.omitted)
dstArrayRearm = Component(EpicsSignal, "DIST:REARM-ARRAY", put_complete=True, kind=Kind.omitted)
@ -742,10 +939,10 @@ class aa1AxisPsoBase(Device):
# PSO waveform module
waveEnable = Component(EpicsSignal, "WAVE:ENABLE", put_complete=True, kind=Kind.omitted)
waveMode = Component(EpicsSignal, "WAVE:MODE", put_complete=True, kind=Kind.omitted)
#waveDelay = Component(EpicsSignal, "WAVE:DELAY", put_complete=True, kind=Kind.omitted)
# waveDelay = Component(EpicsSignal, "WAVE:DELAY", put_complete=True, kind=Kind.omitted)
# PSO waveform pulse output
#pulseTrunc = Component(EpicsSignal, "WAVE:PULSE:TRUNC", put_complete=True, kind=Kind.omitted)
# pulseTrunc = Component(EpicsSignal, "WAVE:PULSE:TRUNC", put_complete=True, kind=Kind.omitted)
pulseOnTime = Component(EpicsSignal, "WAVE:PULSE:ONTIME", put_complete=True, kind=Kind.omitted)
pulseWindow = Component(EpicsSignal, "WAVE:PULSE:PERIOD", put_complete=True, kind=Kind.omitted)
pulseCount = Component(EpicsSignal, "WAVE:PULSE:COUNT", put_complete=True, kind=Kind.omitted)
@ -767,9 +964,6 @@ class aa1AxisPsoBase(Device):
self.waveMode.set(orig_waveMode).wait()
class aa1AxisPsoDistance(aa1AxisPsoBase):
""" Position Sensitive Output - Distance mode
@ -802,11 +996,30 @@ class aa1AxisPsoDistance(aa1AxisPsoBase):
pso.configure(d={'distance': 1.8, 'wmode': "pulsed", 'n_pulse': 5})
pso.kickoff().wait()
"""
SUB_PROGRESS = "progress"
def __init__(self, prefix="", *, name, kind=None, read_attrs=None, configuration_attrs=None, parent=None, **kwargs):
def __init__(
self,
prefix="",
*,
name,
kind=None,
read_attrs=None,
configuration_attrs=None,
parent=None,
**kwargs,
):
""" __init__ MUST have a full argument list"""
super().__init__(prefix=prefix, name=name, kind=kind, read_attrs=read_attrs, configuration_attrs=configuration_attrs, parent=parent, **kwargs)
super().__init__(
prefix=prefix,
name=name,
kind=kind,
read_attrs=read_attrs,
configuration_attrs=configuration_attrs,
parent=parent,
**kwargs,
)
self._Vdistance = 3.141592
self.subscribe(self._progress_update, "progress", run=False)
@ -814,7 +1027,9 @@ class aa1AxisPsoDistance(aa1AxisPsoBase):
"""Progress update on the scan"""
if self.dstArrayDepleted.value:
print("PSO array depleted")
self._run_subs( sub_type=self.SUB_PROGRESS, value=1, max_value=1, done=1, )
self._run_subs(
sub_type=self.SUB_PROGRESS, value=1, max_value=1, done=1,
)
return
progress = 1
@ -822,23 +1037,25 @@ class aa1AxisPsoDistance(aa1AxisPsoBase):
print(f"PSO array proggress: {progress}")
self._run_subs(
sub_type=self.SUB_PROGRESS,
value=int(progress), max_value=max_value, done=int(np.isclose(max_value, progress, 1e-3)), )
value=int(progress),
max_value=max_value,
done=int(np.isclose(max_value, progress, 1e-3)),
)
# ########################################################################
# PSO high level interface
def configure(self, d: dict={}) -> tuple:
def configure(self, d: dict = {}) -> tuple:
""" Simplified configuration interface to access the most common
functionality for distance mode PSO.
:param distance: The trigger distance or the array of distances between subsequent points.
:param wmode: Waveform mode configuration, usually pulsed/toggled.
"""
distance = d['distance']
wmode = str(d['wmode'])
t_pulse = float(d['t_pulse']) if 't_pulse' in d else 100
w_pulse = float(d['w_pulse']) if 'w_pulse' in d else 200
n_pulse = float(d['n_pulse']) if 'n_pulse' in d else 1
distance = d["distance"]
wmode = str(d["wmode"])
t_pulse = float(d["t_pulse"]) if "t_pulse" in d else 100
w_pulse = float(d["w_pulse"]) if "w_pulse" in d else 200
n_pulse = float(d["n_pulse"]) if "n_pulse" in d else 1
# Validate input parameters
if wmode not in ["pulse", "pulsed", "toggle", "toggled"]:
@ -896,7 +1113,7 @@ class aa1AxisPsoDistance(aa1AxisPsoBase):
def complete(self, settle_time=0.1) -> DeviceStatus:
""" DDC just reads back whatever is available in the buffers"""
sleep(settle_time)
status = DeviceStatus(self)
status = DeviceStatus(self)
status.set_finished()
return status
@ -908,11 +1125,14 @@ class aa1AxisPsoDistance(aa1AxisPsoBase):
self.dstEventsEna.set("Off").wait()
self.dstCounterEna.set("Off").wait()
return super().unstage()
# ########################################################################
# Bluesky flyer interface
def kickoff(self) -> DeviceStatus:
# Rearm the configured array
if hasattr(self, "_distanceValue") and isinstance(self._distanceValue, (np.ndarray, list, tuple)):
if hasattr(self, "_distanceValue") and isinstance(
self._distanceValue, (np.ndarray, list, tuple)
):
self.dstArrayRearm.set(1).wait()
# Start monitoring the counters
self.dstEventsEna.set("On").wait()
@ -925,18 +1145,21 @@ class aa1AxisPsoDistance(aa1AxisPsoBase):
def complete(self) -> DeviceStatus:
""" Bluesky flyer interface"""
# Array mode waits until the buffer is empty
if hasattr(self, "_distanceValue") and isinstance(self._distanceValue, (np.ndarray, list, tuple)):
if hasattr(self, "_distanceValue") and isinstance(
self._distanceValue, (np.ndarray, list, tuple)
):
# Define wait until the busy flag goes down (excluding initial update)
timestamp_ = 0
def notRunning(*args, old_value, value, timestamp, **kwargs):
nonlocal timestamp_
result = False if (timestamp_== 0) else bool(int(value) & 0x1000)
result = False if (timestamp_ == 0) else bool(int(value) & 0x1000)
print(f"Old {old_value}\tNew: {value}\tResult: {result}")
timestamp_ = timestamp
return result
# Subscribe and wait for update
#status = SubscriptionStatus(self.status, notRunning, settle_time=0.5)
# status = SubscriptionStatus(self.status, notRunning, settle_time=0.5)
# Data capture can be stopped any time
status = DeviceStatus(self)
status.set_finished()
@ -948,18 +1171,23 @@ class aa1AxisPsoDistance(aa1AxisPsoBase):
def describe_collect(self) -> OrderedDict:
ret = OrderedDict()
ret['index'] = {'source': "internal", 'dtype': 'integer', 'shape': [], 'units': '', 'lower_ctrl_limit': 0, 'upper_ctrl_limit': 0}
ret["index"] = {
"source": "internal",
"dtype": "integer",
"shape": [],
"units": "",
"lower_ctrl_limit": 0,
"upper_ctrl_limit": 0,
}
return {self.name: ret}
def collect(self) -> OrderedDict:
ret = OrderedDict()
ret["timestamps"] = {"index": time.time()}
ret["data"] = {"index": self.dstCounterVal.value }
ret["data"] = {"index": self.dstCounterVal.value}
yield ret
class aa1AxisPsoWindow(aa1AxisPsoBase):
""" Position Sensitive Output - Window mode
@ -979,27 +1207,46 @@ class aa1AxisPsoWindow(aa1AxisPsoBase):
For a more detailed description of additional signals and masking plase
refer to Automation1's online manual.
"""
def __init__(self, prefix="", *, name, kind=None, read_attrs=None, configuration_attrs=None, parent=None, **kwargs):
def __init__(
self,
prefix="",
*,
name,
kind=None,
read_attrs=None,
configuration_attrs=None,
parent=None,
**kwargs,
):
""" __init__ MUST have a full argument list"""
super().__init__(prefix=prefix, name=name, kind=kind, read_attrs=read_attrs, configuration_attrs=configuration_attrs, parent=parent, **kwargs)
super().__init__(
prefix=prefix,
name=name,
kind=kind,
read_attrs=read_attrs,
configuration_attrs=configuration_attrs,
parent=parent,
**kwargs,
)
self._mode = "output"
self._eventMode = "Enter"
# ########################################################################
# PSO high level interface
def configure(self, d: dict={}) -> tuple:
def configure(self, d: dict = {}) -> tuple:
""" Simplified configuration interface to access the most common
functionality for distance mode PSO.
:param distance: The trigger distance or the array of distances between subsequent points.
:param wmode: Waveform mode configuration, usually output/pulsed/toggled.
"""
bounds = d['distance']
wmode = str(d['wmode'])
emode = str(d['emode'])
t_pulse = float(d['t_pulse']) if 't_pulse' in d else None
w_pulse = float(d['w_pulse']) if 'w_pulse' in d else None
n_pulse = float(d['n_pulse']) if 'n_pulse' in d else None
bounds = d["distance"]
wmode = str(d["wmode"])
emode = str(d["emode"])
t_pulse = float(d["t_pulse"]) if "t_pulse" in d else None
w_pulse = float(d["w_pulse"]) if "w_pulse" in d else None
n_pulse = float(d["n_pulse"]) if "n_pulse" in d else None
# Validate input parameters
if wmode not in ["pulse", "pulsed", "toggle", "toggled", "output", "flag"]:
@ -1080,11 +1327,6 @@ class aa1AxisPsoWindow(aa1AxisPsoBase):
return super().unstage()
class aa1AxisDriveDataCollection(Device):
""" Axis data collection
@ -1125,29 +1367,50 @@ class aa1AxisDriveDataCollection(Device):
SUB_PROGRESS = "progress"
def __init__(self, prefix="", *, name, kind=None, read_attrs=None, configuration_attrs=None, parent=None, **kwargs):
super().__init__(prefix=prefix, name=name, kind=kind, read_attrs=read_attrs, configuration_attrs=configuration_attrs, parent=parent, **kwargs)
def __init__(
self,
prefix="",
*,
name,
kind=None,
read_attrs=None,
configuration_attrs=None,
parent=None,
**kwargs,
):
super().__init__(
prefix=prefix,
name=name,
kind=kind,
read_attrs=read_attrs,
configuration_attrs=configuration_attrs,
parent=parent,
**kwargs,
)
self.subscribe(self._progress_update, "progress", run=False)
def _progress_update(self, value, **kwargs) -> None:
"""Progress update on the scan"""
if self.state.value not in (2, "Acquiring"):
self._run_subs( sub_type=self.SUB_PROGRESS, value=1, max_value=1, done=1, )
self._run_subs(
sub_type=self.SUB_PROGRESS, value=1, max_value=1, done=1,
)
return
progress = 1
max_value = 1
self._run_subs(
sub_type=self.SUB_PROGRESS,
value=int(progress), max_value=max_value, done=int(np.isclose(max_value, progress, 1e-3)), )
value=int(progress),
max_value=max_value,
done=int(np.isclose(max_value, progress, 1e-3)),
)
def configure(self, d: dict={}) -> tuple:
npoints = int(d['npoints'])
trigger = int(d['trigger']) if 'trigger' in d else DriveDataCaptureTrigger.PsoOutput
source0 = int(d['source0']) if 'source0' in d else DriveDataCaptureInput.PrimaryFeedback
source1 = int(d['source1']) if 'source1' in d else DriveDataCaptureInput.PositionCommand
def configure(self, d: dict = {}) -> tuple:
npoints = int(d["npoints"])
trigger = int(d["trigger"]) if "trigger" in d else DriveDataCaptureTrigger.PsoOutput
source0 = int(d["source0"]) if "source0" in d else DriveDataCaptureInput.PrimaryFeedback
source1 = int(d["source1"]) if "source1" in d else DriveDataCaptureInput.PositionCommand
old = self.read_configuration()
@ -1180,7 +1443,7 @@ class aa1AxisDriveDataCollection(Device):
def complete(self, settle_time=0.1) -> DeviceStatus:
""" DDC just reads back whatever is available in the buffers"""
sleep(settle_time)
status = DeviceStatus(self)
status = DeviceStatus(self)
status.set_finished()
return status
@ -1194,17 +1457,18 @@ class aa1AxisDriveDataCollection(Device):
# Define wait until the busy flag goes down (excluding initial update)
timestamp_ = 0
def negEdge(*args, old_value, value, timestamp, **kwargs):
nonlocal timestamp_
result = False if (timestamp_== 0) else (old_value == 1 and value == 0)
# print(f"\nBuffer1 status:\t{old_value} ({timestamp_}) to {value} ({timestamp}) Result: {result}")
result = False if (timestamp_ == 0) else (old_value == 1 and value == 0)
# print(f"\nBuffer1 status:\t{old_value} ({timestamp_}) to {value} ({timestamp}) Result: {result}")
timestamp_ = timestamp
return result
if index==0:
if index == 0:
status = SubscriptionStatus(self._readstatus0, negEdge, settle_time=0.5)
self._readback0.set(1).wait()
elif index==1:
elif index == 1:
status = SubscriptionStatus(self._readstatus1, negEdge, settle_time=0.5)
self._readback1.set(1).wait()
@ -1212,11 +1476,24 @@ class aa1AxisDriveDataCollection(Device):
status.wait()
return status
def describe_collect(self) -> OrderedDict:
ret = OrderedDict()
ret['buffer0'] = {'source': "internal", 'dtype': 'array', 'shape': [], 'units': '', 'lower_ctrl_limit': 0, 'upper_ctrl_limit': 0}
ret['buffer1'] = {'source': "internal", 'dtype': 'array', 'shape': [], 'units': '', 'lower_ctrl_limit': 0, 'upper_ctrl_limit': 0}
ret["buffer0"] = {
"source": "internal",
"dtype": "array",
"shape": [],
"units": "",
"lower_ctrl_limit": 0,
"upper_ctrl_limit": 0,
}
ret["buffer1"] = {
"source": "internal",
"dtype": "array",
"shape": [],
"units": "",
"lower_ctrl_limit": 0,
"upper_ctrl_limit": 0,
}
return {self.name: ret}
def collect(self) -> OrderedDict:
@ -1227,29 +1504,23 @@ class aa1AxisDriveDataCollection(Device):
b0 = self._buffer0.value
b1 = self._buffer1.value
ret = OrderedDict()
ret["timestamps"] = {"buffer0": time.time(), "buffer1": time.time() }
ret["data"] = {"buffer0": b0, "buffer1": b1 }
ret["timestamps"] = {"buffer0": time.time(), "buffer1": time.time()}
ret["data"] = {"buffer0": b0, "buffer1": b1}
yield ret
# Automatically start simulation if directly invoked
if __name__ == "__main__":
AA1_IOC_NAME = "X02DA-ES1-SMP1"
AA1_AXIS_NAME = "ROTY"
# Drive data collection
task = aa1Tasks(AA1_IOC_NAME+":TASK:", name="tsk")
task = aa1Tasks(AA1_IOC_NAME + ":TASK:", name="tsk")
task.wait_for_connection()
task.describe()
ddc = aa1AxisDriveDataCollection("X02DA-ES1-SMP1:ROTY:DDC:", name="ddc")
ddc.wait_for_connection()
globb = aa1GlobalVariableBindings(AA1_IOC_NAME+":VAR:", name="globb")
globb = aa1GlobalVariableBindings(AA1_IOC_NAME + ":VAR:", name="globb")
globb.wait_for_connection()
globb.describe()
mot = EpicsMotor(AA1_IOC_NAME+ ":" + AA1_AXIS_NAME, name="x")
mot = EpicsMotor(AA1_IOC_NAME + ":" + AA1_AXIS_NAME, name="x")
mot.wait_for_connection()

View File

@ -272,232 +272,230 @@ class AxisDataSignal:
class TaskDataSignal:
ProgramLineNumber = 17
CoordinatedFlags = 40
CoordinatedArcStartAngle = 53
CoordinatedArcEndAngle = 54
CoordinatedArcRadius = 55
CoordinatedArcRadiusError = 56
CoordinatedPositionCommand = 57
CoordinatedSpeedCommand = 58
CoordinatedAccelerationCommand = 59
CoordinatedTotalDistance = 60
CoordinatedPercentDone = 61
CoordinatedPositionCommandBackwardsDiff = 62
TaskParameter = 69
TaskError = 70
TaskWarning = 71
CoordinatedSpeedTargetActual = 86
DependentCoordinatedSpeedTargetActual = 87
ActiveFixtureOffset = 88
TaskStatus0 = 90
TaskStatus1 = 91
TaskStatus2 = 92
SpindleSpeedTarget = 93
CoordinateSystem1I = 96
CoordinateSystem1J = 97
CoordinateSystem1K = 98
CoordinateSystem1Plane = 99
ToolNumberActive = 100
Mfo = 101
CoordinatedSpeedTarget = 102
DependentCoordinatedSpeedTarget = 103
CoordinatedAccelerationRate = 104
CoordinatedDecelerationRate = 105
CoordinatedAccelerationTime = 106
CoordinatedDecelerationTime = 107
TaskMode = 108
TaskState = 117
TaskStateInternal = 118
ExecutionMode = 121
EnableAlignmentAxes = 127
CoordinatedGalvoLaserOutput = 133
CoordinatedMotionRate = 145
CoordinatedTaskCommand = 146
EnableState = 166
LookaheadMovesExamined = 200
ProfileControlMask = 231
CoordinatedArcRadiusReciprocal = 253
MotionEngineStage = 254
CoordinatedTimeScale = 256
CoordinatedTimeScaleDerivative = 257
IfovSpeedScale = 266
IfovSpeedScaleAverage = 267
IfovGenerationFrameCounter = 268
IfovGenerationTimeOriginal = 269
IfovGenerationTimeModified = 270
IfovCoordinatedPositionCommand = 271
IfovCoordinatedSpeedCommand = 272
IfovCenterPointH = 276
IfovCenterPointV = 277
IfovTrajectoryCount = 278
IfovTrajectoryIndex = 279
IfovAttemptCode = 280
IfovGenerationFrameIndex = 281
IfovMaximumVelocity = 282
IfovIdealVelocity = 283
TaskInternalDebug = 284
IfovCoordinatedAccelerationCommand = 285
IfovFovPositionH = 286
IfovFovPositionV = 287
IfovFovDimensionH = 288
IfovFovDimensionV = 289
MotionBufferElements = 311
MotionBufferMoves = 312
MotionLineNumber = 313
MotionBufferRetraceMoves = 314
MotionBufferRetraceElements = 315
MotionBufferIndex = 316
MotionBufferIndexLookahead = 317
MotionBufferProcessingBlocked = 318
ActiveMoveValid = 319
TaskExecutionLines = 320
SchedulerTaskHolds = 321
SchedulerProgramLoopRuns = 322
SchedulerTaskBlocked = 323
CriticalSectionsActive = 324
AxesSlowdownReason = 331
TaskExecutionTime = 333
TaskExecutionTimeMaximum = 334
TaskExecutionLinesMaximum = 335
LookaheadDecelReason = 338
LookaheadDecelMoves = 339
LookaheadDecelDistance = 340
ProgramCounter = 341
StackPointer = 342
FramePointer = 343
StringStackPointer = 344
ProgramLineNumberSourceFileId = 349
MotionLineNumberSourceFileId = 350
ProgramLineNumberSourcePathId = 351
MotionLineNumberSourcePathId = 352
StringArgumentStackPointer = 354
CoordinatedAccelerationSCurvePercentage = 369
CoordinatedDecelerationSCurvePercentage = 370
DependentCoordinatedAccelerationRate = 373
DependentCoordinatedDecelerationRate = 374
CriticalSectionTimeout = 375
CommandQueueCapacity = 421
CommandQueueUnexecutedCount = 422
CommandQueueTimesEmptied = 423
CommandQueueExecutedCount = 424
ProgramLineNumber = 17
CoordinatedFlags = 40
CoordinatedArcStartAngle = 53
CoordinatedArcEndAngle = 54
CoordinatedArcRadius = 55
CoordinatedArcRadiusError = 56
CoordinatedPositionCommand = 57
CoordinatedSpeedCommand = 58
CoordinatedAccelerationCommand = 59
CoordinatedTotalDistance = 60
CoordinatedPercentDone = 61
CoordinatedPositionCommandBackwardsDiff = 62
TaskParameter = 69
TaskError = 70
TaskWarning = 71
CoordinatedSpeedTargetActual = 86
DependentCoordinatedSpeedTargetActual = 87
ActiveFixtureOffset = 88
TaskStatus0 = 90
TaskStatus1 = 91
TaskStatus2 = 92
SpindleSpeedTarget = 93
CoordinateSystem1I = 96
CoordinateSystem1J = 97
CoordinateSystem1K = 98
CoordinateSystem1Plane = 99
ToolNumberActive = 100
Mfo = 101
CoordinatedSpeedTarget = 102
DependentCoordinatedSpeedTarget = 103
CoordinatedAccelerationRate = 104
CoordinatedDecelerationRate = 105
CoordinatedAccelerationTime = 106
CoordinatedDecelerationTime = 107
TaskMode = 108
TaskState = 117
TaskStateInternal = 118
ExecutionMode = 121
EnableAlignmentAxes = 127
CoordinatedGalvoLaserOutput = 133
CoordinatedMotionRate = 145
CoordinatedTaskCommand = 146
EnableState = 166
LookaheadMovesExamined = 200
ProfileControlMask = 231
CoordinatedArcRadiusReciprocal = 253
MotionEngineStage = 254
CoordinatedTimeScale = 256
CoordinatedTimeScaleDerivative = 257
IfovSpeedScale = 266
IfovSpeedScaleAverage = 267
IfovGenerationFrameCounter = 268
IfovGenerationTimeOriginal = 269
IfovGenerationTimeModified = 270
IfovCoordinatedPositionCommand = 271
IfovCoordinatedSpeedCommand = 272
IfovCenterPointH = 276
IfovCenterPointV = 277
IfovTrajectoryCount = 278
IfovTrajectoryIndex = 279
IfovAttemptCode = 280
IfovGenerationFrameIndex = 281
IfovMaximumVelocity = 282
IfovIdealVelocity = 283
TaskInternalDebug = 284
IfovCoordinatedAccelerationCommand = 285
IfovFovPositionH = 286
IfovFovPositionV = 287
IfovFovDimensionH = 288
IfovFovDimensionV = 289
MotionBufferElements = 311
MotionBufferMoves = 312
MotionLineNumber = 313
MotionBufferRetraceMoves = 314
MotionBufferRetraceElements = 315
MotionBufferIndex = 316
MotionBufferIndexLookahead = 317
MotionBufferProcessingBlocked = 318
ActiveMoveValid = 319
TaskExecutionLines = 320
SchedulerTaskHolds = 321
SchedulerProgramLoopRuns = 322
SchedulerTaskBlocked = 323
CriticalSectionsActive = 324
AxesSlowdownReason = 331
TaskExecutionTime = 333
TaskExecutionTimeMaximum = 334
TaskExecutionLinesMaximum = 335
LookaheadDecelReason = 338
LookaheadDecelMoves = 339
LookaheadDecelDistance = 340
ProgramCounter = 341
StackPointer = 342
FramePointer = 343
StringStackPointer = 344
ProgramLineNumberSourceFileId = 349
MotionLineNumberSourceFileId = 350
ProgramLineNumberSourcePathId = 351
MotionLineNumberSourcePathId = 352
StringArgumentStackPointer = 354
CoordinatedAccelerationSCurvePercentage = 369
CoordinatedDecelerationSCurvePercentage = 370
DependentCoordinatedAccelerationRate = 373
DependentCoordinatedDecelerationRate = 374
CriticalSectionTimeout = 375
CommandQueueCapacity = 421
CommandQueueUnexecutedCount = 422
CommandQueueTimesEmptied = 423
CommandQueueExecutedCount = 424
class SystemDataSignal:
VirtualBinaryInput = 46
VirtualBinaryOutput = 47
VirtualRegisterInput = 48
VirtualRegisterOutput = 49
Timer = 51
TimerPerformance = 52
GlobalReal = 67
CommunicationRealTimeErrors = 81
LibraryCommand = 119
DataCollectionSampleTime = 120
DataCollectionSampleIndex = 129
ModbusClientConnected = 134
ModbusServerConnected = 135
ModbusClientError = 136
ModbusServerError = 137
StopWatchTimer = 157
ScopetrigId = 163
EstimatedProcessorUsage = 177
DataCollectionStatus = 188
SignalLogState = 198
SafeZoneViolationMask = 207
SafeZoneActiveMask = 229
ModbusClientInputWords = 240
ModbusClientOutputWords = 241
ModbusClientInputBits = 242
ModbusClientOutputBits = 243
ModbusClientOutputBitsStatus = 244
ModbusClientOutputWordsStatus = 245
ModbusServerInputWords = 246
ModbusServerOutputWords = 247
ModbusServerInputBits = 248
ModbusServerOutputBits = 249
SystemParameter = 265
ThermoCompSensorTemperature = 305
ThermoCompControllingTemperature = 306
ThermoCompCompensatingTemperature = 307
ThermoCompStatus = 308
GlobalInteger = 345
AliveAxesMask = 348
SignalLogPointsStored = 377
ControllerInitializationWarning = 379
StopWatchTimerMin = 416
StopWatchTimerMax = 417
StopWatchTimerAvg = 418
EthercatEnabled = 428
EthercatError = 429
EthercatTxPdo = 430
EthercatTxPdoSize = 431
EthercatRxPdo = 432
EthercatRxPdoSize = 433
EthercatState = 437
ModbusClientEnabled = 438
ModbusServerEnabled = 439
VirtualBinaryInput = 46
VirtualBinaryOutput = 47
VirtualRegisterInput = 48
VirtualRegisterOutput = 49
Timer = 51
TimerPerformance = 52
GlobalReal = 67
CommunicationRealTimeErrors = 81
LibraryCommand = 119
DataCollectionSampleTime = 120
DataCollectionSampleIndex = 129
ModbusClientConnected = 134
ModbusServerConnected = 135
ModbusClientError = 136
ModbusServerError = 137
StopWatchTimer = 157
ScopetrigId = 163
EstimatedProcessorUsage = 177
DataCollectionStatus = 188
SignalLogState = 198
SafeZoneViolationMask = 207
SafeZoneActiveMask = 229
ModbusClientInputWords = 240
ModbusClientOutputWords = 241
ModbusClientInputBits = 242
ModbusClientOutputBits = 243
ModbusClientOutputBitsStatus = 244
ModbusClientOutputWordsStatus = 245
ModbusServerInputWords = 246
ModbusServerOutputWords = 247
ModbusServerInputBits = 248
ModbusServerOutputBits = 249
SystemParameter = 265
ThermoCompSensorTemperature = 305
ThermoCompControllingTemperature = 306
ThermoCompCompensatingTemperature = 307
ThermoCompStatus = 308
GlobalInteger = 345
AliveAxesMask = 348
SignalLogPointsStored = 377
ControllerInitializationWarning = 379
StopWatchTimerMin = 416
StopWatchTimerMax = 417
StopWatchTimerAvg = 418
EthercatEnabled = 428
EthercatError = 429
EthercatTxPdo = 430
EthercatTxPdoSize = 431
EthercatRxPdo = 432
EthercatRxPdoSize = 433
EthercatState = 437
ModbusClientEnabled = 438
ModbusServerEnabled = 439
class DataCollectionFrequency:
Undefined = 0
Fixed1kHz = 1
Fixed10kHz = 2
Fixed20kHz = 3
Fixed100kHz = 4
Fixed200kHz = 5
Undefined = 0
Fixed1kHz = 1
Fixed10kHz = 2
Fixed20kHz = 3
Fixed100kHz = 4
Fixed200kHz = 5
class DataCollectionMode:
Snapshot = 0
Continouous = 1
Snapshot = 0
Continouous = 1
# Specifies the PSO distance input settings for the XC4e drive.
class PsoDistanceInput:
XC4PrimaryFeedback = 130
XC4AuxiliaryFeedback = 131
XC4SyncPortA = 132
XC4SyncPortB = 133
XC4DrivePulseStream = 134
XC4ePrimaryFeedback = 135
XC4eAuxiliaryFeedback = 136
XC4eSyncPortA = 137
XC4eSyncPortB = 138
XC4eDrivePulseStream = 139
XC4PrimaryFeedback = 130
XC4AuxiliaryFeedback = 131
XC4SyncPortA = 132
XC4SyncPortB = 133
XC4DrivePulseStream = 134
XC4ePrimaryFeedback = 135
XC4eAuxiliaryFeedback = 136
XC4eSyncPortA = 137
XC4eSyncPortB = 138
XC4eDrivePulseStream = 139
class PsoWindowInput:
XC4PrimaryFeedback = 130
XC4AuxiliaryFeedback = 131
XC4SyncPortA = 132
XC4SyncPortB = 133
XC4DrivePulseStream = 134
XC4ePrimaryFeedback = 135
XC4eAuxiliaryFeedback = 136
XC4eSyncPortA = 137
XC4eSyncPortB = 138
XC4eDrivePulseStream = 139
XL5ePrimaryFeedback = 145,
XL5eAuxiliaryFeedback = 146,
XL5eSyncPortA = 147,
XL5eSyncPortB = 148,
XL5eDrivePulseStream = 149,
XC4PrimaryFeedback = 130
XC4AuxiliaryFeedback = 131
XC4SyncPortA = 132
XC4SyncPortB = 133
XC4DrivePulseStream = 134
XC4ePrimaryFeedback = 135
XC4eAuxiliaryFeedback = 136
XC4eSyncPortA = 137
XC4eSyncPortB = 138
XC4eDrivePulseStream = 139
XL5ePrimaryFeedback = (145,)
XL5eAuxiliaryFeedback = (146,)
XL5eSyncPortA = (147,)
XL5eSyncPortB = (148,)
XL5eDrivePulseStream = (149,)
# @brief Specifies the PSO output pin settings for each drive.
class XC4ePsoOutputPin:
DedicatedOutput = 111
AuxiliaryMarkerDifferential = 112
AuxiliaryMarkerSingleEnded = 113
DedicatedOutput = 111
AuxiliaryMarkerDifferential = 112
AuxiliaryMarkerSingleEnded = 113
class XC4PsoOutputPin:
DedicatedOutput = 108
AuxiliaryMarkerDifferential = 109
AuxiliaryMarkerSingleEnded = 110
DedicatedOutput = 108
AuxiliaryMarkerDifferential = 109
AuxiliaryMarkerSingleEnded = 110
"""
@ -834,81 +832,70 @@ class Automation1PsoOutputPin:
class DriveDataCaptureInput:
PositionCommand = 0
PrimaryFeedback = 1
AuxiliaryFeedback = 2
AnalogInput0 = 3
AnalogInput1 = 4
AnalogInput2 = 5
AnalogInput3 = 6
PositionCommand = 0
PrimaryFeedback = 1
AuxiliaryFeedback = 2
AnalogInput0 = 3
AnalogInput1 = 4
AnalogInput2 = 5
AnalogInput3 = 6
class DriveDataCaptureTrigger:
PsoOutput = 0
PsoEvent = 1
HighSpeedInput0RisingEdge = 2
HighSpeedInput0FallingEdge = 3
HighSpeedInput1RisingEdge = 4
HighSpeedInput1FallingEdge = 5
AuxiliaryMarkerRisingEdge = 6
AuxiliaryMarkerFallingEdge = 7
PsoOutput = 0
PsoEvent = 1
HighSpeedInput0RisingEdge = 2
HighSpeedInput0FallingEdge = 3
HighSpeedInput1RisingEdge = 4
HighSpeedInput1FallingEdge = 5
AuxiliaryMarkerRisingEdge = 6
AuxiliaryMarkerFallingEdge = 7
class PsoOutputPin:
GL4None = 100,
GL4LaserOutput0 = 101,
XL4sNone = 102,
XL4sLaserOutput0 = 103,
XR3None = 104,
XR3PsoOutput1 = 105,
XR3PsoOutput2 = 106,
XR3PsoOutput3 = 107,
XC4DedicatedOutput = 108,
XC4AuxiliaryMarkerDifferential = 109,
XC4AuxiliaryMarkerSingleEnded = 110,
XC4eDedicatedOutput = 111,
XC4eAuxiliaryMarkerDifferential = 112,
XC4eAuxiliaryMarkerSingleEnded = 113,
XC6eDedicatedOutput = 114,
XC6eAuxiliaryMarkerDifferential = 115,
XC6eAuxiliaryMarkerSingleEnded = 116,
XL5eDedicatedOutput = 117,
XL5eAuxiliaryMarkerDifferential = 118,
XL5eAuxiliaryMarkerSingleEnded = 119,
XC2DedicatedOutput = 120,
XC2eDedicatedOutput = 121,
XL2eDedicatedOutput = 122,
XI4DedicatedOutput = 123,
iXC4DedicatedOutput = 124,
iXC4AuxiliaryMarkerDifferential = 125,
iXC4AuxiliaryMarkerSingleEnded = 126,
iXC4eDedicatedOutput = 127,
iXC4eAuxiliaryMarkerDifferential = 128,
iXC4eAuxiliaryMarkerSingleEnded = 129,
iXC6eDedicatedOutput = 130,
iXC6eAuxiliaryMarkerDifferential = 131,
iXC6eAuxiliaryMarkerSingleEnded = 132,
iXL5eDedicatedOutput = 133,
iXL5eAuxiliaryMarkerDifferential = 134,
iXL5eAuxiliaryMarkerSingleEnded = 135,
iXR3None = 136,
iXR3PsoOutput1 = 137,
iXR3PsoOutput2 = 138,
iXR3PsoOutput3 = 139,
GI4None = 140,
GI4LaserOutput0 = 141,
iXC2DedicatedOutput = 142,
iXC2eDedicatedOutput = 143,
iXL2eDedicatedOutput = 144,
iXI4DedicatedOutput = 145,
GL4None = (100,)
GL4LaserOutput0 = (101,)
XL4sNone = (102,)
XL4sLaserOutput0 = (103,)
XR3None = (104,)
XR3PsoOutput1 = (105,)
XR3PsoOutput2 = (106,)
XR3PsoOutput3 = (107,)
XC4DedicatedOutput = (108,)
XC4AuxiliaryMarkerDifferential = (109,)
XC4AuxiliaryMarkerSingleEnded = (110,)
XC4eDedicatedOutput = (111,)
XC4eAuxiliaryMarkerDifferential = (112,)
XC4eAuxiliaryMarkerSingleEnded = (113,)
XC6eDedicatedOutput = (114,)
XC6eAuxiliaryMarkerDifferential = (115,)
XC6eAuxiliaryMarkerSingleEnded = (116,)
XL5eDedicatedOutput = (117,)
XL5eAuxiliaryMarkerDifferential = (118,)
XL5eAuxiliaryMarkerSingleEnded = (119,)
XC2DedicatedOutput = (120,)
XC2eDedicatedOutput = (121,)
XL2eDedicatedOutput = (122,)
XI4DedicatedOutput = (123,)
iXC4DedicatedOutput = (124,)
iXC4AuxiliaryMarkerDifferential = (125,)
iXC4AuxiliaryMarkerSingleEnded = (126,)
iXC4eDedicatedOutput = (127,)
iXC4eAuxiliaryMarkerDifferential = (128,)
iXC4eAuxiliaryMarkerSingleEnded = (129,)
iXC6eDedicatedOutput = (130,)
iXC6eAuxiliaryMarkerDifferential = (131,)
iXC6eAuxiliaryMarkerSingleEnded = (132,)
iXL5eDedicatedOutput = (133,)
iXL5eAuxiliaryMarkerDifferential = (134,)
iXL5eAuxiliaryMarkerSingleEnded = (135,)
iXR3None = (136,)
iXR3PsoOutput1 = (137,)
iXR3PsoOutput2 = (138,)
iXR3PsoOutput3 = (139,)
GI4None = (140,)
GI4LaserOutput0 = (141,)
iXC2DedicatedOutput = (142,)
iXC2eDedicatedOutput = (143,)
iXL2eDedicatedOutput = (144,)
iXI4DedicatedOutput = (145,)