.. SPDX-FileCopyrightText: 2022 Cosylab d.d.
..
.. SPDX-License-Identifier: MIT
.. _heading-ref-manual:
################
Reference Manual
################
This section describes how to configure database records and the commands available in the IOC shell.
Database record configuration
=============================
Database records are configured as follows:
**DTYP** field:
specifies the asyn interface (e.g. *asynInt32*, *asynFloat64*, *asynInt8ArrayIn*) and is set according to the record type. Some records allow different asyn interfaces to be set. For more information see asynDriver distribution's ``dbd`` directory, ``devAsyn*.dbd`` (e.g. ``devAsynInt32.dbd``) files. See :ref:`supported-record-types` for a list of supported asyn interfaces.
**INP** and **OUT** fields:
uses the asyn *drvParams* optional parameter (see `asyn driver manual `_, section Generic Device Support for EPICS records) to specify the ADS register/variable that the record is connecting to, number of elements and the operation to be performed (read or write). For example: ``INP=@asyn(plc-01 0 0) USINT R P=300 V=Main.Number`` or ``OUT=@asyn(plc-02 0 0) REAL[] N=10 W P=IO V=Main.SetCalibration``.
**SCAN** field:
determines when the record is processed and, depending on the record type, how their value is handled:
* Output records with ``SCAN=Passive/periodic`` write to their corresponding ADS variable immediately when they are processed.
* Input records with ``SCAN=Passive/periodic`` have their *VAL* field populated with the latest value from their ADS variable's corresponding sum-read data buffers when processed.
* Input records with ``SCAN=I/O Intr`` have their *VAL* field populated immediately after the port driver detects their corresponding ADS variable's value in the sum-read databa buffer has changed.
**PINI** field:
Because the driver needs to perform initialization routines after IOC init, this field should be set to 'NO'. If it is set to 'YES', expect errors at IOC start, because of attempted reads before driver is initialized.
.. warning::
In current ADS port driver version, a large number of simultaneous write requests can saturate the ADS connection and cause the system to become unresponsive and cause records to time out.
The format used to specify the ADS variable in the INP/OUT fields depends if the record targets a scalar variable or array:
* `` P= V=`` is used for scalars,
* ``[] N= P= V=`` is used for arrays. *STRING* datatype requires N=, but not '[]'.
**DATA_TYPE**:
specifies one of the supported PLC data types, e.g., *USINT*, *LREAL*, *BOOL*, etc. See :ref:`supported-data-types` for a list of supported PLC data types. If the target variable is an array, append the '[]' to the datatype, except for strings, e.g., *USINT[]*, *LREAL[]*, *STRING*.
**NELEM** (optional):
is used to specify number of elements for array access, as well as to specify the length of *STRING* PLC variables, e.g., ``N=25``.
**OPERATION**:
specifies if the PLC variable is read (``R``) or written (``W``).
**PORT**:
ADS port in string or numerical format. The same parameter constraints apply as for register access, e.g., ``P=PLC_TC3``.
**VARIABLE**:
ADS variable name in string format, e.g. ``V=Main.temperature``.
Example variable name specifiers:
---------------------------------
Write an array of 5 UINT (16-bit unsigned int) values to PLC variable named Main.Waveform:
``UINT[] N=5 W P=PLC_TC3 V=Main.Waveform``
Write a REAL (32-bit float) value to PLC variable named Main.CorrectionFactor. The lack of [nelem] implies a scalar type:
``REAL W P=PLC_TC3 V=Main.CorrectionFactor``
Read 10 BYTE (8-bit int) values from PLC variable named Main.Values:
``BYTE[] N=10 R P=PLC_TC3 V=Main.Values``
Example database record configuration:
--------------------------------------
.. code-block::
record(ai, "BECKHOFF:ANALOG_IN:01") {
field(DESC, "Read first 16bit analog input")
field(DTYP, "asynInt32")
field(INP, "@asyn(beckhoff 0 0) INT R P=IO V=Main.testVar")
}
Refer to section :ref:`database-examples` for more examples on how to configure database records.
IOC shell commands
==================
This chapter describes the iocsh commands that are provided by the ADS device support software.
.. _iocsh-1:
AdsSetLocalAMSNetId
-------------------
**Description**:
Set the local AMS net ID of the IOC. This is used in ADS communication to represent the identity of the IOC – the ADS client. This command must be called before any calls to :ref:`iocsh-2`, i.e. before any ADS connections are open.
**Interface**:
``AdsSetLocalAMSNetId(ams_net_id)``
**Parameters**:
``ams_net_id``: AMS net ID that will be set locally on the IOC, e.g. "192.168.20.10.1.5".
**Example**:
.. code-block::
# Set the local AMS net ID to "192.168.20.10.1.5".
AmsSetLocalAMSNetId("192.168.20.10.1.5")
.. _iocsh-2:
AdsOpen
-------
**Description**:
Configure a new ADS connection. This command must be called before corresponding database records are loaded, i.e. before *dbLoadRecord* is called.
**Interface**:
``AdsOpen(port_name, ip_addr, ams_net_id, sum_buffer_nelem, ads_timeout)``
**Parameters**:
* **port_name**: The port name that is registered with asynManager and is used in the INP/OUT address specifications for the records.
* **ip_addr**: IP address of the remote ADS device.
* **ams_net_id**: AMS net ID of the remote ADS device.
* **sum_buffer_nelem** (optional): The maximum number of PVs that sum-read request and data buffers can contain. Defaults to 500, as per `recommendation by Beckhoff `_.
* **ads_timeout** (optional): Current version of the ADS device support (v2.0.0) does not implement *ADS function timeout* feature. ADS client library uses the default value of 5000 ms.
**Example**:
.. code-block::
# Configure an ADS connection with the optional parameters not specified.
AdsOpen("plc-01", "10.5.0.115", "10.5.0.115.1.1")
# Configure an ADS connection with all parameters. Here ADS sum operation buffer PV limit is set to 250, ads timeout to 1 second, auto connect is disabled and the default thread priority is used.
AdsOpen("plc-02", "10.5.0.120", "10.5.0.120.1.15", 250, 1000)
.. _supported-record-types:
Supported EPICS record types
============================
This table lists EPICS records that are supported by the ADS device support, and asyn interfaces that are available for each record type.
.. table::
:widths: auto
=================== ======= ======= ================ ==================== =========== ======================= ==========
asyn interface ai/ao bi/bo longin/longout stringin/stringout mbbi/mbbo mbbiDirect/mbboDirect waveform
=================== ======= ======= ================ ==================== =========== ======================= ==========
asynInt32 X X X X
asynInt64 X X
asynUInt32Digital X X
asynFloat64 X
asynOctet X
asynInt8Array X
asynInt16Array X
asynInt32Array X
asynFloat32Array X
asynFloat64Array X
=================== ======= ======= ================ ==================== =========== ======================= ==========
.. _supported-data-types:
Supported TwinCAT PLC data types
================================
This table lists asyn interfaces and `TwinCAT PLC data types `_ that the interfaces support.
.. warning::
ULINT datatype is not supported.
.. table::
:widths: auto
================== =====================
asyn interface supported TwinCAT PLC data types
================== =====================
asynInt32 BOOL, SINT, BYTE, INT, WORD, DINT, USINT, UINT
asynInt64 LINT, UDINT
asynUInt32Digital USINT, UINT, UDINT
asynFloat64 REAL, LREAL
asynOctet STRING
asynInt8Array BOOL, SINT, BYTE, USINT
asynInt16Array INT, WORD, UINT
asynInt32Array DINT, UDINT
asynFloat32Array REAL
asynFloat64Array LREAL
================== =====================
.. _database-examples:
Database record configuration examples
======================================
This section contains examples of database record configurations.
*longin* record read from a 16-bit integer ADS variable:
.. code-block::
record(longin, "$(P):reg_int32_counter") {
field(DTYP, "asynInt32")
field(INP, "@asyn($(PORT) 0 0) INT R P=350 V=Main.counter")
}
*longout* record writes to a 32-bit integer ADS variable:
.. code-block::
record(longout, "$(P):reg_int32_writable") {
field(DTYP, "asynInt32")
field(OUT, "@asyn($(PORT) 0 0) DINT W P=350 V=Main.writable")
}
*stringin* record reads from a string ADS variable of length 9. Due to ``SCAN=I/O Intr``, the ADS device support will update the record immediately when it detects that the addressed ADS variable has changed:
.. code-block::
record(stringin, "$(P):types_stringin") {
field(DTYP, "asynOctetRead")
field(SCAN, "I/O Intr")
field(INP, "@asyn($(PORT) 0 0) STRING N=9 R P=350 V=Test.types_stringin")
}
*mbbi* record reads from a 16-bit unsigned integer ADS variable.
.. code-block::
record(mbbiDirect, "$(P):types_mbbi") {
field(DTYP, "asynInt32")
field(INP, "@asyn($(PORT) 0 0) UINT R P=PLC_TC3 V=Test.types_mbbi")
}
*waveform* record reads 10 elements of 32-bit unsigned integer ADS variables. Due to ``SCAN=I/O Intr``, the ADS device support will update the record immediately when it detects that the addressed ADS variable has changed.
.. code-block::
record(waveform, "$(P):types_wf_ulong_in") {
field(DTYP, "asynInt32ArrayIn")
field(FTVL, "ULONG")
field(NELM, "10")
field(SCAN, "I/O Intr")
field(INP, "@asyn($(PORT) 0 0) UDINT[] N=10 R P=PLC_TC3 V=Test.types_wf_ulong_in")
}
*waveform* record writes 10 elements of 32-bit floating point ADS variables, addressed by port and symbolic name:
.. code-block::
record(waveform, "$(P):types_wf_float_out") {
field(DTYP, "asynFloat32ArrayOut")
field(FTVL, "FLOAT")
field(PREC, "2")
field(NELM, "10")
field(INP, "@asyn($(PORT) 0 0) REAL[] N=10 W P=PLC_TC3 V=TestPlan.types_wf_float_out")
}
.. _supported-ads-names:
Supported ADS port names
========================
This table lists the ADS port names that can be specified by name in the record's *INP/OUT* fields (the ``P=`` parameter).
.. table::
:widths: auto
========== =====
Port name Value
========== =====
LOGGER 100
RTIME 200
TRACE 290
IO 300
SPS 400
NC 500
ISG 550
PCS 600
PLC 801
PLC_RTS1 801
PLC_RTS2 811
PLC_RTS3 821
PLC_RTS4 831
PLC_TC3 851
========== =====