Update readme

This commit is contained in:
2024-03-05 14:23:54 +01:00
parent d582a24d42
commit a773bc5b50
4 changed files with 119 additions and 359 deletions

View File

@@ -1,5 +1,5 @@
record(waveform,"$(P)DAQ-${Name}-Data-Act"){
record(waveform,"$(P)DAQ-${Name}-DataAct"){
info(asyn:FIFO, "1000")
field(DESC, "Data")
field(PINI, "1")
@@ -11,7 +11,7 @@ record(waveform,"$(P)DAQ-${Name}-Data-Act"){
field(TSE, "0")
}
record(bo,"$(P)DAQ-${Name}-Enable"){
record(bo,"$(P)DAQ-${Name}-EnaCmd"){
field(DESC, "Enable")
field(DTYP, "asynInt32")
field(OUT, "@asyn(${PORT},$(ADDR=0),$(TIMEOUT=1000))plugin.daq.${Name}.enable")

462
README.md
View File

@@ -1,8 +1,7 @@
e3-ecmcPlugin_Scope
ecmc_plugin_daq
======
ESS Site-specific EPICS module : ecmcPlugin_Scope
A shared library with Scope functionalities loadable into ecmc:
A shared library with DAQ (data acquisition) functionalities loadable into ecmc:
https://github.com/epics-modules/ecmc (or local ess fork https://github.com/icshwi/ecmc).
@@ -10,378 +9,137 @@ Configuration is made through ecmccfg:
https://github.com/paulscherrerinstitute/ecmccfg (ot local ess fork https://github.com/icshwi/ecmccfg)
# Introduction
The plugin can package ecmc data into arrays of double (collected in the same realtime loop). Data can be both ethercat data (also supports oversampling) or from other objects in ecmc, like motion. The advantage of this is that all data is sampled at the same time.
The main functionality of this plugin is triggerd sampling of ethercat data from oversampled and timestamped ethercat slaves, like:
The structure of the data can be divided into 3 levels of objects:
* Array
* Channel
* DataItem
The Array is the top level object that represents the final array, the plugin supports multiple array objects. Each Array object can contain several Channels and each Channel can contain several DataItems.
Data:
* EL3702
* EL3742
* EL5101-0011
* ELM3604
* ....
The first elements in the Array contains header data describing the contets of the array.
![dataformat.png](doc/dataformat.png)
Trigger:
* EL1252
* EL1252-0050
To summarize:
1. First element of array is always the channel count
2. Second element is the ethercat time (micro seconds, 32bit)
3. Each channel then have a 4 element header:
1. Type code (defined by user)
2. Data start position in array
3. Data element count in array
4. Spare for future use
## Loading of Scope plugin in ecmc:
## Loading of DAQ plugin in ecmc:
NOTE: "require" can be used to get access to the template file. However, the plugin also needs to be loaded like below.
The plugin should be loaded in ecmc by use of require, the parameter PLUGIN_ID needs to be defined:
```
require ecmc_plugin_daq sandst_a "PLUGIN_ID=0"
```
A plugin is loaded by the ecmccfg command loadPlugin:
https://github.com/icshwi/ecmccfg/blob/master/scripts/loadPlugin.cmd
## Defining the array:
Create an empty array object with ecmcDAQAddArray.cmd:
```
${SCRIPTEXEC} ${ecmc_plugin_daq_DIR}ecmcDAQAddArray.cmd, "NAME=TestArray01"
```
This will an empty array object named "TestArray01"
This "NAME" parameter is also used to define the asyn port name and the asyn parameter name for for accessing the waveform data.
### Adding a channel in the array
Add a channel to the last created array with ecmcDAQAddChannel.cmd. The parameter TYPE needs to be defined in the function call:
* TYPE : User defined number for identification of the data channelm type. The type can for instance be used by a consumer of data to trigger different analysis for differet types.
Example:
```
epicsEnvSet(RESULT_NELM, 1024)
epicsEnvSet(ECMC_PLUGIN_FILNAME,"/home/pi/sources/e3-ecmcPlugin_Scope/ecmcPlugin_Scope-loc/O.7.0.4_linux-arm/libecmcPlugin_Scope.so")
epicsEnvSet(ECMC_PLUGIN_CONFIG,"SOURCE=ec0.s${SLAVE_NUM_AI}.mm.CH1_ARRAY;DBG_PRINT=1;TRIGG=ec0.s${SLAVE_NUM_TRIGG}.CH1_LATCH_POS;SOURCE_NEXTTIME=ec0.s${SLAVE_NUM_AI}.NEXT_TIME;RESULT_ELEMENTS=${RESULT_NELM};")
${SCRIPTEXEC} ${ecmccfg_DIR}loadPlugin.cmd, "PLUGIN_ID=1,FILE=${ECMC_PLUGIN_FILNAME},CONFIG='${ECMC_PLUGIN_CONFIG}', REPORT=1"
epicsEnvUnset(ECMC_PLUGIN_FILNAME)
epicsEnvUnset(ECMC_PLUGIN_CONFIG)
dbLoadRecords("../template/ecmcPluginScope.template","P=$(IOC):,PORT=${ECMC_ASYN_PORT},INDEX=0,RESULT_NELM=${RESULT_NELM},RESULT_DTYP=asynInt16ArrayIn,RESULT_FTVL=SHORT")
epicsEnvUnset(RESULT_NELM, 1024)
${SCRIPTEXEC} ${ecmc_plugin_daq_DIR}ecmcDAQAddChannel.cmd, "TYPE=1234"
```
This plugin supports multiple loading. For each load of the plugin a new Scope 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 Scope plugin will have index 0. The next loaded Scope plugin will have index 1...
### Adding a data item the a channel
Note: If another plugin is loaded in between the loading of Scope plugins, it will have no affect on these Scope indexes (so the Scope index is _not_ the same as plugin index).
## Configuration:
Three links to ethercat data needs to be defined:
* Source data
* Source data timestamp
* Trigger timestamp
All these three links needs to be defined in the plugin startup configuration string.
Other configurations that can be made:
* Data elements to collect
* Debug printouts
* Enable
### Source data (mandatory)
The source data should normally be a ecmc memmap.
The source is defined by the "SOURCE" configuration string:
```
SOURCE=ec0.s2.mm.CH1_ARRAY;
```
### Source data timestamp (mandatory)
In order to know which source data elements that correspond to the trigger value, the oversampled ethercat slaves normally have a pdo that contains the value of the next dc sync time which is the dc timestamp of the next acquired data element.
The source timestamp is defined by the "SOURCE_NEXTTIME" configuration string:
```
SOURCE_NEXTTIME=ec0.s2.NEXT_TIME;
```
This timestamp can be either in 32bit or 64bit format. The "NEXT_TIME" is always considered to be later than the trigger timestamp.
### Trigger (mandatory)
The trigger should normally be a timestamped digital input, like EL1252.
The trigger timestamp is defined by the "TRIGG" configuration string:
```
TRIGG=ec0.s5.CH1_LATCH_POS;
```
This timestamp can be either in 32bit or 64bit format. If 32 bits then "NEXT_TIME" is always considered to be later than the trigger timestamp.
### Data elements to collect (optional)
The number of values to be collected after the trigger is defined by setting the option "RESULT_ELEMENTS" in the configurations string. The default value is 1024 data elements of the same type as the choosen source.
```
RESULT_ELEMENTS=2048;
```
### Debug printouts (optional)
Debug printouts can be enbaled/disabled by the option DBG_PRINT (defaults to 0)
```
DBG_PRINT=1;
```
### Enable (optional)
The acuiring of data can be enabled/disabled by the "ENABLE" option (defaults to 1)
```
ENABLE=0;
```
### Example of complete configuration string
```
epicsEnvSet(ECMC_PLUGIN_CONFIG,"SOURCE=ec0.s${SLAVE_NUM_AI}.mm.CH1_ARRAY;DBG_PRINT=1;TRIGG=ec0.s${SLAVE_NUM_TRIGG}.CH1_LATCH_POS;SOURCE_NEXTTIME=ec0.s${SLAVE_NUM_AI}.NEXT_TIME;RESULT_ELEMENTS=${RESULT_NELM};")
```
## EPICS records
Each Scope plugin object will create a new asyn parameters.
The reason for a dedicated asynport is to disturb ecmc as little as possible.
The plugin contains a template file, "ecmcPluginScope.template", that will make most information availbe from records:
* Enable (rw)
* Data Source (ro)
* Trigger source (ro)
* Resultdata (ro)
The available records from this template file can be listed by the cmd:
Add a channel to the last created array with ecmcDAQAddDataItem.cmd. The command takes two parameters:
1. PARAM : Parameter name to specify the data to read from ecmc, ec0.s1.analogInput01, ax1.poserr,...
2. FORMAT : Optional formatting of data:
```
raspberrypi-15269 > dbgrep *Scope*
IOC_TEST:Plugin-Scope0-MissTriggCntAct
IOC_TEST:Plugin-Scope0-ScanToTriggSamples
IOC_TEST:Plugin-Scope0-TriggCntAct
IOC_TEST:Plugin-Scope0-Enable
IOC_TEST:Plugin-Scope0-DataSource
IOC_TEST:Plugin-Scope0-TriggSource
IOC_TEST:Plugin-Scope0-NextTimeSource
IOC_TEST:Plugin-Scope0-Data-Act
0 = raw (default) : Take raw value (do not apply special format)
1 = time_micro_s : Time: Recalc 64bit nano seconds to 32 bit micro second counter
2 = time_micro_s_minus_period : Time: Recalc 64bit nano seconds to 32 bit micro second counter minus one ec-period.
Useful for oversampling slaves where normally the nextsync time is available.
The calculated time then would correspond to the first data in the array recived.
3 = time_ns_minus_period : Time: Raw value minus one period.
```
### Finalizing a array
When the configurations for an array is finalized then the ecmcDAQFinalizeArray.cmd must be called.
The command will read the total array size (header plus data) from the plugin and then load the database with the waveform record (with correct NELM). The command takes the array name as a parameter ("NAME").
The wawform record will be named:
"${PREFIX}:DAQ-${NAME}-DataAct"
Example:
```
${SCRIPTEXEC} ${ecmc_plugin_daq_DIR}ecmcDAQFinalizeArray.cmd, "NAME=TestArray01"
```
## GUI
## Example:
### ecmcScopeMainGui
A simple pyqt gui is provided to visualize and control the scope ([GUI](tools/ecmcScopeMainGui.py)).
The gui are included in the ecmccomgui repo:
https://github.com/anderssandstrom/ecmccomgui
The tool recives data from the EPICS records by pyepics framework.
Help screen of ecmcScopeMainGui.py
```
$ python ecmcScopeMainGui.py
ecmcScopeMainGui: Plots waveforms of FFT data (updates on Y data callback).
python ecmcScopeMainGui.py <prefix> <fftId>
<prefix> : Ioc prefix ('IOC_TEST:')
<scopeId> : Id of scope plugin ('0')
example : python ecmcScopeMainGui.py 'IOC_TEST:' '0'
Will connect to Pvs: <prefix>Plugin-Scope<scopeId>-*
The below example configures 2 array objects:
1. Array "Testing1" containg 3 channels with a few data items (also arrays from oversampling slaves)
2. Array "Testing2" containg 2 channels with a few data items
```
Example: Start ecmcFFMainTGui.py for:
* predix="IOC_TEST:"
* scopePluginId=0 (the first loaded Scope plugin in the ioc)
##############################################################################
## Load daq plugin
#
require ecmc_plugin_daq sandst_a "PLUGIN_ID=0"
epicsEnvSet(NAME,Testing1)
${SCRIPTEXEC} ${ecmc_plugin_daq_DIR}ecmcDAQAddArray.cmd, "NAME=${NAME}"
${SCRIPTEXEC} ${ecmc_plugin_daq_DIR}ecmcDAQAddChannel.cmd, "TYPE=1234"
${SCRIPTEXEC} ${ecmc_plugin_daq_DIR}ecmcDAQAddDataItem.cmd, "PARAM=ec0.s13.ONE,FORMAT=2"
${SCRIPTEXEC} ${ecmc_plugin_daq_DIR}ecmcDAQAddDataItem.cmd, "PARAM=ec0.s13.positionActual01"
${SCRIPTEXEC} ${ecmc_plugin_daq_DIR}ecmcDAQAddDataItem.cmd, "PARAM=ax1.setpos"
${SCRIPTEXEC} ${ecmc_plugin_daq_DIR}ecmcDAQAddDataItem.cmd, "PARAM=ec0.s13.positionActual01"
${SCRIPTEXEC} ${ecmc_plugin_daq_DIR}ecmcDAQAddChannel.cmd, "TYPE=4321"
${SCRIPTEXEC} ${ecmc_plugin_daq_DIR}ecmcDAQAddDataItem.cmd, "PARAM=ec0.s13.ONE,FORMAT=2"
${SCRIPTEXEC} ${ecmc_plugin_daq_DIR}ecmcDAQAddDataItem.cmd, "PARAM=ec0.s13.positionActual01"
${SCRIPTEXEC} ${ecmc_plugin_daq_DIR}ecmcDAQAddDataItem.cmd, "PARAM=ax1.setpos"
${SCRIPTEXEC} ${ecmc_plugin_daq_DIR}ecmcDAQAddChannel.cmd, "TYPE=3702"
${SCRIPTEXEC} ${ecmc_plugin_daq_DIR}ecmcDAQAddDataItem.cmd, "PARAM=ec0.s9.mm.analogInputArray01"
${SCRIPTEXEC} ${ecmc_plugin_daq_DIR}ecmcDAQAddDataItem.cmd, "PARAM=ec0.s9.mm.analogInputArray02"
${SCRIPTEXEC} ${ecmc_plugin_daq_DIR}ecmcDAQFinalizeArray.cmd "NAME=${NAME}"
epicsEnvSet(NAME,Testing2)
${SCRIPTEXEC} ${ecmc_plugin_daq_DIR}ecmcDAQAddArray.cmd, "NAME=${NAME}"
${SCRIPTEXEC} ${ecmc_plugin_daq_DIR}ecmcDAQAddChannel.cmd, "TYPE=1234"
${SCRIPTEXEC} ${ecmc_plugin_daq_DIR}ecmcDAQAddDataItem.cmd, "PARAM=ec0.s13.ONE,FORMAT=2"
${SCRIPTEXEC} ${ecmc_plugin_daq_DIR}ecmcDAQAddDataItem.cmd, "PARAM=ec0.s13.positionActual01"
${SCRIPTEXEC} ${ecmc_plugin_daq_DIR}ecmcDAQAddDataItem.cmd, "PARAM=ax1.setpos"
${SCRIPTEXEC} ${ecmc_plugin_daq_DIR}ecmcDAQAddDataItem.cmd, "PARAM=ec0.s13.positionActual01"
${SCRIPTEXEC} ${ecmc_plugin_daq_DIR}ecmcDAQAddChannel.cmd, "TYPE=4321"
${SCRIPTEXEC} ${ecmc_plugin_daq_DIR}ecmcDAQAddDataItem.cmd, "PARAM=ec0.s13.ONE,FORMAT=2"
${SCRIPTEXEC} ${ecmc_plugin_daq_DIR}ecmcDAQAddDataItem.cmd, "PARAM=ec0.s13.positionActual01"
${SCRIPTEXEC} ${ecmc_plugin_daq_DIR}ecmcDAQAddDataItem.cmd, "PARAM=ax1.setpos"
${SCRIPTEXEC} ${ecmc_plugin_daq_DIR}ecmcDAQFinalizeArray.cmd "NAME=${NAME}"
```
python ecmcScopeMainGui.py 'IOC_TEST:' '0'
Records:
```
![gui.py](docs/gui.png)
### Needed packages:
* python 3.5
* epics
* PyQt5
* numpy
* matplotlib
## Example script
An example script can be found in the iocsh directory of this repo.
The example is based on:
* EL3702 for acquiring analog data with a oversampling factor of 100 (100kHz sampling rate)
* EL1252 for timestamped trigger
The below image shows triggered acquisition in 10Hz of a 100Hz sinus 1Vpp. For each trigger, 500 samples are acquired in 100kHz sample rate and pushed to epics as waveforms (in 10Hz with NELM 500). In total the image shows data from 17 triggers after each other.
![Example](docs/example.png)
## Plugin info
```
Plugin info:
Index = 1
Name = ecmcPlugin_Scope
Description = Scope plugin for use with ecmc.
Option description =
DBG_PRINT=<1/0> : Enables/disables printouts from plugin, default = disabled.
SOURCE=<source> : Ec source variable (example: ec0.s1.mm.CH1_ARRAY).
RESULT_ELEMENTS=<Result buffer size> : Data points to collect, default = 4096.
SOURCE_NEXTTIME=<nexttime> : Ec next sync time for source (example: ec0.s1.NEXTTIME)
TRIGG=<trigger> : Ec trigg time (example: ec0.s2.LATCH_POS).
ENABLE=<1/0> : Enable data acq, defaults to enabled.
Filename = /home/dev/projects/e3-ecmcPlugin_Scope/ecmcPlugin_Scope-loc/O.7.0.4_linux-x86_64/libecmcPlugin_Scope.so
Config string = SOURCE=ec0.s35.mm.CH1_ARRAY;DBG_PRINT=0;TRIGG=ec0.s1.CH1_LATCH_POS;SOURCE_NEXTTIME=ec0.s35.NEXT_TIME;RESULT_ELEMENTS=500;
Version = 2
Interface version = 65536 (ecmc = 65536)
max plc funcs = 64
max plc func args = 10
max plc consts = 64
Construct func = @0x7f28a4eca2a0
Enter realtime func = @0x7f28a4eca300
Exit realtime func = @0x7f28a4eca290
Realtime func = @0x7f28a4eca2f0
Destruct func = @0x7f28a4eca2c0
dlhandle = @0x1883050
Plc functions:
funcs[00]:
Name = "scope_enable(arg0, arg1);"
Desc = scope_enable(index,enable) : Enable/disaable scope[index].
Arg count = 2
func = @0x7f28a4eca310
Plc constants:
c6025a> dbgrep *DAQ*
c6025a:DAQ-Testing1-Enable
c6025a:DAQ-Testing2-Enable
c6025a:DAQ-Testing1-DataAct
c6025a:DAQ-Testing2-DataAct
```
# Troubleshooting
## Missed triggers
The plugin can not handle new triggers before the acquistion from the previous trigger is completed. Therefore the maximum triggering rate depends on the amount of data that should be acquired.
Therfore, in order to handle higher triggering rates, the result element count might need lowering (see above options).
Missed triggers can also be a result of bad syncronized dc clocks. If the dc-clocks are syncing properly the value of "NEXT_TIME" should always be after the trigger value (since NEXT_TIME should occur in the future).
The time between NEXT_TIME and trigger can be diagnosed by the "ScanToTriggSamples" pv like in this example (NELM=100):
Array data:
```
camonitor IOC_TEST:Plugin-Scope0-ScanToTriggSamples
IOC_TEST:Plugin-Scope0-ScanToTriggSamples 2020-09-30 08:40:20.680888 91
IOC_TEST:Plugin-Scope0-ScanToTriggSamples 2020-09-30 08:40:20.703867 118
IOC_TEST:Plugin-Scope0-ScanToTriggSamples 2020-09-30 08:40:20.906862 115
IOC_TEST:Plugin-Scope0-ScanToTriggSamples 2020-09-30 08:40:20.944867 87
IOC_TEST:Plugin-Scope0-ScanToTriggSamples 2020-09-30 08:40:21.019865 102
IOC_TEST:Plugin-Scope0-ScanToTriggSamples 2020-09-30 08:40:21.282872 93
IOC_TEST:Plugin-Scope0-ScanToTriggSamples 2020-09-30 08:40:21.362859 99
IOC_TEST:Plugin-Scope0-ScanToTriggSamples 2020-09-30 08:40:21.470863 102
caget -t c6025a:DAQ-Testing1-DataAct
14:22:04.745986 c6025a:DAQ-Testing1-Data-Act 3 2134284536 1234 14 6 -1 4321 20 5 -1 3702 25 200 -1 4293967 0 0 0 0 0 4293967 0 0 0 0 -5 -8 -7 -5 -5 -5 -7 -5 -7 -5 -7 -7 -5 -7 -7 -3 -5 -5 -9 -4 -5 -5 -9 -5 -8 -8 -7 -7 -7 -8 -5 -4 -8 -8 -7 -5 -7 -4 -5 -9 -8 -8 -11 -7 -4 -5 -8 -8 -8 -9 -5 -7 -4 -4 -5 -9 -7 -4 -10 -7 -7 -8 -8 -5 -5 -7 -8 -8 -5 -5 -8 -7 -7 -7 -8 -8 -7 -4 -7 -8 -8 -7 -8 -7 -5 -9 -8 -7 -8 -9 -9 -5 -7 -7 -8 -5 -9 -8 -9 -5 -5 -3 -5 -4 -6 -4 -6 -5 -5 -5 -6 -6 -4 -5 -4 -6 -6 -6 -5 -6 -4 -4 -5 -6 -7 -7 -6 -4 -7 -4 -6 -6 -8 -6 -5 -4 -4 -5 -4 -6 -6 -6 -6 -5 -4 -6 -3 -4 -7 -9 -6 -4 -3 -4 -6 -6 -5 -5 -7 -5 -5 -4 -6 -5 -3 -6 -6 -6 -5 -4 -4 -5 -3 -4 -5 -5 -6 -5 -5 -6 -6 -5 -4 -7 -3 -6 -6 -5 -6 -6 -5 -5 -3 -4 -6 -6 -5 -7 -6 -5
caget -t c6025a:DAQ-Testing2-DataAct
14:21:22.652988 c6025a:DAQ-Testing2-Data-Act 2 2092191543 1234 10 6 -1 4321 16 5 -1 4293967 0 0 0 0 0 4293967 0 0 0 0
```
The value should always be 0 < value < 2*NELM (NELM = Oversamplefactor or samples per ethercat cycle) which means that the trigger occured up to 2*NELM ago.
If the value is outside these limts the trigger will be rejected. The reason could be badly syncrobized dc-clocks (see below).
## Slave time syncing
If the dc time syncronization of the slaves is not working properly then the timestamps from both trigger and analog i/o will drift apart resulting in lost triggers and currupted data.
This could be related to that an old version of the etherlab master is installed and needs to be upgraded.
NOTE: The dc clocks in the slaves start to syncronize to the reference clocks as soon as the ioc enter runtime. This procedure can take normally a few seconds but can also take minutes depending on how many slaves in the network. During this startup syncronization phase the dc clock of the trigger and the analog input slaves may be out of sync resulting in acquisition of wrong data.
### Verify dc diagnostics
#### ethercat master command
Check ethercat master dc diagnostics by issueing the "etehrcat master" command (when ecmc-ioc is running):
```
dev@mcag-epics4 ~ $ ethercat master
Master0
Phase: Operation
Active: yes
Slaves: 49
Ethernet devices:
Main: c0:3f:d5:66:24:13 (attached)
Link: UP
Tx frames: 1419695
Tx bytes: 553305060
Rx frames: 1419694
Rx bytes: 553304557
Tx errors: 0
Tx frame rate [1/s]: 1000 1000 1000
Tx rate [KByte/s]: 498.0 498.0 498.0
Rx frame rate [1/s]: 1000 1000 1000
Rx rate [KByte/s]: 498.0 498.0 498.0
Common:
Tx frames: 1419695
Tx bytes: 553305060
Rx frames: 1419694
Rx bytes: 553304557
Lost frames: 0
Tx frame rate [1/s]: 1000 1000 1000
Tx rate [KByte/s]: 498.0 498.0 498.0
Rx frame rate [1/s]: 1000 1000 1000
Rx rate [KByte/s]: 498.0 498.0 498.0
Loss rate [1/s]: 0 -0 0
Frame loss [%]: 0.0 -0.0 0.0
Distributed clocks:
Reference clock: Slave 0
DC reference time: 654699808777655501
Application time: 654700465153733449
2020-09-29 13:14:25.153733449
```
The last section of the printout lists some dc information of the master. Check teh following:
* The "Reference clock" should be assigned to a slave.
* The "DC reference time" should have a resonable value.
* The "Application time" should have a resonable value.
#### ethercat slaves command
Check the dc diagnostics for both the triggering and analog input slave bu the ethercat slaves command (when ecmc-ioc is running).
Example: Trigger slave id = 1
```
ev@mcag-epics4 ~ $ ethercat slaves -p1 -v
=== Master 0, Slave 1 ===
Device: Main
State: OP
Flag: +
Identity:
Vendor Id: 0x00000002
Product code: 0x04e43052
Revision number: 0x00150000
Serial number: 0x00000000
DL information:
FMMU bit operation: no
Distributed clocks: yes, 64 bit
DC system time transmission delay: 140 ns
Port Type Link Loop Signal NextSlave RxTime [ns] Diff [ns] NextDc [ns]
0 EBUS up open yes 0 1224884182 0 140
1 EBUS up open yes 2 1224891012 6830 154
2 N/A down closed no - - - -
3 N/C down closed no - - - -
General:
Group: DigIn
Image name: TERM_DI
Order number: EL1252
Device name: EL1252 2K. Fast Dig. Eingang 24V, 1<>s, DC Latch
Flags:
Enable SafeOp: no
Enable notLRW: no
Current consumption: 110 mA
```
Example: analog input slave id = 35
```
dev@mcag-epics4 ~ $ ethercat slaves -p35 -v
=== Master 0, Slave 35 ===
Device: Main
State: OP
Flag: +
Identity:
Vendor Id: 0x00000002
Product code: 0x0e763052
Revision number: 0x00030000
Serial number: 0x00000000
DL information:
FMMU bit operation: no
Distributed clocks: yes, 32 bit
DC system time transmission delay: 9088 ns
Port Type Link Loop Signal NextSlave RxTime [ns] Diff [ns] NextDc [ns]
0 EBUS up open yes 34 1765139745 0 170
1 EBUS down closed no - - - -
2 N/A down closed no - - - -
3 N/A down closed no - - - -
General:
Group: AnaInFast
Image name: TERM_AI
Order number: EL3702
Device name: EL3702 2K. Ana. Eingang +/-10V, DIFF, Oversample
Flags:
Enable SafeOp: no
Enable notLRW: no
Current consumption: 200 mA
```
Check the following for both slaves:
* "DC system time transmission delay" is a non zero value (like above)
* "Distributed clocks" is "yes" and 32 or 64 bit
If status of the above commands are not according to the examples then the etherlab master probbaly needs to be upgraded/reinstalled. Use the etherlab master repo: https://github.com/icshwi/etherlabmaster/ (or for ESS install via cs-entry.)

BIN
doc/dataformat.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 50 KiB

View File

@@ -82,8 +82,8 @@ void ecmcDAQDataArray::connectToDataSources() {
dataElementCount_ = dataElementCount_ + (*pDataCh)->getDataElementCount();
}
// Header: First element is time stamp then 4 elements per channel
totalElementCount_ = dataElementCount_ + channelCounter_ * 4 + 1;
// Header: First element is channel count then time stamp then 4 elements per channel
totalElementCount_ = dataElementCount_ + channelCounter_ * 4 + 2;
// Now we we can finally allocate teh buffer (ecmc is still not in realtime, enterRT)
buffer_ = new double [totalElementCount_];
@@ -113,9 +113,9 @@ void ecmcDAQDataArray::connectToDataSources() {
*....
*/
void ecmcDAQDataArray::buildArrayHeader(){
// 4 elements plus first timestamp to first data element, only first element will change in realtime
// 4 elements plus channel count + timestamp to first data element, only first element will change in realtime
size_t dataStartOffset = channelCounter_* 4 + 1;
size_t dataStartOffset = channelCounter_* 4 + 2;
firstDataElementIndex_ = dataStartOffset;
if( totalElementCount_ < dataStartOffset) {
@@ -123,6 +123,8 @@ void ecmcDAQDataArray::buildArrayHeader(){
}
size_t index = 0;
buffer_[index] = channelCounter_; // Channel count
index++;
buffer_[index] = 0; // Timestamp, will be set in each loop in execute
index++;
@@ -158,7 +160,7 @@ void ecmcDAQDataArray::execute() {
}
//convert to micro secs 32bit and double
buffer_[0] =(double)((master_->getTimeNs()/1000)& 0xFFFFFFFF);
buffer_[1] =(double)((master_->getTimeNs()/1000)& 0xFFFFFFFF);
int first = 1;
size_t index = firstDataElementIndex_ ;