try to recover corrupted git
This commit is contained in:
18
.gitignore
vendored
Normal file
18
.gitignore
vendored
Normal file
@@ -0,0 +1,18 @@
|
||||
*~
|
||||
*-dev
|
||||
modules.order
|
||||
Module.symvers
|
||||
Mkfile.old
|
||||
core.*
|
||||
#*
|
||||
.#*
|
||||
\#*
|
||||
*.local
|
||||
\#*
|
||||
.cvsignore
|
||||
*_old/
|
||||
*PVs.list
|
||||
*-loc/*.Makefile
|
||||
ecmc_plugin_motion/*.Makefile
|
||||
*__*
|
||||
O*
|
||||
7
.vscode/settings.json
vendored
Normal file
7
.vscode/settings.json
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"files.associations": {
|
||||
"string_view": "cpp",
|
||||
"stdexcept": "cpp",
|
||||
"iosfwd": "cpp"
|
||||
}
|
||||
}
|
||||
28
Makefile
Normal file
28
Makefile
Normal file
@@ -0,0 +1,28 @@
|
||||
#
|
||||
# Copyright (c) 2018 - 2019 European Spallation Source ERIC
|
||||
#
|
||||
# The program is free software: you can redistribute
|
||||
# it and/or modify it under the terms of the GNU General Public License
|
||||
# as published by the Free Software Foundation, either version 2 of the
|
||||
# License, or any newer version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
# more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License along with
|
||||
# this program. If not, see https://www.gnu.org/licenses/gpl-2.0.txt
|
||||
#
|
||||
#
|
||||
# Author : Jeong Han Lee
|
||||
# email : han.lee@esss.se
|
||||
# Date : 2020Mar22-1607-33CET
|
||||
# version : 1.0.0
|
||||
|
||||
TOP:=$(CURDIR)
|
||||
|
||||
include $(TOP)/configure/CONFIG
|
||||
|
||||
include $(TOP)/configure/RULES
|
||||
|
||||
453
README.md
Normal file
453
README.md
Normal file
@@ -0,0 +1,453 @@
|
||||
e3-ecmc_plugin_fft
|
||||
======
|
||||
ESS Site-specific EPICS module : ecmcPlugin_FFT
|
||||
|
||||
A shared library with FFT functionalities loadable into ecmc:
|
||||
|
||||
https://github.com/epics-modules/ecmc (or local ess fork https://github.com/icshwi/ecmc).
|
||||
|
||||
Configuration is made through ecmccfg:
|
||||
|
||||
https://github.com/paulscherrerinstitute/ecmccfg (ot local ess fork https://github.com/icshwi/ecmccfg)
|
||||
|
||||
FFT:s are calculated with the kissfft lib:
|
||||
https://github.com/mborgerding/kissfft
|
||||
|
||||
|
||||
# Introduction
|
||||
|
||||
The main functionality of this plugin is to make FFT analysis of ecmc data. Most data in ecmc is accessible:
|
||||
1. EtherCAT data ("ec0.s1.AI_1" or "ec0.s2.mm.CH1_ARRAY")
|
||||
2. Motion data ("ax1.actpos")
|
||||
3. PLC data ("plcs.plc0.static.testvalue")
|
||||
|
||||
Precautions have been taken in order to disturb ecmc real time thread as little as possible:
|
||||
1. All CPU intensive calculations are handled in a low prio work thread (not ecmc thread).
|
||||
2. Communication to epics is made via a dedicated asynPortDriver (not the same that ecmc uses).
|
||||
|
||||
See below for configuration options and the different modes supported by this ecmc plugin.
|
||||
|
||||
## Loading of FFT plugin in ecmc:
|
||||
A plugin is loaded by the ecmccfg command loadPlugin:
|
||||
https://github.com/icshwi/ecmccfg/blob/master/scripts/loadPlugin.cmd
|
||||
|
||||
Example:
|
||||
```
|
||||
${SCRIPTEXEC} ${ecmccfg_DIR}loadPlugin.cmd, "PLUGIN_ID=0,FILE=libecmcPlugin_FFT.so,CONFIG='DBG_PRINT=1;SOURCE=ax1.actpos;RM_LIN=1;', REPORT=1
|
||||
dbLoadRecords(ecmcPluginFFT.template,"P=$(IOC):,INDEX=0, NELM=${FFT_NELM}")
|
||||
```
|
||||
This plugin supports multiple loading. For each load of the plugin a new FFT object will be created. In order to access these plugins, from plc:s or EPICS records, they can be accessed by an index. The first FFT plugin will have index 0. The next loaded FFT plugin will have index 1...
|
||||
|
||||
Note: If another plugin is loaded in between the loading of FFT plugins, it will have no affect on these FFT indexes (so the FFT index is _not_ the same as plugin index).
|
||||
|
||||
## Configuration
|
||||
|
||||
The different available configuration settings:
|
||||
* SOURCE= source variable : Sets source variable for FFT (example: ec0.s1.AI_1). This config is mandatory.
|
||||
* DBG_PRINT=1/0 : Enables/disables printouts from plugin, default = disabled.
|
||||
* NFFT= nfft : Data points to collect, default = 4096.
|
||||
* SCALE=scale : Apply scale to input data, default = 1.0.
|
||||
* RM_DC=1/0 : Remove DC offset of input data (SOURCE), default = disabled.
|
||||
* RM_LIN=1/0 : Remove linear component input data (SOURCE), default = disabled.
|
||||
* ENABLE=1/0 : Enable data acq. and calcs (can be controlled over asyn), default = disabled.
|
||||
* MODE=CONT/TRIGG : Continious or triggered mode, defaults to TRIGG
|
||||
* RATE=rate in hz : fft data sample rate in hz (must be lower than ecmc rate and (ecmc_rate/fft_rate)=integer), default = ecmc rate.
|
||||
* BREAKTABLE= EPICS breaktable : Apply breaktable to raw value.
|
||||
|
||||
Example configuration string:
|
||||
```
|
||||
"SOURCE=ax1.poserr;MODE=TRIGG;DBG_PRINT=1;ENABLE=1;"
|
||||
```
|
||||
|
||||
#### SOURCE (mandatory)
|
||||
The data source is defined by setting the SOURCE option in the plugin configuration string.
|
||||
This configuration is mandatory.
|
||||
|
||||
Example: Axis 1 actpos (See RM_LIN config below)
|
||||
```
|
||||
"DBG_PRINT=1;SOURCE=ax1.actpos;RM_LIN=1;"
|
||||
|
||||
```
|
||||
Example: Ethercat slave 1 analog input ch1
|
||||
```
|
||||
"DBG_PRINT=1;SOURCE=ec0.s1.AI_1;"
|
||||
```
|
||||
#### DBG_PRINT (default: disabled)
|
||||
Enable/disable printouts from plugin can be made bu setting the "DBG_PRINT" option.
|
||||
|
||||
Example: Disable
|
||||
```
|
||||
"DBG_PRINT=0;SOURCE=ax1.poserr;"
|
||||
```
|
||||
|
||||
#### NFFT (default: 4096)
|
||||
Defines number of samples for each measurement.
|
||||
|
||||
Note: Must be a n² number..
|
||||
|
||||
Example: 1024
|
||||
```
|
||||
"NFFT=1024;DBG_PRINT=0;SOURCE=ax1.poserr;"
|
||||
```
|
||||
#### SCALE (default 1.0)
|
||||
Apply custom scale to input data.
|
||||
|
||||
Example: 5.0
|
||||
```
|
||||
"SCALE=5.0;NFFT=1024;DBG_PRINT=0;SOURCE=ax1.poserr;"
|
||||
```
|
||||
### RM_DC
|
||||
Remove DC of input signal. Default is disabled.
|
||||
|
||||
Example: Remove DC offset
|
||||
```
|
||||
"RM_DC=1;SCALE=1;NFFT=1024;DBG_PRINT=0;SOURCE=ax1.poserr;"
|
||||
|
||||
```
|
||||
### RM_LIN
|
||||
Remove linear component of input signal. Default is disabled.
|
||||
The linear component is calculated by least square method.
|
||||
Could be usefull for values that increase, like actual position.
|
||||
|
||||
Example: Remove linear component
|
||||
```
|
||||
"RM_LIN=1;SCALE=1;NFFT=1024;DBG_PRINT=0;SOURCE=ax1.poserr;"
|
||||
```
|
||||
#### ENABLE (default: disabled)
|
||||
Enable data acq. and FFT calcs. The default settings is disabled so needs to be enabled from plc or over asyn in order to start calculations.
|
||||
|
||||
Example: Enable at startup by config
|
||||
```
|
||||
"ENABLE=1;RM_DC=1;SCALE=1;NFFT=1024;DBG_PRINT=0;SOURCE=ax1.poserr;"
|
||||
```
|
||||
Example: Enable FFT index 0 from EPICS:
|
||||
```
|
||||
caput IOC_TEST:Plugin-FFT0-Enable 1
|
||||
```
|
||||
Example: Enable FFT index 0 from ecmc PLC code:
|
||||
```
|
||||
fft_enable(0,1)
|
||||
```
|
||||
|
||||
#### MODE (default: TRIGG)
|
||||
The FFT module can operate in two different modes:
|
||||
* CONTINIOUS (CONT)
|
||||
* TRIGGERED (TRIGG)
|
||||
|
||||
Continious mode:
|
||||
1. Clear data buffers
|
||||
2. Wait for enable (from plc or asyn/epics record or configuration(see above))
|
||||
3. Data acqusition starts
|
||||
4. When buffers are full a worker thread will be triggered to calculate the FFT.
|
||||
5. FTT results are sent by callback over asyn to epics records
|
||||
6. goto 1.
|
||||
|
||||
Note: data will be "lost" during calculation time.
|
||||
|
||||
Triggered mode:
|
||||
1. Clear data buffers
|
||||
2. Wait for enable (from plc or asyn/epics record or configuration(see above))
|
||||
3. Wait for trigger (from plc or asyn/epics record)
|
||||
3. Data acqusition starts
|
||||
4. When buffers are full a worker thread will be triggered to calculate the FFT.
|
||||
5. FTT results are sent by callback over asyn to epics records
|
||||
6. goto 1.
|
||||
|
||||
Example: Mode triggered
|
||||
```
|
||||
"MODE=TRIGG;ENABLE=1;RM_DC=1;SCALE=1;NFFT=1024;DBG_PRINT=0;SOURCE=ax1.poserr;"
|
||||
```
|
||||
Example: Mode from EPICS record
|
||||
```
|
||||
# CONT
|
||||
caput IOC_TEST:Plugin-FFT0-Mode-RB 1
|
||||
# TRIGG
|
||||
caput IOC_TEST:Plugin-FFT0-Mode-RB 2
|
||||
```
|
||||
Note: The record is a output record with readback so can both be read and written to.
|
||||
|
||||
#### RATE (default: the ecmc rate of the selected data source)
|
||||
Sets the sample rate of the raw input data (from data source). The default value is the ecmc rate for that data source.
|
||||
Note: only a lower and "integer" division of sample rate can be defined.
|
||||
|
||||
Example: Rate = 100Hz
|
||||
```
|
||||
"RATE=100;MODE=TRIGG;ENABLE=1;RM_DC=1;SCALE=1;NFFT=1024;DBG_PRINT=0;SOURCE=ax1.poserr;"
|
||||
```
|
||||
|
||||
#### BREAKTABLE (default: no break table)
|
||||
|
||||
Note: The break table must be added in EPICS
|
||||
|
||||
Example: Apply BREAKTABLE=typeTelemess33020_21877 to raw value
|
||||
```
|
||||
"...;BREAKTABLE=typeTelemess33020_21877;"
|
||||
```
|
||||
|
||||
Example: Load custom breaktable in EPICS
|
||||
```
|
||||
dbLoadRecords ./bptBreakTable.dbd
|
||||
```
|
||||
|
||||
Example: breaktable (in a bptBreakTable.dbd)
|
||||
```
|
||||
# <raw> <eng>
|
||||
breaktable(typeTelemess33020_21877) {
|
||||
2502.48 0
|
||||
4058.89 1.5
|
||||
6164.64 3
|
||||
8880.74 4.5
|
||||
11993.57 6
|
||||
15259.00 7.5
|
||||
18371.84 9
|
||||
21271.05 10.5
|
||||
24658.54 12
|
||||
27344.13 13.5
|
||||
29297.28 15
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
## EPICS records
|
||||
Each FFT plugin object will create a new asynportdriver-port named "PLUGIN.FFT<index>" (index is explaine above).
|
||||
The reason for a dedicated asynport is to disturb ecmc as little as possible.
|
||||
The plugin contains a template file, "ecmcPluginFFT.template", that will make most information availbe from records:
|
||||
* Rawdata array (ro)
|
||||
* FFT amplitude array (result) (ro)
|
||||
* FFT x axis (frequencies) (ro)
|
||||
* Status (ro)
|
||||
* Mode (rw)
|
||||
* Sample rate (ro)
|
||||
* Enable cmd (rw)
|
||||
* Trigger cmd (rw)
|
||||
* NFFT (ro)
|
||||
|
||||
The available records from this template file can be listed by the cmd (here two FFT plugins loaded):
|
||||
```
|
||||
dbgrep *FFT*
|
||||
IOC_TEST:Plugin-FFT0-SampleRate-Act
|
||||
IOC_TEST:Plugin-FFT1-SampleRate-Act
|
||||
IOC_TEST:Plugin-FFT0-Mode-RB
|
||||
IOC_TEST:Plugin-FFT1-Mode-RB
|
||||
IOC_TEST:Plugin-FFT0-Source
|
||||
IOC_TEST:Plugin-FFT0-Raw-Data-Act
|
||||
IOC_TEST:Plugin-FFT0-Spectrum-Amp-Act
|
||||
IOC_TEST:Plugin-FFT0-Spectrum-X-Axis-Act
|
||||
IOC_TEST:Plugin-FFT1-Source
|
||||
IOC_TEST:Plugin-FFT1-Raw-Data-Act
|
||||
IOC_TEST:Plugin-FFT1-Spectrum-Amp-Act
|
||||
IOC_TEST:Plugin-FFT1-Spectrum-X-Axis-Act
|
||||
IOC_TEST:Plugin-FFT0-Enable
|
||||
IOC_TEST:Plugin-FFT0-Trigg
|
||||
IOC_TEST:Plugin-FFT1-Enable
|
||||
IOC_TEST:Plugin-FFT1-Trigg
|
||||
IOC_TEST:Plugin-FFT0-stat
|
||||
IOC_TEST:Plugin-FFT0-NFFT
|
||||
IOC_TEST:Plugin-FFT1-stat
|
||||
IOC_TEST:Plugin-FFT1-NFFT
|
||||
```
|
||||
Note: The FFT asynparameters will not be visible by the ecmcReport iocsh command since the FFT records belong to another port.
|
||||
|
||||
## PLC interface
|
||||
|
||||
### PLC Functions
|
||||
|
||||
1. "fft_clear(arg0);" double fft_clear(index) : Clear/resets all buffers fft[index].
|
||||
2. "fft_enable(arg0, arg1);" double fft_enable(index, enable) : Set enable for fft[index].
|
||||
3. "fft_trigg(arg0);" double fft_trigg(index) : Trigg new measurement for fft[index]. Will clear buffers.
|
||||
4. "fft_mode(arg0, arg1);" double fft_mode(index, mode) : Set mode Cont(1)/Trigg(2) for fft[index].
|
||||
5. "fft_stat(arg0);" double fft_stat(index) : Get status of fft (NO_STAT, IDLE, ACQ, CALC) for fft[index].
|
||||
|
||||
### PLC Constants:
|
||||
|
||||
These constants are for use togheter with the above listed PLC functions:
|
||||
1. "fft_CONT" = 1: FFT Mode: Continious
|
||||
2. "fft_TRIGG" = 2: FFT Mode :Triggered
|
||||
3. "fft_NO_STAT" = 0: FFT Status: Invalid state
|
||||
4. "fft_IDLE" = 1: FFT Status: Idle state (waiting for trigger)
|
||||
5. "fft_ACQ" = 2: FFT Status: Acquiring data
|
||||
6. "fft_CALC" = 3: FFT Status: Calculating result
|
||||
|
||||
## Example script
|
||||
An example script can be found in the iocsh directory of this repo.
|
||||
This example load 2 FFT plugin objects:
|
||||
1. SOURCE="plcs.plc0.static.sineval" which is a plc variable updated as a sinus with default freq 5 Hz.
|
||||
2. SOURCE="ecmc.thread.latency.max". This is the execution latency of ecmc (in nanoseconds).
|
||||
|
||||
Start one FFT calc over EPICS records:
|
||||
```
|
||||
# Enable
|
||||
caput IOC_TEST:Plugin-FFT0-Enable 1
|
||||
# Trigg a new calc
|
||||
caput IOC_TEST:Plugin-FFT1-Trigg 1
|
||||
```
|
||||
|
||||
#### Example input signal
|
||||
Epics record: IOC_TEST:Plugin-FFT0-Raw-Data-Act
|
||||
|
||||
||
|
||||
| :---: |
|
||||
|**Figure 1** Raw data. |
|
||||
|
||||
#### Example FFT result
|
||||
Epics records:
|
||||
* X = IOC_TEST:Plugin-FFT0-Spectrum-X-Axis-Act
|
||||
* Y = IOC_TEST:Plugin-FFT0-Spectrum-Amp-Act
|
||||
|
||||
||
|
||||
| :---: |
|
||||
|**Figure 2** Resulting FFT amplitude. |
|
||||
|
||||
#### ecmc PLC code for example:
|
||||
```
|
||||
static.time:=ec_get_time()/1E9;
|
||||
static.sineval:=sin(2*pi*${FREQ=5}*static.time);
|
||||
```
|
||||
|
||||
## FFT GUI
|
||||
|
||||
### FFT GUI (FFT and rawdata plots + controls)
|
||||
A simple tool, [ecmcFFTMainGui.py](tools/ecmcFFTMainGui.py), to visualize the calculated spectrum, rawdata and also plugin controls can be found in the tools directory. The GUI connects to the plugin records over pypics framwork.
|
||||
The gui are included in the ecmccomgui repo:
|
||||
https://github.com/anderssandstrom/ecmccomgui
|
||||
|
||||
Example: ecmcFFTMainGui.py help printout
|
||||
```
|
||||
python ecmcFFTMainGui.py
|
||||
ecmcFFTMainGui: Plots waveforms of FFT data (updates on Y data callback).
|
||||
python ecmcFFTMainGui.py <prefix> <fftId>
|
||||
<prefix>: Ioc prefix ('IOC_TEST:')
|
||||
<fftId> : Id of fft plugin ('0')
|
||||
example : python ecmcFFTMainGui.py 'IOC_TEST:' '0'
|
||||
Will connect to Pvs: <prefix>Plugin-FFT<fftId>-*
|
||||
```
|
||||
|
||||
Example: Start ecmcFFMainTGui.py for:
|
||||
* predix="IOC_TEST:"
|
||||
* fftPluginId=0 (the first loaded FFT plugin in the ioc)
|
||||
```
|
||||
python ecmcFFTMainGui.py IOC_TEST: 0
|
||||
```
|
||||

|
||||
|
||||
### FFT GUI (only FFT plot)
|
||||
|
||||
A simple tool, [ecmcFFTGui.py](tools/ecmcFFTGui.py), to visualize the calculated spectrum can be found in the tools directory.
|
||||
The GUI connects to the plugin records over pypics framwork.
|
||||
|
||||
Example: ecmcFFTGui.py help printout
|
||||
```
|
||||
python ecmcFFTGui.py
|
||||
ecmcFFTGui: Plots waveforms of FFT data (updates on Y data callback).
|
||||
python ecmcFFTGui.py <x.pv> <y.pv>
|
||||
example: python ecmcFFTGui.py IOC_TEST:Plugin-FFT1-Spectrum-X-Axis-Act IOC_TEST:Plugin-FFT1-Spectrum-Amp-Act
|
||||
```
|
||||
|
||||
Example: Start ecmcFFTGui.py for spectrum amplitude and freq. waveform pvs
|
||||
```
|
||||
python ecmcFFTGui.py IOC_TEST:Plugin-FFT1-Spectrum-X-Axis-Act IOC_TEST:Plugin-FFT1-Spectrum-Amp-Act
|
||||
```
|
||||

|
||||
|
||||
### Array GUI (generic waveform plt)
|
||||
A simple generic tool, [ecmcFFTGui.py](tools/ecmcFFTGui.py), to visualize wavforms.
|
||||
The GUI connects to the plugin records over pypics framwork.
|
||||
|
||||
Example: ecmcArrayGui.py help printout
|
||||
```
|
||||
python ecmcArrayGui.py
|
||||
ecmcArrayGui: Plots waveforms data (updates on data callback).
|
||||
python ecmcArrayGui.py <y.pv>
|
||||
example: python ecmcArrayGui.py IOC_TEST:Plugin-FFT0-Raw-Data-Act
|
||||
```
|
||||
|
||||
Example: Start ecmcArrayGui.py for raw data wavform
|
||||
```
|
||||
python ecmcArrayGui.py IOC_TEST:Plugin-FFT0-Raw-Data-Act
|
||||
```
|
||||

|
||||
|
||||
### Needed packages:
|
||||
* python 3.5
|
||||
* epics
|
||||
* PyQt5
|
||||
* numpy
|
||||
* matplotlib
|
||||
|
||||
|
||||
## Plugin info
|
||||
|
||||
```
|
||||
Plugin info:
|
||||
Index = 1
|
||||
Name = ecmcPlugin_FFT
|
||||
Description = FFT plugin for use with ecmc.
|
||||
Option description =
|
||||
DBG_PRINT=<1/0> : Enables/disables printouts from plugin, default = disabled.
|
||||
SOURCE=<source> : Sets source variable for FFT (example: ec0.s1.AI_1).
|
||||
NFFT=<nfft> : Data points to collect, default = 4096.
|
||||
SCALE=<1/0> : Apply scale, default = disabled.
|
||||
RM_DC=<1/0> : Remove DC offset of input data (SOURCE), default = disabled.
|
||||
ENABLE=<1/0> : Enable data acq. and calcs (can be controlled over asyn), default = disabled.
|
||||
MODE=<CONT/TRIGG> : Continious or triggered mode, defaults to TRIGG
|
||||
RATE=<rate in hz> : fft data sample rate in hz (must be lower than ecmc rate and (ecmc_rate/fft_rate)=integer), default = ecmc rate.
|
||||
Filename = /epics/base-7.0.3.1/require/3.1.2/siteMods/ecmcPlugin_FFT/master/lib/linux-arm/libecmcPlugin_FFT.so
|
||||
Config string = SOURCE=ecmc.thread.latency.max;DBG_PRINT=0;NFFT=1024;
|
||||
Version = 1
|
||||
Interface version = 512 (ecmc = 512)
|
||||
max plc funcs = 64
|
||||
max plc func args = 10
|
||||
max plc consts = 64
|
||||
Construct func = @0xb5022044
|
||||
Enter realtime func = @0xb5022090
|
||||
Exit realtime func = @0xb502203c
|
||||
Realtime func = @0xb5022034
|
||||
Destruct func = @0xb502206c
|
||||
dlhandle = @0x1d9de28
|
||||
Plc functions:
|
||||
funcs[00]:
|
||||
Name = "fft_clear(arg0);"
|
||||
Desc = double fft_clear(index) : Clear/reset fft[index].
|
||||
Arg count = 1
|
||||
func = @0xb5022094
|
||||
funcs[01]:
|
||||
Name = "fft_enable(arg0, arg1);"
|
||||
Desc = double fft_enable(index, enable) : Set enable for fft[index].
|
||||
Arg count = 2
|
||||
func = @0xb50220b0
|
||||
funcs[02]:
|
||||
Name = "fft_trigg(arg0);"
|
||||
Desc = double fft_trigg(index) : Trigg new measurement for fft[index]. Will clear buffers.
|
||||
Arg count = 1
|
||||
func = @0xb50220d4
|
||||
funcs[03]:
|
||||
Name = "fft_mode(arg0, arg1);"
|
||||
Desc = double fft_mode(index, mode) : Set mode Cont(1)/Trigg(2) for fft[index].
|
||||
Arg count = 2
|
||||
func = @0xb50220f0
|
||||
funcs[04]:
|
||||
Name = "fft_stat(arg0);"
|
||||
Desc = double fft_stat(index) : Get status of fft (NO_STAT, IDLE, ACQ, CALC) for fft[index].
|
||||
Arg count = 1
|
||||
func = @0xb5022114
|
||||
Plc constants:
|
||||
consts[00]:
|
||||
Name = "fft_CONT" = 1.000
|
||||
Desc = FFT Mode: Continious
|
||||
consts[01]:
|
||||
Name = "fft_TRIGG" = 2.000
|
||||
Desc = FFT Mode :Triggered
|
||||
consts[02]:
|
||||
Name = "fft_NO_STAT" = 0.000
|
||||
Desc = FFT Status: Invalid state
|
||||
consts[03]:
|
||||
Name = "fft_IDLE" = 1.000
|
||||
Desc = FFT Status: Idle state (waiting for trigger)
|
||||
consts[04]:
|
||||
Name = "fft_ACQ" = 2.000
|
||||
Desc = FFT Status: Acquiring data
|
||||
consts[05]:
|
||||
Name = "fft_CALC" = 3.000
|
||||
Desc = FFT Status: Calculating result
|
||||
|
||||
```
|
||||
0
cmds/.keep
Normal file
0
cmds/.keep
Normal file
11
configure/CONFIG
Normal file
11
configure/CONFIG
Normal file
@@ -0,0 +1,11 @@
|
||||
#
|
||||
VARS_EXCLUDES := $(.VARIABLES)
|
||||
|
||||
include $(TOP)/configure/RELEASE
|
||||
include $(TOP)/configure/CONFIG_MODULE
|
||||
|
||||
E3_REQUIRE_LOCATION := $(EPICS_BASE)/$(E3_REQUIRE_NAME)/$(E3_REQUIRE_VERSION)
|
||||
REQUIRE_CONFIG := $(E3_REQUIRE_LOCATION)/configure
|
||||
|
||||
include $(REQUIRE_CONFIG)/CONFIG
|
||||
|
||||
40
configure/CONFIG_MODULE
Normal file
40
configure/CONFIG_MODULE
Normal file
@@ -0,0 +1,40 @@
|
||||
#
|
||||
EPICS_MODULE_NAME:=ecmc_plugin_motion
|
||||
|
||||
EPICS_MODULE_TAG:=master
|
||||
#
|
||||
E3_MODULE_VERSION:=master
|
||||
|
||||
# DEPENDENT MODULE VERSION
|
||||
# For Example,
|
||||
|
||||
ECMC_DEP_VERSION:=v9.0.1_RC1
|
||||
ASYN_DEP_VERSION:=4.41.0
|
||||
EXPRTK_DEP_VERSION:=addCompFunc
|
||||
MOTOR_DEP_VERSION:=7.0.6
|
||||
RUCKIG_DEP_VERSION:=1.0.0
|
||||
|
||||
#DEVLIB2_DEP_VERSION:=2.9.0
|
||||
#PCRE_DEP_VERSION:=8.41.0
|
||||
#ADCORE_DEP_VERSION:=3.7.0
|
||||
#ADSUPPORT_DEP_VERSION:=1.9.0
|
||||
#LOKI_DEP_VERSION=1.0.0
|
||||
#NDS_DEP_VERSION=2.3.3
|
||||
#SIS8300DRV_DEP_VERSION=4.3.1
|
||||
#SEQUENCER_DEP_VERSION=2.2.7
|
||||
#
|
||||
#
|
||||
#E3_KMOD_SRC_PATH:=$(E3_MODULE_SRC_PATH)
|
||||
#
|
||||
# In most case, we don't need to touch the following variables.
|
||||
#
|
||||
|
||||
E3_MODULE_NAME:=$(EPICS_MODULE_NAME)
|
||||
E3_MODULE_SRC_PATH:=ecmc_plugin_motion
|
||||
E3_MODULE_MAKEFILE:=$(EPICS_MODULE_NAME).Makefile
|
||||
|
||||
|
||||
-include $(TOP)/configure/CONFIG_OPTIONS
|
||||
# The definitions shown below can also be placed in an untracked CONFIG_MODULE.local
|
||||
-include $(TOP)/configure/CONFIG_MODULE.local
|
||||
|
||||
6
configure/CONFIG_OPTIONS
Normal file
6
configure/CONFIG_OPTIONS
Normal file
@@ -0,0 +1,6 @@
|
||||
#
|
||||
# WITH_PVA:=NO
|
||||
#
|
||||
# The definitions shown below can also be placed in an untracked CONFIG_OPTIONS.local
|
||||
-include $(TOP)/configure/CONFIG_OPTIONS.local
|
||||
|
||||
11
configure/RELEASE
Normal file
11
configure/RELEASE
Normal file
@@ -0,0 +1,11 @@
|
||||
#
|
||||
EPICS_BASE:=${HOME}/epics/base-7.0.5
|
||||
|
||||
E3_REQUIRE_NAME:=require
|
||||
E3_REQUIRE_VERSION:=3.4.0
|
||||
|
||||
# The definitions shown below can also be placed in an untracked RELEASE.local
|
||||
-include $(TOP)/../../RELEASE.local
|
||||
-include $(TOP)/../RELEASE.local
|
||||
-include $(TOP)/configure/RELEASE.local
|
||||
|
||||
12
configure/RULES
Normal file
12
configure/RULES
Normal file
@@ -0,0 +1,12 @@
|
||||
|
||||
include $(REQUIRE_CONFIG)/RULES_E3
|
||||
include $(REQUIRE_CONFIG)/DEFINES_FT
|
||||
include $(REQUIRE_CONFIG)/RULES_PATCH
|
||||
include $(REQUIRE_CONFIG)/RULES_E3_SITELIBS
|
||||
|
||||
include $(REQUIRE_CONFIG)/RULES_VLIBS
|
||||
include $(REQUIRE_CONFIG)/RULES_VARS
|
||||
|
||||
include $(TOP)/configure/module/RULES_MODULE
|
||||
-include $(TOP)/configure/module/RULES_DKMS_L
|
||||
|
||||
38
configure/module/RULES_DKMS_L
Normal file
38
configure/module/RULES_DKMS_L
Normal file
@@ -0,0 +1,38 @@
|
||||
|
||||
# KMOD_NAME := mrf
|
||||
|
||||
# .PHONY: dkms_add
|
||||
|
||||
# dkms_add: conf
|
||||
# $(MSI) -M name="$(E3_MODULE_NAME)" -M version="$(E3_MODULE_VERSION)" -M kmod_name="$(KMOD_NAME)" $(TOP)/dkms/dkms_with_msi.conf.in > $(TOP)/dkms/dkms_with_msi.conf
|
||||
# $(QUIET) cat $(TOP)/dkms/dkms_with_msi.conf $(TOP)/dkms/dkms_without_msi.conf > $(TOP)/dkms/dkms.conf
|
||||
# $(QUIET) install -m 644 $(TOP)/dkms/dkms.conf $(E3_KMOD_SRC_PATH)/
|
||||
# $(SUDO) install -d /usr/src/$(E3_MODULE_NAME)-$(E3_MODULE_VERSION)
|
||||
# $(SUDO) cp -r $(TOP)/$(E3_KMOD_SRC_PATH)/* /usr/src/$(E3_MODULE_NAME)-$(E3_MODULE_VERSION)/
|
||||
# $(SUDO) $(DKMS) add $(DKMS_ARGS)
|
||||
|
||||
|
||||
# setup:
|
||||
# $(QUIET) $(SUDO2) 'echo KERNEL==\"uio*\", ATTR{name}==\"mrf-pci\", MODE=\"0666\" | tee /etc/udev/rules.d/99-$(KMOD_NAME).rules'
|
||||
# $(QUIET) $(SUDO) /bin/udevadm control --reload-rules
|
||||
# $(QUIET) $(SUDO) /bin/udevadm trigger
|
||||
# $(QUIET) $(SUDO2) 'echo $(KMOD_NAME) | tee /etc/modules-load.d/$(KMOD_NAME).conf'
|
||||
# $(QUIET) $(SUDO) depmod --quick
|
||||
# $(QUIET) $(SUDO) modprobe -rv $(KMOD_NAME)
|
||||
# $(QUIET) $(SUDO) modprobe -v $(KMOD_NAME)
|
||||
# $(QUIET) echo ""
|
||||
# $(QUIET) echo ""
|
||||
# $(QUIET) echo "It is OK to see \"E3/RULES_DKMS:37: recipe for target 'setup' failed\""
|
||||
# $(QUIET) echo "---------------------------------------------------------------------"
|
||||
# $(QUIET) -ls -l /dev/uio* 2>/dev/null
|
||||
# $(QUIET) echo "---------------------------------------------------------------------"
|
||||
|
||||
|
||||
# setup_clean:
|
||||
# $(QUIET) $(SUDO) modprobe -rv $(KMOD_NAME)
|
||||
# $(SUDO) rm -f /etc/modules-load.d/$(KMOD_NAME).conf
|
||||
# $(SUDO) rm -f /etc/udev/rules.d/99-$(KMOD_NAME).rules
|
||||
|
||||
|
||||
# .PHONY: setup setup_clean
|
||||
|
||||
20
configure/module/RULES_MODULE
Normal file
20
configure/module/RULES_MODULE
Normal file
@@ -0,0 +1,20 @@
|
||||
#
|
||||
.PHONY: db hdrs
|
||||
|
||||
db: conf
|
||||
$(QUIET) $(E3_MODULE_MAKE_CMDS) db
|
||||
|
||||
hdrs:
|
||||
# $(SUDO) install -m 755 -d $(E3_MODULES_INSTALL_LOCATION_INC)/pv
|
||||
# cd $(E3_MODULES_INSTALL_LOCATION_INC) && $(SUDO) mv *.h pv/
|
||||
|
||||
#.PHONY: epics
|
||||
#epics:
|
||||
# $(QUIET)echo "EPICS_BASE:=$(EPICS_BASE)" > $(TOP)/$(E3_MODULE_SRC_PATH)/configure/RELEASE
|
||||
# $(QUIET)echo "ASYN:=$(M_ASYN)" > $(TOP)/$(E3_MODULE_SRC_PATH)/configure/RELEASE
|
||||
# $(QUIET)echo "SSCAN:=$(M_SSCAN)" >> $(TOP)/$(E3_MODULE_SRC_PATH)/configure/RELEASE
|
||||
# $(QUIET)echo "SNCSEQ:=$(M_SNCSEQ)" >> $(TOP)/$(E3_MODULE_SRC_PATH)/configure/RELEASE
|
||||
# $(QUIET)echo "CHECK_RELEASE:=YES" > $(TOP)/$(E3_MODULE_SRC_PATH)/configure/CONFIG_SITE
|
||||
# $(QUIET)echo "INSTALL_LOCATION:=$(M_DEVLIB2)" >> $(TOP)/$(E3_MODULE_SRC_PATH)/configure/CONFIG_SITE
|
||||
# $(SUDOBASH) "$(MAKE) -C $(E3_MODULE_SRC_PATH)"
|
||||
|
||||
28
docs/.MODULE_LOG
Normal file
28
docs/.MODULE_LOG
Normal file
@@ -0,0 +1,28 @@
|
||||
>>
|
||||
Script is used : e3TemplateGenerator.bash
|
||||
Script Path : /home/anderssandstrom/plugin_ecmc/e3-tools/e3TemplateGenerator
|
||||
Script Version : 1.0.8
|
||||
Script Run Time : 2020Mar22-1607-33CET
|
||||
User : anderssandstrom
|
||||
e3-tools Hash : bf03d40
|
||||
>>
|
||||
>> git diff
|
||||
|
||||
>>
|
||||
>> git diff --cached
|
||||
|
||||
>>
|
||||
>> git diff HEAD
|
||||
|
||||
|
||||
>>
|
||||
>> Your sources are located in e3-ecmcPlugin_Simple.
|
||||
>>
|
||||
EPICS_MODULE_NAME : ecmcPlugin_Simple
|
||||
E3_MODULE_SRC_PATH : ecmcPlugin_Simple
|
||||
E3_TARGET_URL : https://github.com/anderssandstrom
|
||||
>>
|
||||
e3 module name : e3-ecmcPlugin_Simple
|
||||
e3 target url full : https://github.com/anderssandstrom/e3-ecmcPlugin_Simple.git
|
||||
>>
|
||||
e3 module is located in siteMods
|
||||
BIN
docs/ecmcPLC5HzFFT.png
Normal file
BIN
docs/ecmcPLC5HzFFT.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 21 KiB |
BIN
docs/ecmcPLC5HzRAW.png
Normal file
BIN
docs/ecmcPLC5HzRAW.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 103 KiB |
BIN
docs/gui/ecmcArrayGui.png
Normal file
BIN
docs/gui/ecmcArrayGui.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 50 KiB |
BIN
docs/gui/ecmcFFTGui.png
Normal file
BIN
docs/gui/ecmcFFTGui.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 32 KiB |
BIN
docs/gui/ecmcFFTMainGui.png
Normal file
BIN
docs/gui/ecmcFFTMainGui.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 57 KiB |
99
ecmc_plugin_motion.Makefile
Normal file
99
ecmc_plugin_motion.Makefile
Normal file
@@ -0,0 +1,99 @@
|
||||
#
|
||||
# Copyright (c) 2023 Paul Scherrer Institute
|
||||
#
|
||||
# The program is free software: you can redistribute
|
||||
# it and/or modify it under the terms of the GNU General Public License
|
||||
# as published by the Free Software Foundation, either version 2 of the
|
||||
# License, or any newer version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
# more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License along with
|
||||
# this program. If not, see https://www.gnu.org/licenses/gpl-2.0.txt
|
||||
#
|
||||
#
|
||||
# Author : anderssandstrom
|
||||
# email : anders.sandstroem@psi.ch
|
||||
# Date : 2023 July 10
|
||||
# version : 0.0.0
|
||||
#
|
||||
|
||||
|
||||
## The following lines are mandatory, please don't change them.
|
||||
where_am_I := $(dir $(abspath $(lastword $(MAKEFILE_LIST))))
|
||||
include $(E3_REQUIRE_TOOLS)/driver.makefile
|
||||
include $(E3_REQUIRE_CONFIG)/DECOUPLE_FLAGS
|
||||
|
||||
ifneq ($(strip $(ASYN_DEP_VERSION)),)
|
||||
asyn_VERSION=$(ASYN_DEP_VERSION)
|
||||
endif
|
||||
|
||||
ifneq ($(strip $(ECMC_DEP_VERSION)),)
|
||||
ecmc_VERSION=$(ECMC_DEP_VERSION)
|
||||
endif
|
||||
|
||||
ifneq ($(strip $(RUCKIG_DEP_VERSION)),)
|
||||
ruckig_VERSION=$(RUCKIG_DEP_VERSION)
|
||||
endif
|
||||
|
||||
ifeq ($(T_A),linux-x86_64)
|
||||
# Assume that the etherlab user library is done via
|
||||
# https://github.com/icshwi/etherlabmaster
|
||||
USR_INCLUDES += -I/opt/etherlab/include
|
||||
USR_CFLAGS += -fPIC
|
||||
USR_LDFLAGS += -L /opt/etherlab/lib
|
||||
USR_LDFLAGS += -lethercat
|
||||
USR_LDFLAGS += -Wl,-rpath=/opt/etherlab/lib
|
||||
else
|
||||
ifeq ($(T_A),linux-arm)
|
||||
# Assume that the etherlab user library is done via
|
||||
# https://github.com/icshwi/etherlabmaster
|
||||
USR_INCLUDES += -I/opt/etherlab/include
|
||||
USR_CFLAGS += -fPIC
|
||||
USR_LDFLAGS += -L /opt/etherlab/lib
|
||||
USR_LDFLAGS += -lethercat
|
||||
USR_LDFLAGS += -Wl,-rpath=/opt/etherlab/lib
|
||||
else
|
||||
# Assume that the etherlab user library is done via
|
||||
# Yocto ESS Linux bb recipe
|
||||
USR_INCLUDES += -I$(SDKTARGETSYSROOT)/usr/include/etherlab
|
||||
USR_CFLAGS += -fPIC
|
||||
USR_LDFLAGS += -L $(SDKTARGETSYSROOT)/usr/lib/etherlab
|
||||
USR_LDFLAGS += -lethercat
|
||||
USR_LDFLAGS += -Wl,-rpath=$(SDKTARGETSYSROOT)/usr/lib/etherlab
|
||||
USR_LDFLAGS += -lstdc++
|
||||
endif
|
||||
endif
|
||||
|
||||
APP:="."
|
||||
#APPDB:=$(APP)/Db
|
||||
#APPSRC:=$(APP)/src
|
||||
APPSRC:=src
|
||||
APPDB:=Db
|
||||
|
||||
USR_CFLAGS += -shared -fPIC -Wall -Wextra
|
||||
USR_LDFLAGS += -lstdc++
|
||||
USR_INCLUDES += -I$(where_am_I)$(APPSRC)
|
||||
|
||||
TEMPLATES += $(wildcard $(APPDB)/*.db)
|
||||
TEMPLATES += $(wildcard $(APPDB)/*.template)
|
||||
SOURCES += $(APPSRC)/ecmcPluginMotion.c
|
||||
SOURCES += $(APPSRC)/ecmcMotionPlgWrap.cpp
|
||||
SOURCES += $(APPSRC)/ecmcMotionPlg.cpp
|
||||
#SOURCES += $(APPSRC)/ecmcDataBuffer.cpp
|
||||
|
||||
SCRIPTS += startup.cmd
|
||||
SCRIPTS += addMotionObj.cmd
|
||||
|
||||
db:
|
||||
|
||||
.PHONY: db
|
||||
|
||||
vlibs:
|
||||
|
||||
.PHONY: vlibs
|
||||
|
||||
###
|
||||
0
ecmc_plugin_motion/Db/.keep
Normal file
0
ecmc_plugin_motion/Db/.keep
Normal file
272
ecmc_plugin_motion/Db/ecmcPluginMotion.template
Normal file
272
ecmc_plugin_motion/Db/ecmcPluginMotion.template
Normal file
@@ -0,0 +1,272 @@
|
||||
|
||||
|
||||
# Parameter 0 type=asynFloat64Array, name=plugin.motion_0.actpos_arr, value is undefined DONE
|
||||
# Parameter 1 type=asynFloat64Array, name=plugin.motion_0.setpos_arr, value is undefined DONE
|
||||
# Parameter 2 type=asynFloat64Array, name=plugin.motion_0.diffpos_arr, value is undefined DONE
|
||||
# Parameter 3 type=asynFloat64Array, name=plugin.motion_0.x_arr, value is undefined DONE
|
||||
# Parameter 4 type=asynInt32, name=plugin.motion_0.enable, value=1, status=0 DONE
|
||||
# Parameter 5 type=asynInt32, name=plugin.motion_0.cmd, value=0, status=0
|
||||
# Parameter 6 type=asynInt32, name=plugin.motion_0.status, value=0, status=0
|
||||
# Parameter 7 type=asynInt32, name=plugin.motion_0.trigg, value=0, status=0
|
||||
# Parameter 8 type=asynInt32, name=plugin.motion_0.buff_size, value=25, status=0
|
||||
# Parameter 9 type=asynFloat64, name=plugin.motion_0.samplerate, value=1000, status=0
|
||||
# Parameter 10 type=asynInt32, name=plugin.motion_0.elem_count, value=0, status=0
|
||||
# Parameter 11 type=asynInt32, name=plugin.motion_0.axis_id, value=1, status=0
|
||||
# Parameter 12 type=asynInt32, name=plugin.motion_0.mode, value=0, status=0
|
||||
|
||||
# Act pos
|
||||
record(waveform,"$(P)Plg-Mtn${INDEX}-PosAct-Arr"){
|
||||
info(asyn:FIFO, "1000")
|
||||
field(DESC, "Pos Act")
|
||||
field(PINI, "1")
|
||||
field(DTYP, "asynFloat64ArrayIn")
|
||||
field(INP, "@asyn(PLUGIN.MOTION_${INDEX},$(ADDR=0),$(TIMEOUT=1000))plugin.motion_${INDEX}.actpos_arr")
|
||||
field(FTVL, "DOUBLE")
|
||||
field(NELM, "$(NELM)")
|
||||
field(SCAN, "I/O Intr")
|
||||
field(TSE, "0")
|
||||
field(EGU, "${RAW_EGU= }")
|
||||
}
|
||||
|
||||
# Set pos
|
||||
record(waveform,"$(P)Plg-Mtn${INDEX}-PosSet-Arr"){
|
||||
info(asyn:FIFO, "1000")
|
||||
field(DESC, "Pos Set")
|
||||
field(PINI, "1")
|
||||
field(DTYP, "asynFloat64ArrayIn")
|
||||
field(INP, "@asyn(PLUGIN.MOTION_${INDEX},$(ADDR=0),$(TIMEOUT=1000))plugin.motion_${INDEX}.setpos_arr")
|
||||
field(FTVL, "DOUBLE")
|
||||
field(NELM, "$(NELM)")
|
||||
field(SCAN, "I/O Intr")
|
||||
field(TSE, "0")
|
||||
field(EGU, "${RAW_EGU= }")
|
||||
}
|
||||
|
||||
# Position Error
|
||||
record(waveform,"$(P)Plg-Mtn${INDEX}-PosErr-Arr"){
|
||||
info(asyn:FIFO, "1000")
|
||||
field(DESC, "Pos Error (diff)")
|
||||
field(PINI, "1")
|
||||
field(DTYP, "asynFloat64ArrayIn")
|
||||
field(INP, "@asyn(PLUGIN.MOTION_${INDEX},$(ADDR=0),$(TIMEOUT=1000))plugin.motion_${INDEX}.diffpos_arr")
|
||||
field(FTVL, "DOUBLE")
|
||||
field(NELM, "$(NELM)")
|
||||
field(SCAN, "I/O Intr")
|
||||
field(TSE, "0")
|
||||
field(EGU, "${RAW_EGU= }")
|
||||
}
|
||||
|
||||
# X axis time (reltive within buffer)
|
||||
record(waveform,"$(P)Plg-Mtn${INDEX}-Time-Arr"){
|
||||
info(asyn:FIFO, "1000")
|
||||
field(DESC, "Rel. time within buffer")
|
||||
field(PINI, "1")
|
||||
field(DTYP, "asynFloat64ArrayIn")
|
||||
field(INP, "@asyn(PLUGIN.MOTION_${INDEX},$(ADDR=0),$(TIMEOUT=1000))plugin.motion_${INDEX}.x_arr")
|
||||
field(FTVL, "DOUBLE")
|
||||
field(NELM, "$(NELM)")
|
||||
field(SCAN, "I/O Intr")
|
||||
field(TSE, "0")
|
||||
field(EGU, "s")
|
||||
}
|
||||
|
||||
# Axis Enable
|
||||
record(waveform,"$(P)Plg-Mtn${INDEX}-Ena-Arr"){
|
||||
info(asyn:FIFO, "1000")
|
||||
field(DESC, "Enable")
|
||||
field(PINI, "1")
|
||||
field(DTYP, "asynInt8ArrayIn")
|
||||
field(INP, "@asyn(PLUGIN.MOTION_${INDEX},$(ADDR=0),$(TIMEOUT=1000))plugin.motion_${INDEX}.enable_arr")
|
||||
field(FTVL, "CHAR")
|
||||
field(NELM, "$(NELM)")
|
||||
field(SCAN, "I/O Intr")
|
||||
field(TSE, "0")
|
||||
field(EGU, "s")
|
||||
}
|
||||
|
||||
# Axis Enabled
|
||||
record(waveform,"$(P)Plg-Mtn${INDEX}-EnaAct-Arr"){
|
||||
info(asyn:FIFO, "1000")
|
||||
field(DESC, "Enabled")
|
||||
field(PINI, "1")
|
||||
field(DTYP, "asynInt8ArrayIn")
|
||||
field(INP, "@asyn(PLUGIN.MOTION_${INDEX},$(ADDR=0),$(TIMEOUT=1000))plugin.motion_${INDEX}.enabled_arr")
|
||||
field(FTVL, "CHAR")
|
||||
field(NELM, "$(NELM)")
|
||||
field(SCAN, "I/O Intr")
|
||||
field(TSE, "0")
|
||||
field(EGU, "s")
|
||||
}
|
||||
|
||||
# Axis Busy
|
||||
record(waveform,"$(P)Plg-Mtn${INDEX}-Bsy-Arr"){
|
||||
info(asyn:FIFO, "1000")
|
||||
field(DESC, "Busy")
|
||||
field(PINI, "1")
|
||||
field(DTYP, "asynInt8ArrayIn")
|
||||
field(INP, "@asyn(PLUGIN.MOTION_${INDEX},$(ADDR=0),$(TIMEOUT=1000))plugin.motion_${INDEX}.busy_arr")
|
||||
field(FTVL, "CHAR")
|
||||
field(NELM, "$(NELM)")
|
||||
field(SCAN, "I/O Intr")
|
||||
field(TSE, "0")
|
||||
field(EGU, "s")
|
||||
}
|
||||
|
||||
# Axis Execute
|
||||
record(waveform,"$(P)Plg-Mtn${INDEX}-Exe-Arr"){
|
||||
info(asyn:FIFO, "1000")
|
||||
field(DESC, "Execute")
|
||||
field(PINI, "1")
|
||||
field(DTYP, "asynInt8ArrayIn")
|
||||
field(INP, "@asyn(PLUGIN.MOTION_${INDEX},$(ADDR=0),$(TIMEOUT=1000))plugin.motion_${INDEX}.execute_arr")
|
||||
field(FTVL, "CHAR")
|
||||
field(NELM, "$(NELM)")
|
||||
field(SCAN, "I/O Intr")
|
||||
field(TSE, "0")
|
||||
field(EGU, "s")
|
||||
}
|
||||
|
||||
# Axis Traj source
|
||||
record(waveform,"$(P)Plg-Mtn${INDEX}-TrjSrc-Arr"){
|
||||
info(asyn:FIFO, "1000")
|
||||
field(DESC, "Traj source")
|
||||
field(PINI, "1")
|
||||
field(DTYP, "asynInt8ArrayIn")
|
||||
field(INP, "@asyn(PLUGIN.MOTION_${INDEX},$(ADDR=0),$(TIMEOUT=1000))plugin.motion_${INDEX}.trajsrc_arr")
|
||||
field(FTVL, "CHAR")
|
||||
field(NELM, "$(NELM)")
|
||||
field(SCAN, "I/O Intr")
|
||||
field(TSE, "0")
|
||||
field(EGU, "s")
|
||||
}
|
||||
|
||||
# Axis Enc source
|
||||
record(waveform,"$(P)Plg-Mtn${INDEX}-EncSrc-Arr"){
|
||||
info(asyn:FIFO, "1000")
|
||||
field(DESC, "Enc source")
|
||||
field(PINI, "1")
|
||||
field(DTYP, "asynInt8ArrayIn")
|
||||
field(INP, "@asyn(PLUGIN.MOTION_${INDEX},$(ADDR=0),$(TIMEOUT=1000))plugin.motion_${INDEX}.encsrc_arr")
|
||||
field(FTVL, "CHAR")
|
||||
field(NELM, "$(NELM)")
|
||||
field(SCAN, "I/O Intr")
|
||||
field(TSE, "0")
|
||||
field(EGU, "s")
|
||||
}
|
||||
|
||||
# Axis At target
|
||||
record(waveform,"$(P)Plg-Mtn${INDEX}-AtTrg-Arr"){
|
||||
info(asyn:FIFO, "1000")
|
||||
field(DESC, "At target")
|
||||
field(PINI, "1")
|
||||
field(DTYP, "asynInt8ArrayIn")
|
||||
field(INP, "@asyn(PLUGIN.MOTION_${INDEX},$(ADDR=0),$(TIMEOUT=1000))plugin.motion_${INDEX}.attarget_arr")
|
||||
field(FTVL, "CHAR")
|
||||
field(NELM, "$(NELM)")
|
||||
field(SCAN, "I/O Intr")
|
||||
field(TSE, "0")
|
||||
field(EGU, "s")
|
||||
}
|
||||
|
||||
# Axis Error Id
|
||||
record(waveform,"$(P)Plg-Mtn${INDEX}-ErrId-Arr"){
|
||||
info(asyn:FIFO, "1000")
|
||||
field(DESC, "Error Id")
|
||||
field(PINI, "1")
|
||||
field(DTYP, "asynInt8ArrayIn")
|
||||
field(INP, "@asyn(PLUGIN.MOTION_${INDEX},$(ADDR=0),$(TIMEOUT=1000))plugin.motion_${INDEX}.error_arr")
|
||||
field(FTVL, "CHAR")
|
||||
field(NELM, "$(NELM)")
|
||||
field(SCAN, "I/O Intr")
|
||||
field(TSE, "0")
|
||||
field(EGU, "s")
|
||||
}
|
||||
|
||||
record(bo,"$(P)Plg-Mtn${INDEX}-EnaCmd-RB"){
|
||||
info(asyn:READBACK,"1")
|
||||
field(DESC, "Plg Enable")
|
||||
field(DTYP,"asynInt32")
|
||||
field(OUT, "@asyn(PLUGIN.MOTION_${INDEX},$(ADDR=0),$(TIMEOUT=1000))plugin.motion_${INDEX}.enable")
|
||||
field(ZNAM,"FALSE")
|
||||
field(ONAM,"TRUE")
|
||||
field(DOL, "0")
|
||||
field(VAL, "0")
|
||||
}
|
||||
|
||||
record(ao,"$(P)Plg-Mtn${INDEX}-AxCmd-RB"){
|
||||
info(asyn:READBACK,"1")
|
||||
field(DESC, "Axis")
|
||||
field(DTYP,"asynInt32")
|
||||
field(OUT, "@asyn(PLUGIN.MOTION_${INDEX},$(ADDR=0),$(TIMEOUT=1000))plugin.motion_${INDEX}.axis_id")
|
||||
field(DOL, "0")
|
||||
field(VAL, "1")
|
||||
}
|
||||
|
||||
record(ao,"$(P)Plg-Mtn${INDEX}-SmpHz-RB"){
|
||||
info(asyn:READBACK,"1")
|
||||
field(DESC, "Sample rate")
|
||||
field(DTYP,"asynInt32")
|
||||
field(OUT, "@asyn(PLUGIN.MOTION_${INDEX},$(ADDR=0),$(TIMEOUT=1000))plugin.motion_${INDEX}.samplerate")
|
||||
field(DOL, "0")
|
||||
field(VAL, "1")
|
||||
field(EGU, "Hz")
|
||||
}
|
||||
|
||||
record(ai,"$(P)Plg-Mtn${INDEX}-BuffSze"){
|
||||
info(asyn:READBACK,"1")
|
||||
field(DESC, "Buffer Size")
|
||||
field(DTYP,"asynInt32")
|
||||
field(OUT, "@asyn(PLUGIN.MOTION_${INDEX},$(ADDR=0),$(TIMEOUT=1000))plugin.motion_${INDEX}.buff_size")
|
||||
field(DOL, "0")
|
||||
field(VAL, "1")
|
||||
}
|
||||
|
||||
record(ai,"$(P)Plg-Mtn${INDEX}-ElmCnt"){
|
||||
info(asyn:READBACK,"1")
|
||||
field(DESC, "Elements in buffer count")
|
||||
field(DTYP,"asynInt32")
|
||||
field(OUT, "@asyn(PLUGIN.MOTION_${INDEX},$(ADDR=0),$(TIMEOUT=1000))plugin.motion_${INDEX}.elem_count")
|
||||
field(DOL, "0")
|
||||
field(VAL, "1")
|
||||
}
|
||||
|
||||
record(bo,"$(P)Plg-Mtn${INDEX}-TrgCmd-RB"){
|
||||
info(asyn:READBACK,"1")
|
||||
field(DESC, "Trigg command")
|
||||
field(DTYP,"asynInt32")
|
||||
field(OUT, "@asyn(PLUGIN.MOTION_${INDEX},$(ADDR=0),$(TIMEOUT=1000))plugin.motion_${INDEX}.trigg")
|
||||
field(ZNAM,"IDLE")
|
||||
field(ONAM,"TRIGG")
|
||||
field(VAL, "0")
|
||||
field(HIGH, 0.001)
|
||||
}
|
||||
|
||||
record(longout,"$(P)Plg-Mtn${INDEX}-Mde-RB"){
|
||||
info(asyn:READBACK,"1")
|
||||
field(DESC, "Mode selection")
|
||||
field(PINI, "1")
|
||||
field(TSE, "0")
|
||||
field(DTYP, "asynInt32")
|
||||
field(OUT, "@asyn(PLUGIN.MOTION_${INDEX},$(ADDR=0),$(TIMEOUT=1000))plugin.motion_${INDEX}.mode")
|
||||
field(SCAN, "Passive")
|
||||
}
|
||||
|
||||
record(longout,"$(P)Plg-Mtn${INDEX}-Cmd-RB"){
|
||||
info(asyn:READBACK,"1")
|
||||
field(DESC, "Command")
|
||||
field(PINI, "1")
|
||||
field(TSE, "0")
|
||||
field(DTYP, "asynInt32")
|
||||
field(OUT, "@asyn(PLUGIN.MOTION_${INDEX},$(ADDR=0),$(TIMEOUT=1000))plugin.motion_${INDEX}.cmd")
|
||||
field(SCAN, "Passive")
|
||||
}
|
||||
|
||||
record(longin,"$(P)Plg-Mtn${INDEX}-Stat"){
|
||||
info(asyn:READBACK,"1")
|
||||
field(DESC, "Status")
|
||||
field(PINI, "1")
|
||||
field(TSE, "0")
|
||||
field(DTYP, "asynInt32")
|
||||
field(OUT, "@asyn(PLUGIN.MOTION_${INDEX},$(ADDR=0),$(TIMEOUT=1000))plugin.motion_${INDEX}.status")
|
||||
field(SCAN, "Passive")
|
||||
}
|
||||
39
ecmc_plugin_motion/addMotionObj.cmd
Normal file
39
ecmc_plugin_motion/addMotionObj.cmd
Normal file
@@ -0,0 +1,39 @@
|
||||
|
||||
#==============================================================================
|
||||
# addMotionObj.cmd
|
||||
#-------------- Information:
|
||||
#- Description: ecmc_plugin_motion startup.cmd
|
||||
#-
|
||||
#- by Anders Sandström, Paul Scherrer Institute, 2023
|
||||
#- email: anders.sandstroem@psi.ch
|
||||
#-
|
||||
#-###############################################################################
|
||||
#-
|
||||
#- Arguments
|
||||
#- [mandatory]
|
||||
#- PLUGIN_ID = Plugin instansiation index, must be unique for each call
|
||||
#-
|
||||
#- [optional]
|
||||
#- AX = Axis id, default 1
|
||||
#- BUFF_SIZE = Buffer size, default 1000
|
||||
#- DBG = Debug mode, default 1
|
||||
#- ENA = Enable operation, default 1
|
||||
#- REPORT = Printout plugin details, default 1
|
||||
|
||||
#################################################################################
|
||||
|
||||
#- Load plugin: MOTION
|
||||
|
||||
#- Note: ECMC_PLG_MOTION_OBJ_INDEX is the index of motion object in motion plugin and not PLUGIN_ID.
|
||||
#- First loaded object will therefore have index
|
||||
epicsEnvSet(ECMC_PLG_MOTION_OBJ_INDEX,${ECMC_PLG_MOTION_OBJ_INDEX=0})
|
||||
|
||||
# Might need differet paths for PSI and ESS.. must check
|
||||
epicsEnvSet(ECMC_PLUGIN_FILNAME,"$(ecmc_plugin_motion_DIR)/lib/${EPICS_HOST_ARCH=linux-x86_64}/libecmc_plugin_motion.so")
|
||||
epicsEnvSet(ECMC_PLUGIN_CONFIG,"AXIS=${AX};BUFFER_SIZE=${BUFF_SIZE};DBG_PRINT=${DBG=1};ENABLE=${ENA=1};")
|
||||
${SCRIPTEXEC} ${ecmccfg_DIR}loadPlugin.cmd, "PLUGIN_ID=${PLUGIN_ID},FILE=${ECMC_PLUGIN_FILNAME},CONFIG='${ECMC_PLUGIN_CONFIG}', REPORT=${REPORT=1}"
|
||||
|
||||
dbLoadRecords(ecmcPluginMotion.template,"P=$(IOC):,INDEX=${ECMC_PLG_MOTION_OBJ_INDEX=0},NELM=${BUFF_SIZE=1000}")
|
||||
|
||||
#- Increase of index (need to keep track in order to load correct db)
|
||||
ecmcEpicsEnvSetCalc("ECMC_PLG_MOTION_OBJ_INDEX" ,${ECMC_PLG_MOTION_OBJ_INDEX=0}+1)
|
||||
0
ecmc_plugin_motion/src/.keep
Normal file
0
ecmc_plugin_motion/src/.keep
Normal file
300
ecmc_plugin_motion/src/ecmcDataBuffer.h
Normal file
300
ecmc_plugin_motion/src/ecmcDataBuffer.h
Normal file
@@ -0,0 +1,300 @@
|
||||
/*************************************************************************\
|
||||
* Copyright (c) 2019 European Spallation Source ERIC
|
||||
* ecmc is distributed subject to a Software License Agreement found
|
||||
* in file LICENSE that is included with this distribution.
|
||||
*
|
||||
* ecmcDataBuffer.h
|
||||
*
|
||||
* Created on: Mar 22, 2020
|
||||
* Author: anderssandstrom
|
||||
*
|
||||
\*************************************************************************/
|
||||
#ifndef ECMC_DATA_BUFFER_WRITE_H_
|
||||
#define ECMC_DATA_BUFFER_WRITE_H_
|
||||
|
||||
#include "ecmcAsynPortDriver.h"
|
||||
|
||||
#include <stdexcept>
|
||||
#include "inttypes.h"
|
||||
#include <string>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include "asynPortDriver.h"
|
||||
#include "epicsMutex.h"
|
||||
#include "ecmcMotionPlgDefs.h"
|
||||
|
||||
template <typename T>
|
||||
struct dataBuffer {
|
||||
T *data;
|
||||
int dataCounter;
|
||||
int id;
|
||||
};
|
||||
|
||||
/*
|
||||
Implements a data buffer with asyn callbacks.
|
||||
|
||||
The buffer uses two memory areas. When one mem area is full,
|
||||
writes are redirected to the other buffer. The full buffer then
|
||||
can be transferred to epics.
|
||||
|
||||
*/
|
||||
|
||||
template <typename T>
|
||||
class ecmcDataBuffer {
|
||||
public:
|
||||
|
||||
/** ecmc ecmcDataBuffer class
|
||||
* This object can throw:
|
||||
* - bad_alloc
|
||||
* - invalid_argument
|
||||
* - runtime_error
|
||||
* - out_of_range
|
||||
*/
|
||||
|
||||
ecmcDataBuffer(int objIndex,
|
||||
int bufferIndex,
|
||||
int bufferSize,
|
||||
int dbgMode,
|
||||
const char* asynSuffix,
|
||||
asynPortDriver *asynPort) {
|
||||
// prepare data buffers
|
||||
bufferSize_ = bufferSize;
|
||||
buffer1_.data = new T[bufferSize_];
|
||||
buffer2_.data = new T[bufferSize_];
|
||||
memset(&buffer1_.data[0],0,sizeof(T)*bufferSize_);
|
||||
memset(&buffer2_.data[0],0,sizeof(T)*bufferSize_);
|
||||
buffer1_.dataCounter = 0;
|
||||
buffer1_.id = 1;
|
||||
buffer2_.dataCounter = 0;
|
||||
buffer2_.id = 2;
|
||||
// add data to buffer
|
||||
bufferAdd_ = &buffer1_;
|
||||
// Buffer ready for writing to epics
|
||||
bufferWrite_ = &buffer2_;
|
||||
cfgDbgMode_ = dbgMode;
|
||||
destructs_ = 0;
|
||||
bufferSwitchMutex_ = epicsMutexCreate();
|
||||
bufferIndex_ = bufferIndex;
|
||||
objIndex_ = objIndex;
|
||||
asynPort_ = asynPort;
|
||||
asynSuffix_ = strdup(asynSuffix);
|
||||
asynParamId_ = -1;
|
||||
enable_ = true;
|
||||
|
||||
initAsyn();
|
||||
}
|
||||
~ecmcDataBuffer() {
|
||||
delete[] buffer1_.data;
|
||||
delete[] buffer2_.data;
|
||||
free(asynSuffix_);
|
||||
destructs_ = 1; // maybe need todo in other way..
|
||||
}
|
||||
|
||||
void addData(T data) {
|
||||
// Switch buffer if needed
|
||||
if(bufferAdd_->dataCounter >= bufferSize_) {
|
||||
switchBuffer();
|
||||
}
|
||||
|
||||
epicsMutexLock(bufferSwitchMutex_);
|
||||
bufferAdd_->data[bufferAdd_->dataCounter] = data;
|
||||
bufferAdd_->dataCounter++;
|
||||
epicsMutexUnlock(bufferSwitchMutex_);
|
||||
}
|
||||
|
||||
void clear() {
|
||||
//Fill data buffer
|
||||
memset(&buffer1_.data[0],0,sizeof(T)*bufferSize_);
|
||||
memset(&buffer2_.data[0],0,sizeof(T)*bufferSize_);
|
||||
buffer1_.dataCounter = 0;
|
||||
buffer2_.dataCounter = 0;
|
||||
}
|
||||
|
||||
void setEnable(bool enable) {
|
||||
enable_ = enable;
|
||||
}
|
||||
|
||||
bool getBufferFull() {
|
||||
return bufferAdd_->dataCounter == bufferSize_;
|
||||
}
|
||||
|
||||
void switchBuffer(){
|
||||
// ensure safe buffer switch
|
||||
epicsMutexLock(bufferSwitchMutex_);
|
||||
dataBuffer<T> *temp = bufferWrite_;
|
||||
bufferWrite_ = bufferAdd_;
|
||||
bufferAdd_ = temp;
|
||||
// start from 0 in new buffer
|
||||
bufferAdd_->dataCounter = 0;
|
||||
epicsMutexUnlock(bufferSwitchMutex_);
|
||||
}
|
||||
void writeBuffer();
|
||||
void initAsyn();
|
||||
|
||||
private:
|
||||
|
||||
static std::string to_string(int value){
|
||||
std::ostringstream os;
|
||||
os << value;
|
||||
return os.str();
|
||||
}
|
||||
|
||||
int destructs_;
|
||||
int cfgDbgMode_;
|
||||
int bufferSize_;
|
||||
int bufferIndex_;
|
||||
int objIndex_;
|
||||
epicsMutexId bufferSwitchMutex_;
|
||||
dataBuffer<T> buffer1_;
|
||||
dataBuffer<T> buffer2_;
|
||||
dataBuffer<T> *bufferAdd_;
|
||||
dataBuffer<T> *bufferWrite_;
|
||||
asynPortDriver *asynPort_;
|
||||
char *asynSuffix_;
|
||||
int asynParamId_;
|
||||
bool enable_;
|
||||
};
|
||||
|
||||
// specialized for epicsInt8
|
||||
template<> inline void ecmcDataBuffer<epicsInt8>::writeBuffer() {
|
||||
epicsMutexLock(bufferSwitchMutex_);
|
||||
// Write asyn
|
||||
asynPort_->lock();
|
||||
/*asynStatus stat=*/ asynPort_->doCallbacksInt8Array(&bufferWrite_->data[0], bufferSize_, asynParamId_,0);
|
||||
|
||||
asynPort_->unlock();
|
||||
|
||||
epicsMutexUnlock(bufferSwitchMutex_);
|
||||
}
|
||||
|
||||
// specialized for epicsInt16
|
||||
template<> inline void ecmcDataBuffer<epicsInt16>::writeBuffer() {
|
||||
epicsMutexLock(bufferSwitchMutex_);
|
||||
// Write asyn
|
||||
asynPort_->lock();
|
||||
/*asynStatus stat=*/ asynPort_->doCallbacksInt16Array(&bufferWrite_->data[0], bufferSize_, asynParamId_,0);
|
||||
|
||||
asynPort_->unlock();
|
||||
|
||||
epicsMutexUnlock(bufferSwitchMutex_);
|
||||
}
|
||||
|
||||
// specialized for epicsInt32
|
||||
template<> inline void ecmcDataBuffer<int32_t>::writeBuffer() {
|
||||
epicsMutexLock(bufferSwitchMutex_);
|
||||
// Write asyn
|
||||
asynPort_->lock();
|
||||
/*asynStatus stat=*/ asynPort_->doCallbacksInt32Array(&bufferWrite_->data[0], bufferSize_, asynParamId_,0);
|
||||
|
||||
asynPort_->unlock();
|
||||
|
||||
epicsMutexUnlock(bufferSwitchMutex_);
|
||||
}
|
||||
|
||||
// specialized for epicsInt64
|
||||
template<> inline void ecmcDataBuffer<int64_t>::writeBuffer() {
|
||||
epicsMutexLock(bufferSwitchMutex_);
|
||||
// Write asyn
|
||||
asynPort_->lock();
|
||||
/*asynStatus stat=*/ asynPort_->doCallbacksInt64Array(&bufferWrite_->data[0], bufferSize_, asynParamId_,0);
|
||||
|
||||
asynPort_->unlock();
|
||||
|
||||
epicsMutexUnlock(bufferSwitchMutex_);
|
||||
}
|
||||
|
||||
// specialized for epicsFloat32
|
||||
template<> inline void ecmcDataBuffer<epicsFloat32>::writeBuffer() {
|
||||
epicsMutexLock(bufferSwitchMutex_);
|
||||
// Write asyn
|
||||
asynPort_->lock();
|
||||
/*asynStatus stat=*/ asynPort_->doCallbacksFloat32Array(&bufferWrite_->data[0], bufferSize_, asynParamId_,0);
|
||||
|
||||
asynPort_->unlock();
|
||||
|
||||
epicsMutexUnlock(bufferSwitchMutex_);
|
||||
}
|
||||
|
||||
// specialized for epicsFloat64
|
||||
template<> inline void ecmcDataBuffer<epicsFloat64>::writeBuffer() {
|
||||
epicsMutexLock(bufferSwitchMutex_);
|
||||
// Write asyn
|
||||
asynPort_->lock();
|
||||
/*asynStatus stat=*/ asynPort_->doCallbacksFloat64Array(&bufferWrite_->data[0], bufferSize_, asynParamId_,0);
|
||||
|
||||
asynPort_->unlock();
|
||||
|
||||
epicsMutexUnlock(bufferSwitchMutex_);
|
||||
}
|
||||
|
||||
template<> inline void ecmcDataBuffer<epicsInt8>::initAsyn() {
|
||||
|
||||
std::string paramName = ECMC_PLUGIN_ASYN_PREFIX "_" + to_string(objIndex_) +
|
||||
"." + std::string(asynSuffix_);
|
||||
if( asynPort_->createParam(0, paramName.c_str(), asynParamInt8Array, &asynParamId_ ) != asynSuccess ) {
|
||||
throw std::runtime_error("Failed create asyn parameter rawdata");
|
||||
}
|
||||
// use buffer 1 for first callback
|
||||
writeBuffer();
|
||||
}
|
||||
|
||||
template<> inline void ecmcDataBuffer<epicsInt16>::initAsyn() {
|
||||
|
||||
std::string paramName = ECMC_PLUGIN_ASYN_PREFIX "_" + to_string(objIndex_) +
|
||||
"." + std::string(asynSuffix_);
|
||||
if( asynPort_->createParam(0, paramName.c_str(), asynParamInt16Array, &asynParamId_ ) != asynSuccess ) {
|
||||
throw std::runtime_error("Failed create asyn parameter rawdata");
|
||||
}
|
||||
// use buffer 1 for first callback
|
||||
writeBuffer();
|
||||
}
|
||||
|
||||
template<> inline void ecmcDataBuffer<epicsInt32>::initAsyn() {
|
||||
|
||||
std::string paramName = ECMC_PLUGIN_ASYN_PREFIX "_" + to_string(objIndex_) +
|
||||
"." + std::string(asynSuffix_);
|
||||
if( asynPort_->createParam(0, paramName.c_str(), asynParamInt32Array, &asynParamId_ ) != asynSuccess ) {
|
||||
throw std::runtime_error("Failed create asyn parameter rawdata");
|
||||
}
|
||||
// use buffer 1 for first callback
|
||||
writeBuffer();
|
||||
}
|
||||
|
||||
template<> inline void ecmcDataBuffer<epicsInt64>::initAsyn() {
|
||||
|
||||
std::string paramName = ECMC_PLUGIN_ASYN_PREFIX "_" + to_string(objIndex_) +
|
||||
"." + std::string(asynSuffix_);
|
||||
if( asynPort_->createParam(0, paramName.c_str(), asynParamInt64Array, &asynParamId_ ) != asynSuccess ) {
|
||||
throw std::runtime_error("Failed create asyn parameter rawdata");
|
||||
}
|
||||
// use buffer 1 for first callback
|
||||
writeBuffer();
|
||||
}
|
||||
|
||||
|
||||
template<> inline void ecmcDataBuffer<epicsFloat32>::initAsyn() {
|
||||
|
||||
std::string paramName = ECMC_PLUGIN_ASYN_PREFIX "_" + to_string(objIndex_) +
|
||||
"." + std::string(asynSuffix_);
|
||||
if( asynPort_->createParam(0, paramName.c_str(), asynParamFloat32Array, &asynParamId_ ) != asynSuccess ) {
|
||||
throw std::runtime_error("Failed create asyn parameter rawdata");
|
||||
}
|
||||
// use buffer 1 for first callback
|
||||
writeBuffer();
|
||||
}
|
||||
|
||||
template<> inline void ecmcDataBuffer<epicsFloat64>::initAsyn() {
|
||||
|
||||
std::string paramName = ECMC_PLUGIN_ASYN_PREFIX "_" + to_string(objIndex_) +
|
||||
"." + std::string(asynSuffix_);
|
||||
if( asynPort_->createParam(0, paramName.c_str(), asynParamFloat64Array, &asynParamId_ ) != asynSuccess ) {
|
||||
throw std::runtime_error("Failed create asyn parameter rawdata");
|
||||
}
|
||||
// use buffer 1 for first callback
|
||||
writeBuffer();
|
||||
}
|
||||
|
||||
#endif /* ECMC_DATA_BUFFER_WRITE_H_ */
|
||||
1039
ecmc_plugin_motion/src/ecmcMotionPlg.cpp
Normal file
1039
ecmc_plugin_motion/src/ecmcMotionPlg.cpp
Normal file
File diff suppressed because it is too large
Load Diff
167
ecmc_plugin_motion/src/ecmcMotionPlg.h
Normal file
167
ecmc_plugin_motion/src/ecmcMotionPlg.h
Normal file
@@ -0,0 +1,167 @@
|
||||
/*************************************************************************\
|
||||
* Copyright (c) 2023 Paul Scherrer Institute
|
||||
* ecmc is distributed subject to a Software License Agreement found
|
||||
* in file LICENSE that is included with this distribution.
|
||||
*
|
||||
* ecmcMotionPlg.h
|
||||
*
|
||||
* Created on: july 10, 2023
|
||||
* Author: anderssandstrom
|
||||
*
|
||||
\*************************************************************************/
|
||||
#ifndef ECMC_MOTION_PLG_H_
|
||||
#define ECMC_MOTION_PLG_H_
|
||||
|
||||
#include <stdexcept>
|
||||
#include "ecmcDataItem.h"
|
||||
#include "ecmcAsynPortDriver.h"
|
||||
#include "ecmcMotionPlgDefs.h"
|
||||
#include "inttypes.h"
|
||||
#include <string>
|
||||
#include "dbBase.h"
|
||||
#include "ecmcAxisBase.h"
|
||||
#include "ecmcDataBuffer.h"
|
||||
#include "epicsMutex.h"
|
||||
#include "epicsEvent.h"
|
||||
|
||||
#define ECMC_PLUGIN_MOTION_ERROR_AXIS_OUT_OF_RANGE 1
|
||||
|
||||
typedef enum TRIGG_MODE{
|
||||
NO_MODE = 0,
|
||||
CONT = 1,
|
||||
TRIGG = 2,
|
||||
} TRIGG_MODE;
|
||||
|
||||
class ecmcMotionPlg : public asynPortDriver {
|
||||
public:
|
||||
|
||||
/** ecmc Motion Plg class
|
||||
* This object can throw:
|
||||
* - bad_alloc
|
||||
* - invalid_argument
|
||||
* - runtime_error
|
||||
* - out_of_range
|
||||
*/
|
||||
ecmcMotionPlg(int objIndex, // index of this object
|
||||
char* configStr,
|
||||
char* portName);
|
||||
~ecmcMotionPlg();
|
||||
|
||||
// Add data to buffer (called from "external" callback)
|
||||
void dataUpdatedCallback(uint8_t* data,
|
||||
size_t size,
|
||||
ecmcEcDataType dt);
|
||||
// Call just before realtime because then all data sources should be available
|
||||
void connectToDataSource();
|
||||
void doWriteWorker(); // low prio worker thread
|
||||
void setEnable(int enable);
|
||||
void clearBuffers();
|
||||
void triggMotionObject();
|
||||
void executeMotionObject();
|
||||
virtual asynStatus writeInt32(asynUser *pasynUser, epicsInt32 value);
|
||||
virtual asynStatus readInt32(asynUser *pasynUser, epicsInt32 *value);
|
||||
virtual asynStatus readFloat64Array(asynUser *pasynUser, epicsFloat64 *value,
|
||||
size_t nElements, size_t *nIn);
|
||||
virtual asynStatus readFloat64(asynUser *pasynUser, epicsFloat64 *value);
|
||||
|
||||
|
||||
private:
|
||||
void parseConfigStr(char *configStr);
|
||||
void addDataToBuffer(double data);
|
||||
void initAsyn();
|
||||
static int dataTypeSupported(ecmcEcDataType dt);
|
||||
int setAxis(int axisId);
|
||||
int setMode(TRIGG_MODE mode);
|
||||
int setTrigg(int trigg);
|
||||
void writeBuffers();
|
||||
void switchBuffers();
|
||||
|
||||
|
||||
epicsMutexId axisMutex_;
|
||||
|
||||
double* xAxisArray_; // FFT x axis with freqs
|
||||
size_t elementsInBuffer_;
|
||||
double ecmcSampleRateHz_;
|
||||
int dataSourceLinked_; // To avoid link several times
|
||||
int command_;
|
||||
int status_;
|
||||
// ecmc callback handle for use when deregister at unload
|
||||
int callbackHandle_;
|
||||
int destructs_;
|
||||
int objectId_; // Unique object id
|
||||
int triggOnce_;
|
||||
int cycleCounter_;
|
||||
int ignoreCycles_;
|
||||
|
||||
// Config options
|
||||
int cfgDbgMode_; // Config: allow dbg printouts
|
||||
size_t cfgArraySize_; // Config: Data set size
|
||||
int cfgEnable_; // Config: Enable data acq./calc.
|
||||
double cfgSampleRateHz_; // Config: Sample rate (defaults to ecmc rate)
|
||||
double cfgDataSampleRateHz_;// Config: Sample for data
|
||||
int cfgAxisIndex_; // Config: Enable data acq./calc.
|
||||
TRIGG_MODE cfgMode_; // Config: Mode continous or triggered.
|
||||
|
||||
// Asyn
|
||||
int asynEnableId_; // Enable/disable acq./calcs
|
||||
int asynYActPosArrayId_;
|
||||
int asynYSetPosArrayId_;
|
||||
int asynYDiffPosArrayId_;
|
||||
int asynXAxisArrayId_;
|
||||
int asynTriggId_; // Trigg new measurement
|
||||
int asynAxisId_; // motion axis id
|
||||
int asynSRateId_; // Sample rate
|
||||
int asynElementsInBufferId_; // Current buffer index
|
||||
int asynBufferSizeId_; // Current buffer index
|
||||
int asynCommandId_;
|
||||
int asynStatusId_;
|
||||
int asynModeId_;
|
||||
|
||||
ecmcAxisBase *axis_;
|
||||
// Thread related
|
||||
//epicsEvent doCalcEvent_;
|
||||
|
||||
|
||||
// Some generic utility functions
|
||||
static uint8_t getUint8(uint8_t* data);
|
||||
static int8_t getInt8(uint8_t* data);
|
||||
static uint16_t getUint16(uint8_t* data);
|
||||
static int16_t getInt16(uint8_t* data);
|
||||
static uint32_t getUint32(uint8_t* data);
|
||||
static int32_t getInt32(uint8_t* data);
|
||||
static uint64_t getUint64(uint8_t* data);
|
||||
static int64_t getInt64(uint8_t* data);
|
||||
static float getFloat32(uint8_t* data);
|
||||
static double getFloat64(uint8_t* data);
|
||||
static size_t getEcDataTypeByteSize(ecmcEcDataType dt);
|
||||
static void printEcDataArray(uint8_t* data,
|
||||
size_t size,
|
||||
ecmcEcDataType dt,
|
||||
int objId);
|
||||
static void printComplexArray(std::complex<double>* fftBuff,
|
||||
size_t elements,
|
||||
int objId);
|
||||
static std::string to_string(int value);
|
||||
|
||||
ecmcDataBuffer<epicsFloat64> *actPosBuffer_;
|
||||
ecmcDataBuffer<epicsFloat64> *setPosBuffer_;
|
||||
ecmcDataBuffer<epicsFloat64> *diffPosBuffer_;
|
||||
ecmcDataBuffer<epicsFloat64> *xPosBuffer_;
|
||||
ecmcDataBuffer<epicsInt8> *enableBuffer_;
|
||||
ecmcDataBuffer<epicsInt8> *enabledBuffer_;
|
||||
ecmcDataBuffer<epicsInt8> *busyBuffer_;
|
||||
ecmcDataBuffer<epicsInt8> *executeBuffer_;
|
||||
ecmcDataBuffer<epicsInt8> *trajSourceBuffer_;
|
||||
ecmcDataBuffer<epicsInt8> *encSourceBuffer_;
|
||||
ecmcDataBuffer<epicsInt8> *atTargetBuffer_;
|
||||
ecmcDataBuffer<epicsInt32> *errorIdBuffer_;
|
||||
|
||||
bool bTriggInProgress_;
|
||||
double xdt_;
|
||||
double xTime_;
|
||||
epicsEvent doWriteEvent_;
|
||||
int writeBusy_;
|
||||
timespec writePauseTime_;
|
||||
};
|
||||
|
||||
#endif /* ECMC_MOTION_PLG_H_ */
|
||||
39
ecmc_plugin_motion/src/ecmcMotionPlgDefs.h
Normal file
39
ecmc_plugin_motion/src/ecmcMotionPlgDefs.h
Normal file
@@ -0,0 +1,39 @@
|
||||
/*************************************************************************\
|
||||
* Copyright (c) 2023 Paul Scherrer Institute
|
||||
* ecmc is distributed subject to a Software License Agreement found
|
||||
* in file LICENSE that is included with this distribution.
|
||||
*
|
||||
* ecmcMotionPlgDefs.h
|
||||
*
|
||||
* Created on: july 10, 2023
|
||||
* Author: anderssandstrom
|
||||
* Credits to https://github.com/sgreg/dynamic-loading
|
||||
*
|
||||
\*************************************************************************/
|
||||
|
||||
#ifndef ECMC_MOTION_PLG_DEFS_H_
|
||||
#define ECMC_MOTION_PLG_DEFS_H_
|
||||
|
||||
#define ECMC_PLUGIN_ASYN_PREFIX "plugin.motion"
|
||||
|
||||
// Options
|
||||
#define ECMC_PLUGIN_DBG_PRINT_OPTION_CMD "DBG_PRINT="
|
||||
#define ECMC_PLUGIN_AXIS_OPTION_CMD "AXIS="
|
||||
#define ECMC_PLUGIN_BUFFER_SIZE_OPTION_CMD "BUFFER_SIZE="
|
||||
#define ECMC_PLUGIN_RATE_OPTION_CMD "RATE="
|
||||
#define ECMC_PLUGIN_ENABLE_OPTION_CMD "ENABLE="
|
||||
#define ECMC_PLUGIN_MODE_OPTION_CMD "MODE="
|
||||
|
||||
// CONT, TRIGG
|
||||
#define ECMC_PLUGIN_MODE_CONT_OPTION "CONT"
|
||||
#define ECMC_PLUGIN_MODE_TRIGG_OPTION "TRIGG"
|
||||
|
||||
|
||||
/** Just one error code in "c" part of plugin
|
||||
(error handled with exceptions i c++ part) */
|
||||
#define ECMC_PLUGIN_MOTION_ERROR_CODE 1
|
||||
|
||||
// Default size (must be n²)
|
||||
#define ECMC_PLUGIN_DEFAULT_ARRAY_SIZE 4096
|
||||
|
||||
#endif /* ECMC_MOTION_PLG_DEFS_H_ */
|
||||
126
ecmc_plugin_motion/src/ecmcMotionPlgWrap.cpp
Normal file
126
ecmc_plugin_motion/src/ecmcMotionPlgWrap.cpp
Normal file
@@ -0,0 +1,126 @@
|
||||
/*************************************************************************\
|
||||
* Copyright (c) 2023 Paul Scherrer Institute
|
||||
* ecmc is distributed subject to a Software License Agreement found
|
||||
* in file LICENSE that is included with this distribution.
|
||||
*
|
||||
* ecmcMotionPlgWrap.cpp
|
||||
*
|
||||
* Created on: july 10, 2023
|
||||
* Author: anderssandstrom
|
||||
* Credits to https://github.com/sgreg/dynamic-loading
|
||||
*
|
||||
\*************************************************************************/
|
||||
|
||||
// Needed to get headers in ecmc right...
|
||||
#define ECMC_IS_PLUGIN
|
||||
|
||||
#include <vector>
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
#include "ecmcMotionPlgWrap.h"
|
||||
#include "ecmcMotionPlg.h"
|
||||
|
||||
#define ECMC_PLUGIN_MAX_PORTNAME_CHARS 64
|
||||
#define ECMC_PLUGIN_PORTNAME_PREFIX "PLUGIN.MOTION"
|
||||
|
||||
static std::vector<ecmcMotionPlg*> motionObjs;
|
||||
static int motionObjCounter = 0;
|
||||
static char portNameBuffer[ECMC_PLUGIN_MAX_PORTNAME_CHARS];
|
||||
|
||||
int createMotionObj(char* configStr) {
|
||||
|
||||
// create new ecmcMotionPlg object
|
||||
ecmcMotionPlg* motionObj = NULL;
|
||||
|
||||
// create asynport name for new object ()
|
||||
memset(portNameBuffer, 0, ECMC_PLUGIN_MAX_PORTNAME_CHARS);
|
||||
snprintf (portNameBuffer, ECMC_PLUGIN_MAX_PORTNAME_CHARS,
|
||||
ECMC_PLUGIN_PORTNAME_PREFIX "_%d", motionObjCounter);
|
||||
try {
|
||||
motionObj = new ecmcMotionPlg(motionObjCounter, configStr, portNameBuffer);
|
||||
}
|
||||
catch(std::exception& e) {
|
||||
if(motionObj) {
|
||||
delete motionObj;
|
||||
}
|
||||
printf("Exception: %s. Plugin will unload.\n",e.what());
|
||||
return ECMC_PLUGIN_MOTION_ERROR_CODE;
|
||||
}
|
||||
|
||||
motionObjs.push_back(motionObj);
|
||||
motionObjCounter++;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void deleteAllMotionObjs() {
|
||||
for(std::vector<ecmcMotionPlg*>::iterator pMotionObj = motionObjs.begin(); pMotionObj != motionObjs.end(); ++pMotionObj) {
|
||||
if(*pMotionObj) {
|
||||
delete (*pMotionObj);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int linkDataTomotionObjs() {
|
||||
for(std::vector<ecmcMotionPlg*>::iterator pMotionObj = motionObjs.begin(); pMotionObj != motionObjs.end(); ++pMotionObj) {
|
||||
if(*pMotionObj) {
|
||||
try {
|
||||
(*pMotionObj)->connectToDataSource();
|
||||
}
|
||||
catch(std::exception& e) {
|
||||
printf("Exception: %s. Plugin will unload.\n",e.what());
|
||||
return ECMC_PLUGIN_MOTION_ERROR_CODE;
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int enableMotionObj(int objIndex, int enable) {
|
||||
try {
|
||||
motionObjs.at(objIndex)->setEnable(enable);
|
||||
}
|
||||
catch(std::exception& e) {
|
||||
printf("Exception: %s. Motion object index out of range.\n",e.what());
|
||||
return ECMC_PLUGIN_MOTION_ERROR_CODE;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int clearMotionObj(int objIndex) {
|
||||
try {
|
||||
motionObjs.at(objIndex)->clearBuffers();
|
||||
}
|
||||
catch(std::exception& e) {
|
||||
printf("Exception: %s. Motion object index out of range.\n",e.what());
|
||||
return ECMC_PLUGIN_MOTION_ERROR_CODE;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int triggMotionObj(int objIndex) {
|
||||
try {
|
||||
motionObjs.at(objIndex)->triggMotionObject();
|
||||
}
|
||||
catch(std::exception& e) {
|
||||
printf("Exception: %s. Motion object index out of range.\n",e.what());
|
||||
return ECMC_PLUGIN_MOTION_ERROR_CODE;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int executeMotionObjs() {
|
||||
|
||||
for(std::vector<ecmcMotionPlg*>::iterator pMotionObj = motionObjs.begin(); pMotionObj != motionObjs.end(); ++pMotionObj) {
|
||||
if(*pMotionObj) {
|
||||
try {
|
||||
(*pMotionObj)->executeMotionObject();
|
||||
}
|
||||
catch(std::exception& e) {
|
||||
printf("Exception: %s. Plugin will unload.\n",e.what());
|
||||
return ECMC_PLUGIN_MOTION_ERROR_CODE;
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
109
ecmc_plugin_motion/src/ecmcMotionPlgWrap.h
Normal file
109
ecmc_plugin_motion/src/ecmcMotionPlgWrap.h
Normal file
@@ -0,0 +1,109 @@
|
||||
/*************************************************************************\
|
||||
* Copyright (c) 2023 Paul Scherrer Institute
|
||||
* ecmc is distributed subject to a Software License Agreement found
|
||||
* in file LICENSE that is included with this distribution.
|
||||
*
|
||||
* ecmcMotionPlgWrap.h
|
||||
*
|
||||
* Created on: july 10, 2023
|
||||
* Author: anderssandstrom
|
||||
*
|
||||
\*************************************************************************/
|
||||
#ifndef ECMC_MOTION_PLG_WRAP_H_
|
||||
#define ECMC_MOTION_PLG_WRAP_H_
|
||||
#include "ecmcMotionPlgDefs.h"
|
||||
|
||||
# ifdef __cplusplus
|
||||
extern "C" {
|
||||
# endif // ifdef __cplusplus
|
||||
|
||||
/** \brief Create new Motion object
|
||||
*
|
||||
* The plugin supports creation of multiple Motion objects\n
|
||||
* (if loaded several times).\n
|
||||
* The different fft are adressed by fftindex (in other functions below).\n
|
||||
* The first loaded fft get index 0 and then increases for each load.\n
|
||||
* This function call will create the custom asynparameters dedicated for this plugin.\
|
||||
* The configuration string needs to define a data source by:\n
|
||||
* "SOURCE=<data source>;"\n
|
||||
* Example:\n
|
||||
* "SOURCE=ec0.s1.AI_1";\n
|
||||
* \param[in] configStr Configuration string.\n
|
||||
*
|
||||
* \return 0 if success or otherwise an error code.\n
|
||||
*/
|
||||
int createMotionObj(char *configStr);
|
||||
|
||||
/** \brief Enable/disable Motion object
|
||||
*
|
||||
* Enable/disable Motion object. If disabled no data will be acquired\n
|
||||
* and no calculations will be made.\n
|
||||
* \param[in] fftIndex Index of fft (first loaded fft have index 0 then increases)\n
|
||||
* \param[in] enable enable/disable (1/0).\n
|
||||
*
|
||||
* \return 0 if success or otherwise an error code.\n
|
||||
*/
|
||||
int enableMotionObj(int objIndex, int enable);
|
||||
|
||||
/** \brief Clear FFT object\n
|
||||
*
|
||||
* Clears buffers. After this command the acquistion can start from scratch.\n
|
||||
* \param[in] fftIndex Index of fft (first loaded fft have index 0 then increases)\n
|
||||
*
|
||||
* \return 0 if success or otherwise an error code.\n
|
||||
*/
|
||||
int clearMotionObj(int objIndex);
|
||||
|
||||
/** \brief Set mode of FFT object
|
||||
*
|
||||
* The FFT object can measure in two differnt modes:\n
|
||||
* CONT(1) : Continious measurement (Acq data, calc, then Acq data ..)\n
|
||||
* TRIGG(2): Measurements are triggered from plc or over asyn and is only done once (untill next trigger)\n
|
||||
* \param[in] fftIndex Index of fft (first loaded fft have index 0 then increases)\n
|
||||
* \param[in] mode Mode CONT(1) or TRIGG(2)\n
|
||||
*
|
||||
* \return 0 if success or otherwise an error code.\n
|
||||
*/
|
||||
//int modeMotionObj(int objIndex, FFT_MODE mode);
|
||||
|
||||
/** \brief Trigger FFT object\n
|
||||
*
|
||||
* If in triggered mode a new measurment cycle is initiated (fft will be cleared first).\n
|
||||
* \param[in] fftIndex Index of fft (first loaded fft have index 0 then increases)\n
|
||||
*
|
||||
* \return 0 if success or otherwise an error code.\n
|
||||
*/
|
||||
int triggMotionObj(int objIndex);
|
||||
|
||||
|
||||
/** \brief execute FFT object\n
|
||||
*
|
||||
* If in triggered mode a new measurment cycle is initiated (fft will be cleared first).\n
|
||||
* \param[in] fftIndex Index of fft (first loaded fft have index 0 then increases)\n
|
||||
*
|
||||
* \return 0 if success or otherwise an error code.\n
|
||||
*/
|
||||
int executeMotionObjs();
|
||||
|
||||
/** \brief Link data to _all_ fft objects
|
||||
*
|
||||
* This tells the FFT lib to connect to ecmc to find it's data source.\n
|
||||
* This function should be called just before entering realtime since then all\n
|
||||
* data sources in ecmc will be definded (plc sources are compiled just before runtime\n
|
||||
* so are only fist accesible now).\n
|
||||
* \return 0 if success or otherwise an error code.\n
|
||||
*/
|
||||
int linkDataTomotionObjs();
|
||||
|
||||
/** \brief Deletes all created fft objects\n
|
||||
*
|
||||
* Should be called when destructs.\n
|
||||
*/
|
||||
|
||||
void deleteAllMotionObjs();
|
||||
|
||||
# ifdef __cplusplus
|
||||
}
|
||||
# endif // ifdef __cplusplus
|
||||
|
||||
#endif /* ECMC_MOTION_PLG_WRAP_H_ */
|
||||
298
ecmc_plugin_motion/src/ecmcPluginMotion.c
Normal file
298
ecmc_plugin_motion/src/ecmcPluginMotion.c
Normal file
@@ -0,0 +1,298 @@
|
||||
/*************************************************************************\
|
||||
* Copyright (c) 2023 Paul Scherrer Institute
|
||||
* ecmc is distributed subject to a Software License Agreement found
|
||||
* in file LICENSE that is included with this distribution.
|
||||
*
|
||||
* ecmcPluginExample.cpp
|
||||
*
|
||||
* Created on: july 10, 2023
|
||||
* Author: anderssandstrom
|
||||
*
|
||||
\*************************************************************************/
|
||||
|
||||
// Needed to get headers in ecmc right...
|
||||
#define ECMC_IS_PLUGIN
|
||||
#define ECMC_EXAMPLE_PLUGIN_VERSION 2
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif // ifdef __cplusplus
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "ecmcPluginDefs.h"
|
||||
#include "ecmcMotionPlgDefs.h"
|
||||
#include "ecmcMotionPlgWrap.h"
|
||||
|
||||
static int lastEcmcError = 0;
|
||||
static char* lastConfStr = NULL;
|
||||
|
||||
/** Optional.
|
||||
* Will be called once after successfull load into ecmc.
|
||||
* Return value other than 0 will be considered error.
|
||||
* configStr can be used for configuration parameters.
|
||||
**/
|
||||
int motionConstruct(char *configStr)
|
||||
{
|
||||
//This module is allowed to load several times so no need to check if loaded
|
||||
|
||||
// create FFT object and register data callback
|
||||
lastConfStr = strdup(configStr);
|
||||
return createMotionObj(configStr);
|
||||
}
|
||||
|
||||
/** Optional function.
|
||||
* Will be called once at unload.
|
||||
**/
|
||||
void motionDestruct(void)
|
||||
{
|
||||
deleteAllMotionObjs();
|
||||
if(lastConfStr){
|
||||
free(lastConfStr);
|
||||
}
|
||||
}
|
||||
|
||||
/** Optional function.
|
||||
* Will be called each realtime cycle if definded
|
||||
* ecmcError: Error code of ecmc. Makes it posible for
|
||||
* this plugin to react on ecmc errors
|
||||
* Return value other than 0 will be considered to be an error code in ecmc.
|
||||
**/
|
||||
int motionRealtime(int ecmcError)
|
||||
{
|
||||
executeMotionObjs();
|
||||
lastEcmcError = ecmcError;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** Link to data source here since all sources should be availabe at this stage
|
||||
* (for example ecmc PLC variables are defined only at enter of realtime)
|
||||
**/
|
||||
int motionEnterRT(){
|
||||
return linkDataTomotionObjs();
|
||||
}
|
||||
|
||||
/** Optional function.
|
||||
* Will be called once just before leaving realtime mode
|
||||
* Return value other than 0 will be considered error.
|
||||
**/
|
||||
int motionExitRT(void){
|
||||
return 0;
|
||||
}
|
||||
|
||||
//// Plc function for clear of buffers
|
||||
//double fft_clear(double index) {
|
||||
// return (double)clearFFT((int)index);
|
||||
//}
|
||||
//
|
||||
//// Plc function for enable
|
||||
//double fft_enable(double index, double enable) {
|
||||
// return (double)enableFFT((int)index, (int)enable);
|
||||
//}
|
||||
//
|
||||
//// Plc function for trigg new measurement (will clear buffers)
|
||||
//double fft_trigg(double index) {
|
||||
// return (double)triggFFT((int)index);
|
||||
//}
|
||||
//
|
||||
//// Plc function for enable
|
||||
//double fft_mode(double index, double mode) {
|
||||
// return (double)modeFFT((int)index, (FFT_MODE)((int)mode));
|
||||
//}
|
||||
//
|
||||
//// Plc function for enable
|
||||
//double fft_stat(double index) {
|
||||
// return (double)statFFT((int)index);
|
||||
//}
|
||||
|
||||
// Register data for plugin so ecmc know what to use
|
||||
struct ecmcPluginData pluginDataDef = {
|
||||
// Allways use ECMC_PLUG_VERSION_MAGIC
|
||||
.ifVersion = ECMC_PLUG_VERSION_MAGIC,
|
||||
// Name
|
||||
.name = "ecmcPlugin_Motion",
|
||||
// Description
|
||||
.desc = "Motion plugin for commissioning of ecmc motion axes.",
|
||||
// Option description
|
||||
.optionDesc = "\n "ECMC_PLUGIN_DBG_PRINT_OPTION_CMD"<1/0> : Enables/disables printouts from plugin, default = disabled.\n"
|
||||
" "ECMC_PLUGIN_AXIS_OPTION_CMD"<axis id> : Sets default source axis id.\n"
|
||||
" "ECMC_PLUGIN_BUFFER_SIZE_OPTION_CMD"<size> : Data points to collect, default = 4096.\n"
|
||||
" "ECMC_PLUGIN_RATE_OPTION_CMD"<rate hz> : Sampling rate in Hz"
|
||||
" "ECMC_PLUGIN_MODE_OPTION_CMD"<TRIGG/CONT> : Sampling rate in Hz"
|
||||
,
|
||||
// Plugin version
|
||||
.version = ECMC_EXAMPLE_PLUGIN_VERSION,
|
||||
// Optional construct func, called once at load. NULL if not definded.
|
||||
.constructFnc = motionConstruct,
|
||||
// Optional destruct func, called once at unload. NULL if not definded.
|
||||
.destructFnc = motionDestruct,
|
||||
// Optional func that will be called each rt cycle. NULL if not definded.
|
||||
.realtimeFnc = motionRealtime,
|
||||
// Optional func that will be called once just before enter realtime mode
|
||||
.realtimeEnterFnc = motionEnterRT,
|
||||
// Optional func that will be called once just before exit realtime mode
|
||||
.realtimeExitFnc = motionExitRT,
|
||||
// PLC funcs
|
||||
// .funcs[0] =
|
||||
// { /*----fft_clear----*/
|
||||
// // Function name (this is the name you use in ecmc plc-code)
|
||||
// .funcName = "fft_clear",
|
||||
// // Function description
|
||||
// .funcDesc = "double fft_clear(index) : Clear/reset fft[index].",
|
||||
// /**
|
||||
// * 7 different prototypes allowed (only doubles since reg in plc).
|
||||
// * Only funcArg${argCount} func shall be assigned the rest set to NULL.
|
||||
// **/
|
||||
// .funcArg0 = NULL,
|
||||
// .funcArg1 = fft_clear,
|
||||
// .funcArg2 = NULL,
|
||||
// .funcArg3 = NULL,
|
||||
// .funcArg4 = NULL,
|
||||
// .funcArg5 = NULL,
|
||||
// .funcArg6 = NULL,
|
||||
// .funcArg7 = NULL,
|
||||
// .funcArg8 = NULL,
|
||||
// .funcArg9 = NULL,
|
||||
// .funcArg10 = NULL,
|
||||
// .funcGenericObj = NULL,
|
||||
// },
|
||||
// .funcs[1] =
|
||||
// { /*----fft_enable----*/
|
||||
// // Function name (this is the name you use in ecmc plc-code)
|
||||
// .funcName = "fft_enable",
|
||||
// // Function description
|
||||
// .funcDesc = "double fft_enable(index, enable) : Set enable for fft[index].",
|
||||
// /**
|
||||
// * 7 different prototypes allowed (only doubles since reg in plc).
|
||||
// * Only funcArg${argCount} func shall be assigned the rest set to NULL.
|
||||
// **/
|
||||
// .funcArg0 = NULL,
|
||||
// .funcArg1 = NULL,
|
||||
// .funcArg2 = fft_enable,
|
||||
// .funcArg3 = NULL,
|
||||
// .funcArg4 = NULL,
|
||||
// .funcArg5 = NULL,
|
||||
// .funcArg6 = NULL,
|
||||
// .funcArg7 = NULL,
|
||||
// .funcArg8 = NULL,
|
||||
// .funcArg9 = NULL,
|
||||
// .funcArg10 = NULL,
|
||||
// .funcGenericObj = NULL,
|
||||
// },
|
||||
// .funcs[2] =
|
||||
// { /*----fft_trigg----*/
|
||||
// // Function name (this is the name you use in ecmc plc-code)
|
||||
// .funcName = "fft_trigg",
|
||||
// // Function description
|
||||
// .funcDesc = "double fft_trigg(index) : Trigg new measurement for fft[index]. Will clear buffers.",
|
||||
// /**
|
||||
// * 7 different prototypes allowed (only doubles since reg in plc).
|
||||
// * Only funcArg${argCount} func shall be assigned the rest set to NULL.
|
||||
// **/
|
||||
// .funcArg0 = NULL,
|
||||
// .funcArg1 = fft_trigg,
|
||||
// .funcArg2 = NULL,
|
||||
// .funcArg3 = NULL,
|
||||
// .funcArg4 = NULL,
|
||||
// .funcArg5 = NULL,
|
||||
// .funcArg6 = NULL,
|
||||
// .funcArg7 = NULL,
|
||||
// .funcArg8 = NULL,
|
||||
// .funcArg9 = NULL,
|
||||
// .funcArg10 = NULL,
|
||||
// .funcGenericObj = NULL,
|
||||
// },
|
||||
// .funcs[3] =
|
||||
// { /*----fft_mode----*/
|
||||
// // Function name (this is the name you use in ecmc plc-code)
|
||||
// .funcName = "fft_mode",
|
||||
// // Function description
|
||||
// .funcDesc = "double fft_mode(index, mode) : Set mode Cont(1)/Trigg(2) for fft[index].",
|
||||
// /**
|
||||
// * 7 different prototypes allowed (only doubles since reg in plc).
|
||||
// * Only funcArg${argCount} func shall be assigned the rest set to NULL.
|
||||
// **/
|
||||
// .funcArg0 = NULL,
|
||||
// .funcArg1 = NULL,
|
||||
// .funcArg2 = fft_mode,
|
||||
// .funcArg3 = NULL,
|
||||
// .funcArg4 = NULL,
|
||||
// .funcArg5 = NULL,
|
||||
// .funcArg6 = NULL,
|
||||
// .funcArg7 = NULL,
|
||||
// .funcArg8 = NULL,
|
||||
// .funcArg9 = NULL,
|
||||
// .funcArg10 = NULL,
|
||||
// .funcGenericObj = NULL,
|
||||
// },
|
||||
// .funcs[4] =
|
||||
// { /*----fft_stat----*/
|
||||
// // Function name (this is the name you use in ecmc plc-code)
|
||||
// .funcName = "fft_stat",
|
||||
// // Function description
|
||||
// .funcDesc = "double fft_stat(index) : Get status of fft (NO_STAT, IDLE, ACQ, CALC) for fft[index].",
|
||||
// /**
|
||||
// * 7 different prototypes allowed (only doubles since reg in plc).
|
||||
// * Only funcArg${argCount} func shall be assigned the rest set to NULL.
|
||||
// **/
|
||||
// .funcArg0 = NULL,
|
||||
// .funcArg1 = fft_stat,
|
||||
// .funcArg2 = NULL,
|
||||
// .funcArg3 = NULL,
|
||||
// .funcArg4 = NULL,
|
||||
// .funcArg5 = NULL,
|
||||
// .funcArg6 = NULL,
|
||||
// .funcArg7 = NULL,
|
||||
// .funcArg8 = NULL,
|
||||
// .funcArg9 = NULL,
|
||||
// .funcArg10 = NULL,
|
||||
// .funcGenericObj = NULL,
|
||||
// },
|
||||
.funcs[0] = {0}, // last element set all to zero..
|
||||
// PLC consts
|
||||
/* CONTINIOUS MODE = 1 */
|
||||
// .consts[0] = {
|
||||
// .constName = "fft_CONT",
|
||||
// .constDesc = "FFT Mode: Continious",
|
||||
// .constValue = CONT
|
||||
// },
|
||||
// /* TRIGGERED MODE = 2 */
|
||||
// .consts[1] = {
|
||||
// .constName = "fft_TRIGG",
|
||||
// .constDesc = "FFT Mode :Triggered",
|
||||
// .constValue = TRIGG
|
||||
// },
|
||||
// /* TRIGGERED MODE = 2 */
|
||||
// .consts[2] = {
|
||||
// .constName = "fft_NO_STAT",
|
||||
// .constDesc = "FFT Status: Invalid state",
|
||||
// .constValue = NO_STAT,
|
||||
// },
|
||||
// /* TRIGGERED MODE = 2 */
|
||||
// .consts[3] = {
|
||||
// .constName = "fft_IDLE",
|
||||
// .constDesc = "FFT Status: Idle state (waiting for trigger)",
|
||||
// .constValue = IDLE
|
||||
// },
|
||||
// /* TRIGGERED MODE = 2 */
|
||||
// .consts[4] = {
|
||||
// .constName = "fft_ACQ",
|
||||
// .constDesc = "FFT Status: Acquiring data",
|
||||
// .constValue = ACQ
|
||||
// },
|
||||
// /* TRIGGERED MODE = 2 */
|
||||
// .consts[5] = {
|
||||
// .constName = "fft_CALC",
|
||||
// .constDesc = "FFT Status: Calculating result",
|
||||
// .constValue = CALC
|
||||
// },
|
||||
.consts[0] = {0}, // last element set all to zero..
|
||||
};
|
||||
|
||||
ecmc_plugin_register(pluginDataDef);
|
||||
|
||||
# ifdef __cplusplus
|
||||
}
|
||||
# endif // ifdef __cplusplus
|
||||
32
ecmc_plugin_motion/startup.cmd
Normal file
32
ecmc_plugin_motion/startup.cmd
Normal file
@@ -0,0 +1,32 @@
|
||||
|
||||
#==============================================================================
|
||||
# startup.cmd
|
||||
#-------------- Information:
|
||||
#- Description: ecmc_plugin_motion startup.cmd
|
||||
#-
|
||||
#- by Anders Sandström, Paul Scherrer Institute, 2023
|
||||
#- email: anders.sandstroem@psi.ch
|
||||
#-
|
||||
#-###############################################################################
|
||||
#-
|
||||
#- Arguments
|
||||
#- [mandatory]
|
||||
#- PLUGIN_ID = Plugin instansiation index, must be unique for each call
|
||||
#-
|
||||
#- [optional]
|
||||
#- AX = Axis id, default 1
|
||||
#- BUFF_SIZE = Buffer size, default 1000
|
||||
#- DBG = Debug mode, default 1
|
||||
#- ENA = Enable operation, default 1
|
||||
#- REPORT = Printout plugin details, default 1
|
||||
|
||||
#################################################################################
|
||||
|
||||
#- Load plugin: MOTION
|
||||
|
||||
# Only allow call startup.cmd once. if more objects are needed then use addMotionObj.cmd directlly.
|
||||
|
||||
#- add One motion plugin object, only run startup once
|
||||
${ECMC_PLG_MOTION_INIT=""}${SCRIPTEXEC} $(ecmc_plugin_motion_DIR)addMotionObj.cmd "PLUGIN_ID=${PLUGIN_ID},AX=${AX=1},BUFF_SIZE=${BUFF_SIZE=1000},DBG=${DBG=1},ENA=${ENA=1},REPORT=${REPORT=1}"
|
||||
|
||||
epicsEnvSet("ECMC_PLG_MOTION_INIT" ,"#")
|
||||
0
iocsh/.keep
Normal file
0
iocsh/.keep
Normal file
93
iocsh/cfg/el7031.ax
Normal file
93
iocsh/cfg/el7031.ax
Normal file
@@ -0,0 +1,93 @@
|
||||
#General
|
||||
epicsEnvSet("ECMC_MOTOR_NAME", "Axis1")
|
||||
epicsEnvSet("ECMC_R", "Axis1-")
|
||||
epicsEnvSet("ECMC_AXIS_NO", "1")
|
||||
epicsEnvSet("ECMC_DESC", "Test EL7037")
|
||||
epicsEnvSet("ECMC_EGU", "deg") # Motor Record Unit
|
||||
epicsEnvSet("ECMC_PREC", "3") # Motor Record Precision
|
||||
epicsEnvSet("ECMC_AXISCONFIG", "") # Extra parameters to driver
|
||||
epicsEnvSet("ECMC_EC_AXIS_HEALTH", "") # Entry for axis health output (example: ec0.s1.binaryOutput01.0)
|
||||
epicsEnvSet("ECMC_MOD_RANGE" , "0") # Modulo range (traj setpoints and encoder values will be in range 0..ECMC_MOD_RANGE)
|
||||
epicsEnvSet("ECMC_MOD_TYPE", "0") # For positioning and MOD_RANGE is larger than 0: 0 = Normal, 1 = Always Fwd, 2 = Always Bwd, 3 = Closest Distance
|
||||
|
||||
#Encoder
|
||||
epicsEnvSet("ECMC_ENC_SCALE_NUM" "360")
|
||||
epicsEnvSet("ECMC_ENC_SCALE_DENOM" "12800")
|
||||
epicsEnvSet("ECMC_ENC_TYPE" "0") # Type: 0=Incremental, 1=Absolute
|
||||
epicsEnvSet("ECMC_ENC_BITS" "16") # Total bit count of encoder raw data
|
||||
epicsEnvSet("ECMC_ENC_ABS_BITS", "0") # Absolute bit count (for absolute encoders) always least significant part of ECMC_ENC_BITS
|
||||
epicsEnvSet("ECMC_ENC_ABS_OFFSET" "0") # Encoder offset in eng units (for absolute encoders)
|
||||
epicsEnvSet("ECMC_EC_ENC_ACTPOS", "ec0.s$(DRV_ID).positionActual01") # Ethercat entry for actual position input (encoder)
|
||||
epicsEnvSet("ECMC_EC_ENC_RESET", "") # Reset (if no encoder reset bit then leave empty)
|
||||
epicsEnvSet("ECMC_EC_ENC_ALARM_0", "") # Error 0 (if no encoder error bit then leave empty)
|
||||
epicsEnvSet("ECMC_EC_ENC_ALARM_1", "") # Error 1 (if no encoder error bit then leave empty)
|
||||
epicsEnvSet("ECMC_EC_ENC_ALARM_2", "") # Error 2 (if no encoder error bit then leave empty)
|
||||
epicsEnvSet("ECMC_EC_ENC_WARNING", "") # Warning (if no encoder warning bit then leave empty)
|
||||
|
||||
#Drive
|
||||
epicsEnvSet("ECMC_DRV_TYPE" "0") # Stepper: 0. DS402: 1 (DS402 = servos and advanced stepper drives)
|
||||
epicsEnvSet("ECMC_DRV_SCALE_NUM" "3600") # Fastest speed in engineering units
|
||||
epicsEnvSet("ECMC_DRV_SCALE_DENOM" "32768") # I/O range for ECMC_EC_ALIAS_DRV_VELO_SET
|
||||
epicsEnvSet("ECMC_EC_DRV_CONTROL", "ec0.s$(DRV_ID).driveControl01.0") # Ethercat entry for control word or bit output
|
||||
epicsEnvSet("ECMC_EC_DRV_STATUS", "ec0.s$(DRV_ID).driveStatus01.1") # Ethercat entry for status word or bit input
|
||||
epicsEnvSet("ECMC_EC_DRV_VELOCITY", "ec0.s$(DRV_ID).velocitySetpoint01") # Ethercat entry for velocity setpoint output
|
||||
epicsEnvSet("ECMC_EC_DRV_REDUCE_TORQUE", "ec0.s$(DRV_ID).driveControl01.2") # Ethercat entry for reduce torque output
|
||||
epicsEnvSet("ECMC_EC_DRV_BRAKE", "ec0.s$(DO_ID).binaryOutput01.0") # Ethercat entry for brake output
|
||||
epicsEnvSet("ECMC_DRV_BRAKE_OPEN_DLY_TIME", "1000") # Brake timing parameter in cycles (default 1kHz)
|
||||
epicsEnvSet("ECMC_DRV_BRAKE_CLOSE_AHEAD_TIME", "2000") # Brake timing parameter in cycles (default 1kHz)
|
||||
epicsEnvSet("ECMC_EC_DRV_RESET", "ec0.s$(DRV_ID).driveControl01.1") # Reset
|
||||
epicsEnvSet("ECMC_EC_DRV_ALARM_0", "ec0.s$(DRV_ID).driveStatus01.3") # Error
|
||||
epicsEnvSet("ECMC_EC_DRV_ALARM_1", "ec0.s$(DRV_ID).driveStatus01.7") # Stall
|
||||
epicsEnvSet("ECMC_EC_DRV_ALARM_2", "ec0.s$(DRV_ID).driveStatus01.14") # Sync error
|
||||
epicsEnvSet("ECMC_EC_DRV_WARNING", "ec0.s$(DRV_ID).driveStatus01.2") # Warning
|
||||
|
||||
#Trajectory
|
||||
epicsEnvSet("ECMC_VELO", "90.0")
|
||||
epicsEnvSet("ECMC_JOG_VEL", "90.0")
|
||||
epicsEnvSet("ECMC_JAR", "0.0") # JAR defaults to VELO/ACCL
|
||||
epicsEnvSet("ECMC_ACCS_EGU_PER_S2", "10")
|
||||
epicsEnvSet("ECMC_EMERG_DECEL", "100") # Emergency deceleration
|
||||
|
||||
#Homing
|
||||
epicsEnvSet("ECMC_HOME_PROC", "1")
|
||||
epicsEnvSet("ECMC_HOME_POS", "0.0")
|
||||
epicsEnvSet("ECMC_HOME_VEL_TO", "5")
|
||||
epicsEnvSet("ECMC_HOME_VEL_FRM", "4")
|
||||
epicsEnvSet("ECMC_HOME_ACC", "21")
|
||||
epicsEnvSet("ECMC_HOME_DEC", "100")
|
||||
epicsEnvSet("ECMC_HOME_POS_MOVE_ENA", "0") # Enable move to position after successfull homing
|
||||
epicsEnvSet("ECMC_HOME_POS_MOVE_TARG_POS","0") # Target position to go to after successfull homing
|
||||
|
||||
#Controller
|
||||
epicsEnvSet("ECMC_CNTRL_KP", "5.0")
|
||||
epicsEnvSet("ECMC_CNTRL_KI", "0.02")
|
||||
epicsEnvSet("ECMC_CNTRL_KD", "0.0")
|
||||
epicsEnvSet("ECMC_CNTRL_KFF", "1.0")
|
||||
|
||||
#Monitoring
|
||||
# Switches
|
||||
epicsEnvSet("ECMC_EC_MON_LOWLIM", "ec0.s$(DRV_ID).ONE.0") # Ethercat entry for low limit switch input
|
||||
epicsEnvSet("ECMC_EC_MON_HIGHLIM", "ec0.s$(DRV_ID).ONE.0") # Ethercat entry for high limit switch inpuit
|
||||
epicsEnvSet("ECMC_EC_MON_HOME_SWITCH", "ec0.s$(DRV_ID).ONE.0") # Ethercat entry for home switch input
|
||||
epicsEnvSet("ECMC_EC_MON_EXT_INTERLOCK", "ec0.s$(DRV_ID).ONE.0") # Ethercat entry for external interlock input
|
||||
|
||||
# Softlimits (disable with 0,0,0)
|
||||
epicsEnvSet("ECMC_SOFT_LOW_LIM", "$(SM_DLLM=0)")
|
||||
epicsEnvSet("ECMC_SOFT_HIGH_LIM", "$(SM_DHLM=0)")
|
||||
epicsEnvSet("ECMC_DXLM_ENABLE", "0")
|
||||
|
||||
# Position lag
|
||||
epicsEnvSet("ECMC_MON_LAG_MON_TOL", "5")
|
||||
epicsEnvSet("ECMC_MON_LAG_MON_TIME", "100")
|
||||
epicsEnvSet("ECMC_MON_LAG_MON_ENA", "0")
|
||||
|
||||
# At target
|
||||
epicsEnvSet("ECMC_MON_AT_TARGET_TOL", "0.1")
|
||||
epicsEnvSet("ECMC_MON_AT_TARGET_TIME", "100")
|
||||
epicsEnvSet("ECMC_MON_AT_TARGET_ENA", "1")
|
||||
|
||||
# Velocity
|
||||
epicsEnvSet("ECMC_MON_VELO_MAX", "21000.0")
|
||||
epicsEnvSet("ECMC_MON_VELO_MAX_TRAJ_TIME","100")
|
||||
epicsEnvSet("ECMC_MON_VELO_MAX_DRV_TIME", "200")
|
||||
epicsEnvSet("ECMC_MON_VELO_MAX_ENA", "0")
|
||||
9
iocsh/plc/plc_no_ec_fft_sin.plc
Normal file
9
iocsh/plc/plc_no_ec_fft_sin.plc
Normal file
@@ -0,0 +1,9 @@
|
||||
###############################################################################################
|
||||
# For help on syntax, variables and functions, please read the file: "plcSyntaxHelp.plc"
|
||||
#
|
||||
# PLC Functionality Demo:
|
||||
# No hardware related variables
|
||||
#
|
||||
|
||||
static.time:=ec_get_time()/1E9;
|
||||
static.sineval:=sin(2*pi*${FREQ=10}*static.time);
|
||||
329
iocsh/pvs.log
Normal file
329
iocsh/pvs.log
Normal file
@@ -0,0 +1,329 @@
|
||||
IOC_TEST:m0s001-Drv01-Cmd-RB
|
||||
IOC_TEST:m0s001-Drv01-Spd-RB
|
||||
IOC_TEST:m0s001-Enc01-PosAct
|
||||
IOC_TEST:m0s001-Enc01-LtchPosAct
|
||||
IOC_TEST:m0s001-Enc01-Cmd-RB
|
||||
IOC_TEST:m0s001-Enc01-PosCmd-RB
|
||||
IOC_TEST:Axis1-Vel-RB
|
||||
IOC_TEST:Axis1-Acc-RB
|
||||
IOC_TEST:Axis1-EncAct
|
||||
IOC_TEST:Axis1-CfgSREV-RB
|
||||
IOC_TEST:Axis1-CfgUREV-RB
|
||||
IOC_TEST:Axis1-CfgPMIN-RB
|
||||
IOC_TEST:Axis1-CfgPMAX-RB
|
||||
IOC_TEST:Axis1-CfgSPDB-RB
|
||||
IOC_TEST:Axis1-CfgRDBD-RB
|
||||
IOC_TEST:Axis1-CfgRDBD-Tim-RB
|
||||
IOC_TEST:Axis1-CfgPOSLAG-RB
|
||||
IOC_TEST:Axis1-CfgPOSLAG-Tim-RB
|
||||
IOC_TEST:Axis1-CfgDHLM-RB
|
||||
IOC_TEST:Axis1-CfgDLLM-RB
|
||||
IOC_TEST:Axis1-CfgVELO-RB
|
||||
IOC_TEST:Axis1-CfgVMAX-RB
|
||||
IOC_TEST:Axis1-CfgJVEL-RB
|
||||
IOC_TEST:Axis1-CfgACCS-RB
|
||||
IOC_TEST:Axis1-HomPos-RB
|
||||
IOC_TEST:Axis1-PosAct
|
||||
IOC_TEST:Axis1-VelAct
|
||||
IOC_TEST:Axis1-PosSet
|
||||
IOC_TEST:Axis1-PosErr
|
||||
IOC_TEST:Axis1-PLC-Err
|
||||
IOC_TEST:MCU-AppMode
|
||||
IOC_TEST:MCU-ErrId
|
||||
IOC_TEST:MCU-ThdLatMin
|
||||
IOC_TEST:MCU-ThdLatMax
|
||||
IOC_TEST:MCU-ThdPrdMin
|
||||
IOC_TEST:MCU-ThdPrdMax
|
||||
IOC_TEST:MCU-ThdExeMin
|
||||
IOC_TEST:MCU-ThdExeMax
|
||||
IOC_TEST:MCU-ThdSndMin
|
||||
IOC_TEST:MCU-ThdSndMax
|
||||
IOC_TEST:m0s001-Drv01-WrnAlrm
|
||||
IOC_TEST:m0s001-Drv01-ErrAlrm
|
||||
IOC_TEST:m0s001-Drv01-StlAlrm
|
||||
IOC_TEST:m0s001-Drv01-SyncErrAlrm
|
||||
IOC_TEST:m0s001-Enc01-ExtLtchOK
|
||||
IOC_TEST:m0s001-Enc01-OpnCrctAlrm
|
||||
IOC_TEST:m0s001-Enc01-WrnAlrm
|
||||
IOC_TEST:m0s001-Enc01-SyncErrAlrm
|
||||
IOC_TEST:m0s001-Online
|
||||
IOC_TEST:m0s001-Operational
|
||||
IOC_TEST:m0s001-Alstate-Init
|
||||
IOC_TEST:m0s001-Alstate-Preop
|
||||
IOC_TEST:m0s001-Alstate-Safeop
|
||||
IOC_TEST:m0s001-Alstate-Op
|
||||
IOC_TEST:m0s002-BO01-RB
|
||||
IOC_TEST:m0s002-BO02-RB
|
||||
IOC_TEST:m0s002-BO03-RB
|
||||
IOC_TEST:m0s002-BO04-RB
|
||||
IOC_TEST:m0s002-BO05-RB
|
||||
IOC_TEST:m0s002-BO06-RB
|
||||
IOC_TEST:m0s002-BO07-RB
|
||||
IOC_TEST:m0s002-BO08-RB
|
||||
IOC_TEST:m0s002-BO09-RB
|
||||
IOC_TEST:m0s002-BO10-RB
|
||||
IOC_TEST:m0s002-BO11-RB
|
||||
IOC_TEST:m0s002-BO12-RB
|
||||
IOC_TEST:m0s002-BO13-RB
|
||||
IOC_TEST:m0s002-BO14-RB
|
||||
IOC_TEST:m0s002-BO15-RB
|
||||
IOC_TEST:m0s002-BO16-RB
|
||||
IOC_TEST:m0s002-BO01-OvrTmpAlrm
|
||||
IOC_TEST:m0s002-BO01-OpnLdAlrm
|
||||
IOC_TEST:m0s002-BO01-OvrCurrAlrm
|
||||
IOC_TEST:m0s002-BO01-ShrtCircAlrm
|
||||
IOC_TEST:m0s002-BO02-OvrTmpAlrm
|
||||
IOC_TEST:m0s002-BO02-OpnLdAlrm
|
||||
IOC_TEST:m0s002-BO02-OvrCurrAlrm
|
||||
IOC_TEST:m0s002-BO02-ShrtCircAlrm
|
||||
IOC_TEST:m0s002-BO03-OvrTmpAlrm
|
||||
IOC_TEST:m0s002-BO03-OpnLdAlrm
|
||||
IOC_TEST:m0s002-BO03-OvrCurrAlrm
|
||||
IOC_TEST:m0s002-BO03-ShrtCircAlrm
|
||||
IOC_TEST:m0s002-BO04-OvrTmpAlrm
|
||||
IOC_TEST:m0s002-BO04-OpnLdAlrm
|
||||
IOC_TEST:m0s002-BO04-OvrCurrAlrm
|
||||
IOC_TEST:m0s002-BO04-ShrtCircAlrm
|
||||
IOC_TEST:m0s002-BO05-OvrTmpAlrm
|
||||
IOC_TEST:m0s002-BO05-OpnLdAlrm
|
||||
IOC_TEST:m0s002-BO05-OvrCurrAlrm
|
||||
IOC_TEST:m0s002-BO05-ShrtCircAlrm
|
||||
IOC_TEST:m0s002-BO06-OvrTmpAlrm
|
||||
IOC_TEST:m0s002-BO06-OpnLdAlrm
|
||||
IOC_TEST:m0s002-BO06-OvrCurrAlrm
|
||||
IOC_TEST:m0s002-BO06-ShrtCircAlrm
|
||||
IOC_TEST:m0s002-BO07-OvrTmpAlrm
|
||||
IOC_TEST:m0s002-BO07-OpnLdAlrm
|
||||
IOC_TEST:m0s002-BO07-OvrCurrAlrm
|
||||
IOC_TEST:m0s002-BO07-ShrtCircAlrm
|
||||
IOC_TEST:m0s002-BO08-OvrTmpAlrm
|
||||
IOC_TEST:m0s002-BO08-OpnLdAlrm
|
||||
IOC_TEST:m0s002-BO08-OvrCurrAlrm
|
||||
IOC_TEST:m0s002-BO08-ShrtCircAlrm
|
||||
IOC_TEST:m0s002-BO09-OvrTmpAlrm
|
||||
IOC_TEST:m0s002-BO09-OpnLdAlrm
|
||||
IOC_TEST:m0s002-BO09-OvrCurrAlrm
|
||||
IOC_TEST:m0s002-BO09-ShrtCircAlrm
|
||||
IOC_TEST:m0s002-BO10-OvrTmpAlrm
|
||||
IOC_TEST:m0s002-BO10-OpnLdAlrm
|
||||
IOC_TEST:m0s002-BO10-OvrCurrAlrm
|
||||
IOC_TEST:m0s002-BO10-ShrtCircAlrm
|
||||
IOC_TEST:m0s002-BO11-OvrTmpAlrm
|
||||
IOC_TEST:m0s002-BO11-OpnLdAlrm
|
||||
IOC_TEST:m0s002-BO11-OvrCurrAlrm
|
||||
IOC_TEST:m0s002-BO11-ShrtCircAlrm
|
||||
IOC_TEST:m0s002-BO12-OvrTmpAlrm
|
||||
IOC_TEST:m0s002-BO12-OpnLdAlrm
|
||||
IOC_TEST:m0s002-BO12-OvrCurrAlrm
|
||||
IOC_TEST:m0s002-BO12-ShrtCircAlrm
|
||||
IOC_TEST:m0s002-BO13-OvrTmpAlrm
|
||||
IOC_TEST:m0s002-BO13-OpnLdAlrm
|
||||
IOC_TEST:m0s002-BO13-OvrCurrAlrm
|
||||
IOC_TEST:m0s002-BO13-ShrtCircAlrm
|
||||
IOC_TEST:m0s002-BO14-OvrTmpAlrm
|
||||
IOC_TEST:m0s002-BO14-OpnLdAlrm
|
||||
IOC_TEST:m0s002-BO14-OvrCurrAlrm
|
||||
IOC_TEST:m0s002-BO14-ShrtCircAlrm
|
||||
IOC_TEST:m0s002-BO15-OvrTmpAlrm
|
||||
IOC_TEST:m0s002-BO15-OpnLdAlrm
|
||||
IOC_TEST:m0s002-BO15-OvrCurrAlrm
|
||||
IOC_TEST:m0s002-BO15-ShrtCircAlrm
|
||||
IOC_TEST:m0s002-BO16-OvrTmpAlrm
|
||||
IOC_TEST:m0s002-BO16-OpnLdAlrm
|
||||
IOC_TEST:m0s002-BO16-OvrCurrAlrm
|
||||
IOC_TEST:m0s002-BO16-ShrtCircAlrm
|
||||
IOC_TEST:m0s002-Online
|
||||
IOC_TEST:m0s002-Operational
|
||||
IOC_TEST:m0s002-Alstate-Init
|
||||
IOC_TEST:m0s002-Alstate-Preop
|
||||
IOC_TEST:m0s002-Alstate-Safeop
|
||||
IOC_TEST:m0s002-Alstate-Op
|
||||
IOC_TEST:Axis1-EnaCmd-RB
|
||||
IOC_TEST:Axis1-EnaAct
|
||||
IOC_TEST:Axis1-ExeCmd-RB
|
||||
IOC_TEST:Axis1-Busy
|
||||
IOC_TEST:Axis1-AtTarget
|
||||
IOC_TEST:Axis1-Moving
|
||||
IOC_TEST:Axis1-LimFwd
|
||||
IOC_TEST:Axis1-LimBwd
|
||||
IOC_TEST:Axis1-HomeSwitch
|
||||
IOC_TEST:Axis1-Homed
|
||||
IOC_TEST:Axis1-InRT
|
||||
IOC_TEST:Axis1-TrjSrcTyp-RB
|
||||
IOC_TEST:Axis1-EncSrcTyp-RB
|
||||
IOC_TEST:Axis1-CmdFrmPLCCmd-RB
|
||||
IOC_TEST:Axis1-SftLimFwdEna-RB
|
||||
IOC_TEST:Axis1-SftLimBwdEna-RB
|
||||
IOC_TEST:Axis1-PLC-EnaCmd-RB
|
||||
IOC_TEST:Axis1-PLC-FirstScan
|
||||
IOC_TEST:Axis1-Err
|
||||
IOC_TEST:Axis1-Wrn
|
||||
IOC_TEST:MCU-ThdRTPrioOK
|
||||
IOC_TEST:MCU-ThdMemLocked
|
||||
IOC_TEST:m0-LinkUp
|
||||
IOC_TEST:m0-AlStates-Init
|
||||
IOC_TEST:m0-AlStates-Preop
|
||||
IOC_TEST:m0-AlStates-Safeop
|
||||
IOC_TEST:m0-AlStates-Op
|
||||
IOC_TEST:m0-Dom-RedunActive
|
||||
IOC_TEST:m0-Dom-WC-Zero
|
||||
IOC_TEST:m0-Dom-WC-Incomplete
|
||||
IOC_TEST:m0-Dom-WC-Complete
|
||||
IOC_TEST:m0-Stat-OK
|
||||
REQMOD:raspberrypi-19888:exit
|
||||
REQMOD:raspberrypi-19888:MODULES
|
||||
REQMOD:raspberrypi-19888:VERSIONS
|
||||
REQMOD:raspberrypi-19888:MOD_VER
|
||||
IOC_TEST:Axis1-Arr-Stat
|
||||
IOC_TEST:Axis1-PLC-Expr-RB
|
||||
IOC_TEST:Plg-Mtn0-PosAct-Arr
|
||||
IOC_TEST:Plg-Mtn0-PosSet-Arr
|
||||
IOC_TEST:Plg-Mtn0-PosErr-Arr
|
||||
IOC_TEST:Plg-Mtn0-Time-Arr
|
||||
IOC_TEST:MCU-ErrMsg
|
||||
IOC_TEST:MCU-Updated
|
||||
IOC_TEST:m0s001-Enc01-LtchCmd
|
||||
IOC_TEST:Axis1-MtnCmd
|
||||
IOC_TEST:Axis1-movVelCmd
|
||||
IOC_TEST:Axis1-movRelCmd
|
||||
IOC_TEST:Axis1-movAbsCmd
|
||||
IOC_TEST:Axis1-movHomCmd
|
||||
IOC_TEST:Axis1-HomProc-RB
|
||||
IOC_TEST:Axis1-Type
|
||||
IOC_TEST:Axis1-DrvType
|
||||
IOC_TEST:Axis1-TrajType
|
||||
IOC_TEST:m0s001-One
|
||||
IOC_TEST:m0s001-Zero
|
||||
IOC_TEST:m0s002-One
|
||||
IOC_TEST:m0s002-Zero
|
||||
IOC_TEST:Axis1-DIR_
|
||||
IOC_TEST:Axis1-ErrRst
|
||||
IOC_TEST:Axis1-HomProc
|
||||
IOC_TEST:Axis1-MtnCmdData
|
||||
IOC_TEST:m0s001-Stat
|
||||
IOC_TEST:m0s002-Stat
|
||||
IOC_TEST:Axis1-MR-ErrId
|
||||
IOC_TEST:Axis1-CfgRDBD-En-RB
|
||||
IOC_TEST:Axis1-CfgPOSLAG-En-RB
|
||||
IOC_TEST:Axis1-CfgDHLM-En-RB
|
||||
IOC_TEST:Axis1-CfgDLLM-En-RB
|
||||
IOC_TEST:Axis1-Stat
|
||||
IOC_TEST:Axis1-ErrId
|
||||
IOC_TEST:Axis1-WrnId
|
||||
IOC_TEST:m0-Stat
|
||||
IOC_TEST:m0-SlvCntr
|
||||
IOC_TEST:m0-MemmapCntr
|
||||
IOC_TEST:m0-DomFailCntrTot
|
||||
IOC_TEST:m0-EntryCntr
|
||||
IOC_TEST:m0-Dom-Stat
|
||||
IOC_TEST:MCU-Cfg-Info
|
||||
IOC_TEST:MCU-Cfg-Naming
|
||||
IOC_TEST:MCU-Cfg-Mode
|
||||
IOC_TEST:MCU-Cfg-PVA
|
||||
IOC_TEST:Axis1-DbgStrToLOG
|
||||
IOC_TEST:MCU-Cfg-AX1-Pfx
|
||||
IOC_TEST:MCU-Cfg-AX1-Nam
|
||||
IOC_TEST:MCU-Cfg-AX1-PfxNam
|
||||
IOC_TEST:m0s001-EntryCntr
|
||||
IOC_TEST:m0s002-EntryCntr
|
||||
IOC_TEST:Axis1-SeqState
|
||||
IOC_TEST:Axis1-LastIlock
|
||||
IOC_TEST:m0-SlvRsp
|
||||
IOC_TEST:m0-Dom-WC
|
||||
IOC_TEST:m0s001-Enc01-LtchRst
|
||||
IOC_TEST:Axis1-Cmd_
|
||||
REQMOD:raspberrypi-19888:BaseVersion
|
||||
REQMOD:raspberrypi-19888:require_VER
|
||||
REQMOD:raspberrypi-19888:ecmccfg_VER
|
||||
REQMOD:raspberrypi-19888:asyn_VER
|
||||
REQMOD:raspberrypi-19888:exprtk_VER
|
||||
REQMOD:raspberrypi-19888:motor_VER
|
||||
REQMOD:raspberrypi-19888:ruckig_VER
|
||||
REQMOD:raspberrypi-19888:ecmc_VER
|
||||
IOC_TEST:m0s001-HWType
|
||||
IOC_TEST:m0s002-HWType
|
||||
IOC_TEST:Axis1-MsgTxt
|
||||
REQMOD:raspberrypi-19888:ecmc_plugin_motion_VER
|
||||
IOC_TEST:m0s001-Drv01-Stat
|
||||
IOC_TEST:m0s001-Enc01-Stat
|
||||
IOC_TEST:m0s001-Stat_
|
||||
IOC_TEST:m0s002-BO01-Stat
|
||||
IOC_TEST:m0s002-BO02-Stat
|
||||
IOC_TEST:m0s002-BO03-Stat
|
||||
IOC_TEST:m0s002-BO04-Stat
|
||||
IOC_TEST:m0s002-BO05-Stat
|
||||
IOC_TEST:m0s002-BO06-Stat
|
||||
IOC_TEST:m0s002-BO07-Stat
|
||||
IOC_TEST:m0s002-BO08-Stat
|
||||
IOC_TEST:m0s002-BO09-Stat
|
||||
IOC_TEST:m0s002-BO10-Stat
|
||||
IOC_TEST:m0s002-BO11-Stat
|
||||
IOC_TEST:m0s002-BO12-Stat
|
||||
IOC_TEST:m0s002-BO13-Stat
|
||||
IOC_TEST:m0s002-BO14-Stat
|
||||
IOC_TEST:m0s002-BO15-Stat
|
||||
IOC_TEST:m0s002-BO16-Stat
|
||||
IOC_TEST:m0s002-Stat_
|
||||
IOC_TEST:Axis1-Stat_
|
||||
IOC_TEST:ThdRTStat_
|
||||
IOC_TEST:m0-Stat_
|
||||
IOC_TEST:m0-Dom-Stat_
|
||||
IOC_TEST:m0s001-Enc01-LtchAutRst
|
||||
IOC_TEST:Axis1-MtnCmd_
|
||||
IOC_TEST:MCU-Cfg-EC-Mst
|
||||
IOC_TEST:MCU-Cfg-Rate
|
||||
IOC_TEST:MCU-Cfg-Time
|
||||
IOC_TEST:MCU-Cfg-PV-Time
|
||||
IOC_TEST:m0s001-Drv01-Cmd
|
||||
IOC_TEST:m0s001-Drv01-Spd
|
||||
IOC_TEST:m0s001-Enc01-Cmd
|
||||
IOC_TEST:m0s001-Enc01-PosCmd
|
||||
IOC_TEST:m0s001-NxtObjId
|
||||
IOC_TEST:MCU-Cfg-EC-FrstObjId
|
||||
IOC_TEST:m0s002-NxtObjId
|
||||
IOC_TEST:Axis1-OFF_
|
||||
IOC_TEST:Axis1-MRES_
|
||||
IOC_TEST:Axis1-HomPos
|
||||
IOC_TEST:Axis1-VelToHom
|
||||
IOC_TEST:Axis1-VelFrmHom
|
||||
IOC_TEST:Axis1-AccHom
|
||||
IOC_TEST:Axis1-TgtPosCmd
|
||||
IOC_TEST:Axis1-TgtVelCmd
|
||||
IOC_TEST:Axis1-Id
|
||||
IOC_TEST:MCU-Cfg-AX1-NxtObjId
|
||||
IOC_TEST:MCU-Cfg-AX-FrstObjId
|
||||
IOC_TEST:MCU-Cfg-PLG{Index}-NxtObjId
|
||||
IOC_TEST:MCU-Cfg-PLG-FrstObjId
|
||||
IOC_TEST:MCU-Cfg-Eng-Mode
|
||||
IOC_TEST:m0s001-Enc01-LchAutRstSp
|
||||
IOC_TEST:m0s002-BO01
|
||||
IOC_TEST:m0s002-BO02
|
||||
IOC_TEST:m0s002-BO03
|
||||
IOC_TEST:m0s002-BO04
|
||||
IOC_TEST:m0s002-BO05
|
||||
IOC_TEST:m0s002-BO06
|
||||
IOC_TEST:m0s002-BO07
|
||||
IOC_TEST:m0s002-BO08
|
||||
IOC_TEST:m0s002-BO09
|
||||
IOC_TEST:m0s002-BO10
|
||||
IOC_TEST:m0s002-BO11
|
||||
IOC_TEST:m0s002-BO12
|
||||
IOC_TEST:m0s002-BO13
|
||||
IOC_TEST:m0s002-BO14
|
||||
IOC_TEST:m0s002-BO15
|
||||
IOC_TEST:m0s002-BO16
|
||||
IOC_TEST:Axis1-EnaCmd
|
||||
IOC_TEST:Axis1-ExeCmd
|
||||
IOC_TEST:Axis1-StpCmd
|
||||
IOC_TEST:Axis1-RstCmd
|
||||
IOC_TEST:Axis1-EncSrcTyp-Cmd
|
||||
IOC_TEST:Axis1-TrjSrcTyp-Cmd
|
||||
IOC_TEST:Axis1-PLC-EnaCmd
|
||||
IOC_TEST:Axis1-CmdFrmPLCCmd
|
||||
IOC_TEST:Axis1-SftLimBwdEna
|
||||
IOC_TEST:Axis1-SftLimFwdEna
|
||||
IOC_TEST:Plg-FFT0-EnaCmd-RB
|
||||
IOC_TEST:MCU-ErrRst
|
||||
IOC_TEST:Axis1-MCU1-asyn
|
||||
IOC_TEST:MCU-Cmd
|
||||
IOC_TEST:Axis1
|
||||
69
iocsh/test_plugin_motion.script
Normal file
69
iocsh/test_plugin_motion.script
Normal file
@@ -0,0 +1,69 @@
|
||||
##############################################################################
|
||||
## Example: Configuraftion for running ecmc motion plugin
|
||||
##############################################################################
|
||||
|
||||
## Initiation:
|
||||
epicsEnvSet("IOC" ,"$(IOC="IOC_TEST")")
|
||||
epicsEnvSet("ECMCCFG_INIT" ,"") #Only run startup once (auto at PSI, need call at ESS), variable set to "#" in startup.cmd
|
||||
epicsEnvSet("SCRIPTEXEC" ,"$(SCRIPTEXEC="iocshLoad")")
|
||||
|
||||
require ecmccfg "9.0.1_RC1"
|
||||
|
||||
# run module startup.cmd (only needed at ESS PSI auto call at require)
|
||||
$(ECMCCFG_INIT)$(SCRIPTEXEC) ${ecmccfg_DIR}startup.cmd, "IOC=$(IOC),ECMC_VER=v9.0.1_RC1"
|
||||
|
||||
|
||||
##############################################################################
|
||||
## Configure hardware
|
||||
|
||||
epicsEnvSet("ECMC_EC_SLAVE_NUM", "1")
|
||||
${SCRIPTEXEC} ${ecmccfg_DIR}configureSlave.cmd, "SLAVE_ID=$(ECMC_EC_SLAVE_NUM), HW_DESC=EL7031, CONFIG=-Motor-Trinamic-QMot-QSH4218-41-10-035"
|
||||
epicsEnvSet("DRV_ID", "${ECMC_EC_SLAVE_NUM}")
|
||||
${SCRIPTEXEC} ${ecmccfg_DIR}addSlave.cmd, "HW_DESC=EL2819"
|
||||
epicsEnvSet("DO_ID", "${ECMC_EC_SLAVE_NUM}")
|
||||
|
||||
# Configure drv input 1 as drv enable
|
||||
ecmcConfigOrDie "Cfg.EcAddSdo(${DRV_ID},0x8012,0x32,1,1)"
|
||||
OK
|
||||
# Control external drv enable
|
||||
ecmcConfigOrDie "Cfg.WriteEcEntryIDString(${DO_ID},binaryOutput02,1)"
|
||||
|
||||
#Apply hardware configuration
|
||||
ecmcConfigOrDie "Cfg.EcApplyConfig(1)"
|
||||
|
||||
##############################################################################
|
||||
## AXIS 1
|
||||
#
|
||||
epicsEnvSet("DEV", "$(IOC)")
|
||||
$(SCRIPTEXEC) ($(ecmccfg_DIR)configureAxis.cmd, CONFIG=./cfg/el7031.ax)
|
||||
|
||||
########################################################################s######
|
||||
## Load plugin: MOTION
|
||||
|
||||
epicsEnvSet(ECMC_PLUGIN_CONFIG,"PLUGIN_ID=1,AX=1,BUFF_SIZE=25,DBG=0,ENA=1")
|
||||
|
||||
require ecmc_plugin_motion master ${ECMC_PLUGIN_CONFIG}
|
||||
${SCRIPTEXEC} ${ecmc_plugin_motion_DIR}startup.cmd "${ECMC_PLUGIN_CONFIG}"
|
||||
|
||||
#epicsEnvSet(ECMC_PLUGIN_FILNAME,"/home/pi/epics/base-7.0.5/require/3.4.0/siteMods/ecmc_plugin_motion/master/lib/${EPICS_HOST_ARCH=linux-x86_64}/libecmc_plugin_motion.so")
|
||||
#
|
||||
#${SCRIPTEXEC} ${ecmccfg_DIR}loadPlugin.cmd, "PLUGIN_ID=0,FILE=${ECMC_PLUGIN_FILNAME},CONFIG='${ECMC_PLUGIN_CONFIG}', REPORT=1"
|
||||
## Note: INDEX is the index of FFT object in FFT plugin and not PLUGIN_ID. In this case the same
|
||||
##dbLoadRecords(ecmcPluginFFT.template,"P=$(IOC):,INDEX=0, NELM=${FFT_NELM}, AMP_DESC='Sine amplitude',AMP_EGU='',RAW_DESC='Sine',AMP_EGU='', TITLE='FFT of sinus in 5Hz'")
|
||||
|
||||
##############################################################################
|
||||
############# Configure diagnostics:
|
||||
|
||||
ecmcConfigOrDie "Cfg.EcSetDiagnostics(1)"
|
||||
ecmcConfigOrDie "Cfg.EcEnablePrintouts(0)"
|
||||
ecmcConfigOrDie "Cfg.EcSetDomainFailedCyclesLimit(100)"
|
||||
ecmcConfigOrDie "Cfg.SetDiagAxisIndex(1)"
|
||||
ecmcConfigOrDie "Cfg.SetDiagAxisFreq(2)"
|
||||
ecmcConfigOrDie "Cfg.SetDiagAxisEnable(0)"
|
||||
|
||||
##############################################################################
|
||||
############# go active:
|
||||
$(SCRIPTEXEC) ($(ecmccfg_DIR)setAppMode.cmd)
|
||||
|
||||
iocInit
|
||||
dbl > pvs.log
|
||||
7
patch/Site/HISTORY.md
Normal file
7
patch/Site/HISTORY.md
Normal file
@@ -0,0 +1,7 @@
|
||||
# E3_MODULE_VERSION-what_ever_filename.p0.patch
|
||||
|
||||
Generic Description.....
|
||||
|
||||
* created by Jeong Han Lee, han.lee@esss.se
|
||||
* related URL or reference https://github.com/icshwi
|
||||
* Tuesday, February 13 13:24:57 CET 2018
|
||||
22
patch/Site/README.md
Normal file
22
patch/Site/README.md
Normal file
@@ -0,0 +1,22 @@
|
||||
# Site Specific EPICS Module Patch Files
|
||||
|
||||
## Changes
|
||||
The changes were tested in local environemnt, and commits to the forked repository and do pull request to the epics community module repository.
|
||||
|
||||
* Check the original HASH, and your own master
|
||||
* feb8856 : The original HASH
|
||||
* master : Changed
|
||||
|
||||
|
||||
## How to create a p0 patch file between commits
|
||||
|
||||
|
||||
* Show what the difference between commits
|
||||
|
||||
|
||||
* Create p0 patch
|
||||
|
||||
```
|
||||
$git diff feb8856 master --no-prefix > ../patch/Site/E3_MODULE_VERSION-what_ever_filename.p0.patch
|
||||
```
|
||||
|
||||
49
tempGNUmakefile
Normal file
49
tempGNUmakefile
Normal file
@@ -0,0 +1,49 @@
|
||||
include /ioc/tools/driver.makefile
|
||||
|
||||
MODULE = ecmc_plugin_motion
|
||||
|
||||
BUILDCLASSES = Linux
|
||||
ARCH_FILTER = deb10%
|
||||
|
||||
EXCLUDE_VERSIONS+=3 7.0.5
|
||||
|
||||
IGNORE_MODULES += asynMotor
|
||||
IGNORE_MODULES += motorBase
|
||||
|
||||
USR_CXXFLAGS += -std=c++17
|
||||
OPT_CXXFLAGS_YES = -O3
|
||||
|
||||
# dependencies
|
||||
ECmasterECMC_VERSION = v1.1.0
|
||||
motorECMC_VERSION = 7.0.7-ESS
|
||||
ecmc_VERSION = v9.0.1_RC1
|
||||
|
||||
################################################################################
|
||||
# THIS RELATES TO THE EtherCAT MASTER LIBRARY
|
||||
# IT IS OF PARAMOUNT IMPORTANCE TO LOAD THE PROPER KERNEL MODULE
|
||||
# ################################################################################
|
||||
USR_LDFLAGS += -lethercat
|
||||
|
||||
EC_MASTER_LIB = ${EPICS_MODULES}/ECmasterECMC/${ECmasterECMC_VERSION}/R${EPICSVERSION}/lib/${T_A}
|
||||
USR_LDFLAGS += -Wl,-rpath=${EC_MASTER_LIB}
|
||||
USR_LDFLAGS += -L ${EC_MASTER_LIB}
|
||||
|
||||
# expression parser
|
||||
#exprtk_DIR = ecmc/exprtkSupport/
|
||||
#SOURCES += ${exprtk_DIR}exprtkIF.cpp
|
||||
#SOURCES += ${exprtk_DIR}exprtkImp.cpp
|
||||
#SOURCES += ${exprtk_DIR}exprtkWrap.cpp
|
||||
#
|
||||
#HEADER += ${exprtk_DIR}/exprtkWrap.h
|
||||
#HEADER += ${exprtk_DIR}/exprtkIF.h
|
||||
|
||||
SRC_DIR = ecmc_plugin_motion/src
|
||||
|
||||
SOURCES += $(SRC_DIR)/ecmcPluginMotion.c
|
||||
SOURCES += $(SRC_DIR)/ecmcMotionPlgWrap.cpp
|
||||
SOURCES += $(SRC_DIR)/ecmcMotionPlg.cpp
|
||||
|
||||
#SOURCES += $(foreach d,${SRC_DIR}, $(wildcard $d/*.c) $(wildcard $d/*.cpp))
|
||||
HEADERS += $(foreach d,${SRC_DIR}, $(wildcard $d/*.h))
|
||||
DBDS += $(foreach d,${SRC_DIR}, $(wildcard $d/*.dbd))
|
||||
|
||||
0
template/.keep
Normal file
0
template/.keep
Normal file
8
tools/README.md
Normal file
8
tools/README.md
Normal file
@@ -0,0 +1,8 @@
|
||||
# FFT tools
|
||||
|
||||
## GUI
|
||||
|
||||
A python gui for vizualization and control of the FFT plugin can be found in the ecmccomgui repo:
|
||||
https://github.com/anderssandstrom/ecmccomgui
|
||||
|
||||

|
||||
Reference in New Issue
Block a user