From a773bc5b502c87b6a6017443b58c699ca9db8b8d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Anders=20Sandstr=C3=B6m?= Date: Tue, 5 Mar 2024 14:23:54 +0100 Subject: [PATCH 1/4] Update readme --- Db/ecmcPluginDAQ.template | 4 +- README.md | 462 +++++++++----------------------------- doc/dataformat.png | Bin 0 -> 50822 bytes src/ecmcDAQDataArray.cpp | 12 +- 4 files changed, 119 insertions(+), 359 deletions(-) create mode 100644 doc/dataformat.png diff --git a/Db/ecmcPluginDAQ.template b/Db/ecmcPluginDAQ.template index 58a5166..7a79dc0 100644 --- a/Db/ecmcPluginDAQ.template +++ b/Db/ecmcPluginDAQ.template @@ -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") diff --git a/README.md b/README.md index 05ca7b1..26499c8 100644 --- a/README.md +++ b/README.md @@ -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 - : Ioc prefix ('IOC_TEST:') - : Id of scope plugin ('0') -example : python ecmcScopeMainGui.py 'IOC_TEST:' '0' -Will connect to Pvs: Plugin-Scope-* +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= : Ec source variable (example: ec0.s1.mm.CH1_ARRAY). - RESULT_ELEMENTS= : Data points to collect, default = 4096. - SOURCE_NEXTTIME= : Ec next sync time for source (example: ec0.s1.NEXTTIME) - TRIGG= : 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.) - diff --git a/doc/dataformat.png b/doc/dataformat.png new file mode 100644 index 0000000000000000000000000000000000000000..1c61940da19d789a13d14d06ee3089b3b2bb368f GIT binary patch literal 50822 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 aJf?Z=@5jiDyM_(}{)q@m3Y74D{`w!njf@Kb literal 0 HcmV?d00001 diff --git a/src/ecmcDAQDataArray.cpp b/src/ecmcDAQDataArray.cpp index acda256..4523935 100644 --- a/src/ecmcDAQDataArray.cpp +++ b/src/ecmcDAQDataArray.cpp @@ -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_ ; From f665a483b22b528db30059c86ee21fe6347e7402 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Anders=20Sandstr=C3=B6m?= Date: Tue, 5 Mar 2024 14:26:04 +0100 Subject: [PATCH 2/4] Update readme --- README.md | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 26499c8..578150c 100644 --- a/README.md +++ b/README.md @@ -25,10 +25,11 @@ 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 + + 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 DAQ plugin in ecmc: From 480bf1f0d8fd529b13f795f5a33a9e289ad60636 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Anders=20Sandstr=C3=B6m?= Date: Tue, 5 Mar 2024 14:36:50 +0100 Subject: [PATCH 3/4] Update readme --- README.md | 30 ++++++++++++++++++++++++++++-- 1 file changed, 28 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 578150c..8dac5f9 100644 --- a/README.md +++ b/README.md @@ -136,11 +136,37 @@ c6025a:DAQ-Testing1-DataAct c6025a:DAQ-Testing2-DataAct ``` -Array data: +Array data "Testing1": ``` 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 +In this case the header is "3 2134284536 1234 14 6 -1 4321 20 5 -1 3702 25 200 -1": +0. Channel count =3 +1. EtherCAT dc time in micor seconds: 2134284536 +2. Type of first channel = 1234 +3. Data starts at element 14 +4. Data element count = 6 +5. Spare = -1 +6. Type of second channel = 4321 +7. Data starts at element 20 +8. Data element count = 5 +9. Spare = -1 +10. Type of third channel = 3702 +11. Data starts at element 25 +12. Data element count = 200 (two oversampling arrays) +13. Spare = -1 +14. First data element of first channel "1234" = 4293967 +15. Second data element of first channel = 0 +... +... +25. Data start element for teh third channel (with type 3702) = -5 +... +... +``` + +Array data "Testing2": +``` 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 -``` +``` \ No newline at end of file From d0c0d54d62d6668f9513faa1d3016a7bb893f490 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Anders=20Sandstr=C3=B6m?= Date: Tue, 5 Mar 2024 14:41:05 +0100 Subject: [PATCH 4/4] Update readme --- README.md | 35 +++++++++++++++++------------------ 1 file changed, 17 insertions(+), 18 deletions(-) diff --git a/README.md b/README.md index 8dac5f9..75cc84a 100644 --- a/README.md +++ b/README.md @@ -46,7 +46,6 @@ ${SCRIPTEXEC} ${ecmc_plugin_daq_DIR}ecmcDAQAddArray.cmd, "NAME=TestArray ``` 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 @@ -142,25 +141,25 @@ 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 In this case the header is "3 2134284536 1234 14 6 -1 4321 20 5 -1 3702 25 200 -1": -0. Channel count =3 -1. EtherCAT dc time in micor seconds: 2134284536 -2. Type of first channel = 1234 -3. Data starts at element 14 -4. Data element count = 6 -5. Spare = -1 -6. Type of second channel = 4321 -7. Data starts at element 20 -8. Data element count = 5 -9. Spare = -1 -10. Type of third channel = 3702 -11. Data starts at element 25 -12. Data element count = 200 (two oversampling arrays) -13. Spare = -1 -14. First data element of first channel "1234" = 4293967 -15. Second data element of first channel = 0 +0. Channel count : 3 +1. EtherCAT dc time in micro seconds : 2134284536 +2. Type of first channel : 1234 +3. Data starts at element : 14 +4. Data element count : 6 +5. Spare : -1 +6. Type of second channel : 4321 +7. Data starts at element : 20 +8. Data element count : 5 +9. Spare : -1 +10. Type of third channel : 3702 +11. Data starts at element : 25 +12. Data element count : 200 (two oversampling arrays of size 100) +13. Spare : -1 +14. First data element of first ch. "1234" : 4293967 +15. Second data element of first ch. : 0 ... ... -25. Data start element for teh third channel (with type 3702) = -5 +25. Data start element for third ch. : -5 ... ... ```