Device Manager

The Device Manager provides the functionality for supervision and management of a configurable set of devices.

The Device Manager provides a library of devices implementing the communication with the respective device controllers in the PLC. Devices are created at the manager start-up by a device factory class. The main components of the Device Manager server are:

  • State Machine engine based on SCXML and implemented in RAD. It contains a set of action and activity classes.

  • A Device Factory class that creates the instances of all device classes at start-up and based on the server configuration.

  • A set of Device classes. Each device has two additional classes: one for the device configuration and the other one for the interface with the Local Control System (LCS).

  • A Facade class that manages the interface between the state machine engine and the device classes.

alternate text

Device Manager Components without LCS.

Client applications, such as fcfGui, send commands to the Device Manager using the CII MAL library (request/reply). The fcfGui reads the information about the devices from the Redis DB using polling.

The Device Manager uses the Redis Database to store run-time information about itself and about the devices it controls. In absence of a Local Control System, device classes can connect to the Device Simulator via the OPC-UA protocol, see figure above.

In normal operation, device classes connect to the OPC-UA server running under the Windows OS side of the Beckhoff IPC, e.g .CX2030. This communication is based on the execution of RPC calls (OPC-UA Method profile). Each Device Controller running in the TwinCAT PLC declares a number of methods defining the interface with the Device Manager. Additionally, the device classes subscribe to the status data produced by the device controllers. Each time the status changes, the device classes are notified and they updates the Redis DB and publish the corresponding changes via CII (pub/sub).

The PLC OPC-UA Server connects to the device controllers via the vendor specific protocol (ADS). The device controllers trigger the changes in the hardware via the TwinCAT I/O mapping.

alternate text

Device Manager connecting to a Beckhoff IPC.

Supported Devices

Shutters

The Shutter device is a general purpose device for controlling a shutter hardware function. The device can control the shutter open/close.

Lamps

The Lamp device is a general purpose device for controlling a lamp hardware function. The device can switch a lamp on/off, control the intensity and handle warm-up and cool-down times when this is supported.

Motors

The Motor device is a general purpose device that controls different types of motors. It provides the following features:

  • Support three different axis types: Linear, Circular and Circular-Optimized. Circular-Optimized means that the motor will always take the shorter path to reach the target position.

  • Definition of named positions in user units (UU) or encoder values.

  • Arbitrary positioning given in user units or encoder values.

  • Positioning in absolute or relative units.

  • Support for configurable Initialization Sequence.

  • Support for SW limits.

  • Support for various timeouts.

  • Auto disabling when standing.

  • Support for brake handling.

  • Support for backlash compensation.

IODev

The IODev device is a generic Input/Output control device that can be customized for specific applications not already covered by other devices. It can be configured with a variable number of channels. The IODev device supports three different input channel types: Digital input, Analog input and Integer input. And three different output channel types: Digital output, Analog output and Integer output.

Sensors

The Sensor device is a IODev configured only for monitoring signals. The Sensor device supports three different channel types: Digital input, Analog input and Integer input.

Derotators

The Derotator device is an aggregated motor device that continuously adapt its position according to the field or pupil rotation. It supports four different modes:

  • Stationary: Derotator moves to a target position based on the position angle and remains standstill after reaching the target.

  • Sky: The Derotator is continuously moving to compensate the field rotation.

  • Elevation: The Derotator is continuously moving to compensate the pupil rotation.

  • User: The Derotator is continuously moving according to a customized computation of the position defined by the user.

ADCs

The ADC device manages the position of two prisms with the aim of correcting for the atmospheric dispersion.

The device supports two modes:

  • Auto: The ADC is continuously positioning the two motors based on the telescope RA/DEC, the environmental parameters and the ADC configuration.

  • Off: The ADC moves to a target position and remains standstill after reaching the target.

Piezos

The ‘Piezo’ device manages the control of the output signals of a piezo hardware. It supports up to three axes. The device can be set in two modes:

  • Auto: The Piezo is correcting continuously the outputs based on the feedback signals.

  • Pos: The Piezo set the output of the axes to a fixed value. In this mode, the Piezo can

    be controlled in user positions (normally volts) or directly in bits.

Actuator

The Actuator device is a general purpose device for controlling actuators through a switch signal (on/off). The most common use of actuators is for power control.

SmarAct

These are motor devices handled by a SmarAct controller type.

Device Manager State Machine

The Device Manager uses a state machine described in a SCXML format that is interpreted by the state machine engine provided by the rad application framework. (SCXML specification).

alternate text

Device Manager State Machine Diagram.

Off –> NotReady, event: Startup

The Device Manager starts up and goes automatically to NotOperational/NotReady. Main server objects are instantiated including the basic application that uses the State Machine engine. The Device Manager reads its own configuration and completes its initialisation.

NotReady –> Ready, event: Init

The server connects to each of the device controllers through the device objects. Depending on the device configuration, it establishes the connection to the real HW or to the simulator. If any of the device objects fails to establish the connection, the server will remain in substate NotReady.

NotOperational/Ready –> Operational/Idle, event: Enable

The Device Managers goes through the Enabling state. If Device Controllers are already Operational, the Device Manager does not affect their state and goes immediately to the Operational state. If Device Controllers are not operational, Device Manager will trigger the events (via OPC-UA method calls) to reach the operational state for each of the local devices under the manager control. If it does not succeed within the defined timeout (configuration parameter, see CII Configuration Service (config-ng)), it will reply with a failure remaining in NotOperational/Ready state. During the transition from NotOperational/Ready to Operational/Idle, the Device Manager downloads the configuration to each Device Controller. If at least one Device Controller cannot reach the Operational state, the Device Manager will remain in state NotOperational/Ready.

Operational/Idle –> Operational/Error, event: HwFailure

Problems in at least one of the managed devices will bring the Device Manager into the Error state (Operational/Error). A typical example would be when the PLC, running the Device Controller, is power-cycled.

Operational/Error –> Operational/Idle, event: HwNormal

In the situation when an error condition is recovered, the Device Manager will go back automatically to Operational/Ready state (event HwNormal). For instance, if the network connection is lost, the Device Manager will go to Error but when the network is restored, the Device Manager will update its state automatically.

Operational –> NotOperational/Ready, event: Disable

The Device Manager disables the operation of devices but the state of controllers is not affected. If the state of the controllers is to be changed to NotReady, this has to be done separately. The reason for the above is to avoid affecting the state of the controllers by changing the state of the manager and thus achieve minimal impact on the hardware. In case of error going from Operational to NotOperational/Ready, the end state will be nevertheless NotOperational/Ready.

NotOperational/Ready –> NotOperational/NotReady, event Reset

The subscription to the OPC-UA server is stopped and the sessions of the managed devices are disconnected. In case of error going from Ready to NotReady, the end state will be nevertheless NotReady.

Extract of the current State Machine specification for the Device Manager.

<state id="On">
<initial>
  <transition target="NotOperational"/>
</initial>
<state id="NotOperational">
  <initial>
    <transition target="NotReady"/>
  </initial>
  <state id="NotReady">
    <transition event="Events.Reset" target="NotReady">
       <customActionDomain:ActionReset name="ActionReset"/>
    </transition>
    <transition event="Events.Init" target="Initialising"/>
    <transition event="Events.Config">
     <customActionDomain:ActionConfig name="ActionConfig"/>
    </transition>
  </state>
  <state id="Initialising">
    <onentry>
      <customActionDomain:ActionInitStart name="ActionInitStart"/>
    </onentry>
    <invoke id="ActivityInitialising"/>
           <transition event="Events.InitDone" target="Ready">
              <customActionDomain:ActionInitDone name="ActionInitDone"/>
           </transition>
           <transition event="Events.InitError" target="NotReady">
              <customActionDomain:ActionInitError name="ActionInitError"/>
           </transition>

Configuration

CII Configuration Service (config-ng)

The FCF in version 4.0.0 has been ported to the CII config-ng library. This library allows to define type information for the configuration parameters and supports inheritance. The FCF has included a predefined set of configuration definitions. These files are part of the FCF configuration and can be found in the fcf/server/resources/config directory. This config directory contains the following subdirectories:

  • definitions: it contains the basic types for the server and devices.

  • mapping: it contains the instances of the mapping files for each device type.

  • devices: it contains examples of configuration for each device type.

  • server: it contains an example of the configuration for the server.

You can find more information about CII config-ng in the following link. (Config-ng manual).

Warning

Please note that due to the porting to the CII config service, all applications shall be updated accordingly.

Device Manager Configuration

The server configuration is a set of files written in yaml format. (YAML specification). YAML is easy to read format that has been adopted by the CII configuration service.

Many resources about YAML can be found on the web. One could also validate the format online, see http://yaml.org/spec/

The CII config-ng defines a set of yaml custom tags for defining types, e.g. !cfg.type:int32 defines an integer parameter. Applications can define additional types. The FCF has defined a number of types including one per device.

Note

The entry point for the Device Manager configuration is the file that contains the server configuration and the mapping to the device configuration files. The configuration of each device should be given in a separate file for better readability and maintenance. Each device type uses the corresponding mapping file that defines the real names of the attributes in the OPC-UA address space.

Config Item

Type

Optional

Default

Description

server::server_id

string

no

This is the id associated with the specific server.

server::req_endpoint

string

no

This is the endpoint for CII MAL request/reply. The server will listen to incoming commands using this endpoint.

server::pub_endpoint

string

no

This is the endpoint for CII MAL pub/sub. The server will publish its status using this endpoint.

server::db_endpoint

string

no

This is the endpoint used by the server for connecting to the Redis DB.

server::db_timeout

double

yes

2000 [ms]

This is the timeout for connecting to the Redis DB.

server::log_properties

string

log4cplus property file to be used by the server.

server::scxml

string

no

This is the state machine specification file used by the server.

server::fits_prefix

string

no

This is the prefix to be used for the INS meta-data.

server::oldb_prefix

string

no

This is the prefix to be used for the DB. This prefix is meant to identify uniquely a given system, e.g. micado.

server::req_timeout

double

yes

2000 [ms]

General command timeout for sending commands to the Local Control System (LCS).

server::mon_timeout

double

yes

1000 [ms]

General timeout for monitoring.

server::dictionaries

vector

of

string

no

Vector of dictionaries to be used by the server.

server::devices

vector

of

devices

no

This is a vector of devices which are active in the server configuration. Only devices listed here will be managed by the server.

Each element in the device vector has the following attributes:

name

This is the device name.

cfgfile

Configuration filename for a device.

type

Device type.

An example of a server configuration is provided below.

# server definition
!cfg.include fcf/devmgr/definitions/server.yaml:

server: !cfg.type:FcfServer
    server_id       : 'fcs1'
    req_endpoint    : "zpb.rr://127.0.0.1:12082/"
    pub_endpoint    : "zpb.ps://127.0.0.1:12345/"
    db_endpoint     : "127.0.0.1:6379"
    db_timeout      : 2000
    scxml           : "fcf/devmgr/server/sm.xml"
    dictionaries    : ["dictionary/dit/stddid/primary.did.yaml", "dictionary/fcf/devmgr/server/fcf.did"]
    log_properties  : "fcf/devmgr/server/log_properties.cfg"
    fits_prefix     : "INS1"
    oldb_prefix     : "ins8"
    req_timeout     : 300000
    devices         : [
    {
    name: 'shutter1',
    type: Shutter,
    cfgfile: "fcf/devmgr/devices/shutter1.yaml"
    },
    {
    name: 'lamp1',
    type: Lamp,
    cfgfile: "fcf/devmgr/devices/lamp1.yaml"
    },
    {
    name: 'actuator1',
    type: Actuator,
    cfgfile: "fcf/devmgr/devices/actuator1.yaml"
    },
    {
    name: 'motor1',
    type: Motor,
    cfgfile: "fcf/devmgr/devices/motor1.yaml"
    },
    {
    name: 'piezo1',
    type: Piezo,
    cfgfile: "fcf/devmgr/devices/piezo1.yaml"
    },
    {
    name: 'sensor1',
    type: Sensor,
    cfgfile: "fcf/devmgr/devices/sensor1.yaml"
    },
    {
    name: 'adc1',
    type: Adc,
    cfgfile: "fcf/devmgr/devices/adc1.yaml"
    },
    {
    name: 'drot1',
    type: Drot,
    cfgfile: "fcf/devmgr/devices/drot1.yaml"
    }
    ]

Device Base Configuration

Each device has a common set of configuration parameters.

<device id>::type

It specifies the type of the device. Valid types are: Shutter, Lamp, Motor, IODev, SmarAct, Drot, Adc, Piezo and Actuator.

<device id>::interface

It defines the communication interface that will be used by the device. At present, the only valid value is: Softing. This is the name of the OPC-UA toolkit used to communicate to the LCS (PLC). The needed libraries are included in the installation of the ELT standard machine.

<device id>::identifier

It defines the PLC object identifier.

<device id>::namespace

It defines the OPC-UA address space number.

<device id>::prefix

It defines the prefix for the address space nodeId of the device.

<device id>::simulated

Flag indicating if device is simulated.

<device id>::ignored

Flag indicating if the device is ignored. When a device is ignored, the device will ignore most of the commands received by the server until it receives the stop ignoring command (StopIgn).

<device id>::dev_endpoint

It defines the endpoint of the OPCUA server for the device controller.

Note

address has been renamed to dev_endpoint in this version.

<device id>::sim_endpoint

It defines the endpoint of the OPCUA server for the device simulator.

Note

simaddr has been renamed to sim_endpoint in this version.

<device id>::mapfile

File providing the configuration of the attributes in the OPC address space per each of the supported device types.

An example of a mapping file configuration is included below.

!cfg.include fcf/devmgr/definitions/shutterMap.yaml:

Shutter: !cfg.type:ShutterMap
   cfg:
      low_closed:     cfg.bActiveLowClosed
      low_fault:      cfg.bActiveLowFault
      low_open:       cfg.bActiveLowOpen
      low_switch:     cfg.bActiveLowSwitch
      ignore_closed:  cfg.bIgnoreClosed
      ignore_fault:   cfg.bIgnoreFault
      ignore_open:    cfg.bIgnoreOpen
      initial_state:  cfg.bInitialState
      timeout:        cfg.nTimeout
   stat:
      state:         stat.nState
      substate:      stat.nSubstate
      local:         stat.bLocal
      error_code:    stat.nErrorCode
   rpc:
      rpcInit:       RPC_Init
      rpcEnable:     RPC_Enable
      rpcDisable:    RPC_Disable
      rpcClose:      RPC_Close
      rpcOpen:       RPC_Open
      rpcStop:       RPC_Stop
      rpcReset:      RPC_Reset

Note

With the information contained in the mapping file, combined with the PLC prefix and the namespace, the device obtains the NodeId for each of the attributes and the RPCs defined in the ICD with the device controller.

<device id>::fits_prefix

Prefix used by the device when generating the metadata information. This data is included in the FITS file generated by the server at the end of the exposure.

Shutter Specific Configuration

The Shutter device defines a set of configuration parameters that will be transferred to the device controller running in the LCS (PLC). All these parameters are under the ctrl_config heading.

Warning

The ctrl_config parameters are downloaded to the device controller when the device is not Operational. If the controller is already Operational, the user shall force the transition from Operational to NotOperational/NotReady and back to Operational.

Config Item

Type

Optional

Default

Description

ctrl_config::low_closed

bool

yes

false

If true, the closed signal is active low.

ctrl_config::low_fault

bool

yes

false

If true, the fault signal is active low.

ctrl_config::low_open

bool

yes

false

If true, the open signal is active low.

ctrl_config::low_switch

bool

yes

false

If true, the switch signal is active low.

ctrl_config::ignore_closed

bool

yes

false

If true, the closed signal is ignored.

ctrl_config::ignore_fault

bool

yes

false

If true, the fault signal is ignored.

ctrl_config::ignore_open

bool

yes

false

If true, the open signal is ignored.

ctrl_config::initial_state

bool

yes

false

If true, the initial state for shutter will be open.

ctrl_config::timeout

uint

yes

3000 [ms]

Shutter timeout for transitions.

An example of a shutter configuration is given below.

!cfg.include fcf/devmgr/definitions/shutter.yaml:

# Please note some parameters are inherited and therefore not defined here.
shutter1: !cfg.type:Shutter
  identifier: PLC1                             # OPCUA Object Identifier
  prefix: MAIN.Shutter1                        # OPCUA attribute prefix
  simulated: true
  dev_endpoint: opc.tcp://134.171.59.98:4
  sim_endpoint: opc.tcp://127.0.0.1:7576            # Simulation address
  fits_prefix: "SHUT1"
  ctrl_config: !cfg.type:ShutterController
     initial_state:  false                              # If T, initial state is open

Lamp Specific Configuration

The Lamp device defines a set of configuration parameters that will be transferred to the device controller running in the LCS (PLC). All these parameters are under the ctrl_config heading.

Warning

The ctrl_config parameters are downloaded to the device controller when the device is not Operational. If the controller is already Operational, the user shall force the transition from Operational to NotOperational/NotReady and back to Operational.

Config Item

Type

Optional

Default

Description

ctrl_config::low_fault

bool

yes

false

If true, the fault signal is active low.

ctrl_config::low_on

bool

yes

false

If true, the on signal is active low.

ctrl_config::low_switch

bool

yes

false

If true, the switch signal is active low.

ctrl_config::ignore_fault

bool

yes

false

If true, the fault signal is ignored.

ctrl_config::invert_analog

bool

yes

false

If true, the analog feedback is active.

ctrl_config::initial_state

bool

yes

false

If true, the initial state will be switched on.

ctrl_config::analog_threshold

int

yes

0 [bits]

Analog feedback signal threshold

ctrl_config::analog_range

uint

yes

32767

Full range of A/D converter for analog output.

ctrl_config::cooldown

uint

yes

0 [s]

Cooldown time.

ctrl_config::maxon

uint

yes

0 [s]

Maximum time for the lamp to be On. If value is zero means no maximum is defined.

ctrl_config::warmup

uint

yes

0 [s]

Warmup time.

ctrl_config::timeout

uint

yes

3000 [ms]

Lamp timeout for transitions.

An example of a lamp configuration is given below. This configuration file can be found in module devmgr/server

!cfg.include fcf/devmgr/definitions/lamp.yaml:

# Please note some parameters are inherited and therefore not defined here.
lamp1: !cfg.type:Lamp
  identifier: PLC1                             # OPCUA Object Identifier
  prefix: MAIN.Lamp1                           # OPCUA attribute prefix
  dev_endpoint: opc.tcp://134.171.59.98:4840
  sim_endpoint: opc.tcp://134.171.12.182:4840
  fits_prefix: "LAMP1"
  ctrl_config:
     initial_state:    false                     # If T, initial state is on

IODev Specific Configuration

The iodev devices defines currently no configuration that will be downloaded to the LCS. However, it defines the configuration of the iodev channels. The sensor channels are known only at the server side.

Config Item

Type

Optional

Default

Description

norpc

bool

yes

false

Flag to indicate that the device does not support RPCs. This means, no RPC calls to change the state will be executed. This flag is used for special devices running in commercial controllers not running in a PLC but having an embedded OPC-UA server. To be used only in special cases.

sensor

bool

yes

false

Flag to indicate that the iodev is a sensor device. When this flag is active, the iodev only monitors input channels. This is the most typical usage of the iodev device.

ctrl_config::timeout

uint

yes

3000 [ms]

Sensor timeout for transitions.

channels

vector

of

channels

no

na

List of channels.

Each channel contains the following configuration parameters:

Config Item

Type

Optional

Default

Description

name

string

no

“”

Channel name.

description

string

yes

“”

Channel description.

type

string

no

na

Channel type. Allowed types for input channels: DI (bool), AI (double), II (integer).

Allowed types for output channels: DO (bool), AO (double), IO (integer).

header

bool

yes

true

If true, the channel will be included in the metadata FITS file.

log

bool

yes

true

If true, the sensor value will be logged (Not available yet !).

map

string

no

na

Channel internal mapping to the name in the LCS.

prefix

string

no

na

Channel FITS prefix.

unit

string

yes

na

Channel unit.

Warning

The channels parameter has been modified in version 4.0.0 with the porting to the CII config-ng.

An example of a sensor configuration is given below. This configuration file can be found in module devmgr/server. In this case, the sensor device has two channels: ch1 and ch2.

!cfg.include fcf/devmgr/definitions/sensor.yaml:
# Please note some parameters are inherited and therefore not defined here.

sensor1: !cfg.type:Sensor
   identifier: PLC1
   prefix: MAIN.IODev1
   dev_endpoint: opc.tcp://134.171.59.98:4840
   sim_endpoint: opc.tcp://134.171.57.209:4840
   fits_prefix: "SENSOR1"
   ctrl_config:
      timeout:         20000
   channels: [
   {
    name: ch1,
    description: "channel1",
    fits_prefix: "CH1 STAT",
    type: DI,
    header: true,
    log: true,
    unit: mm,
    map: di1
    },
    {
    name: ch2,
    description: "channel2",
    fits_prefix: "CH2 STAT",
    type: DI,
    header: true,
    log: true,
    unit: dd,
    map: di2
    }
    ]

Motor Specific Configuration

The Motor device defines a set of configuration parameters that will be transferred to the device controller running in the LCS (PLC). These parameters are under the ctrl_config heading. The motor initialisation sequence will be also downloaded to the LCS.

The motor also defines a set of configuration parameters that are only known at the server level, for instance the named positions of the motor.

Tolerance of the named position in user units (UU). If the actual position is

within the tolerance, the device will report the named position otherwise its name will be empty.

Warning

The ctrl_config parameters are downloaded to the device controller when the device is not Operational. If the controller is already Operational, the user shall force the transition from Operational to NotOperational/NotReady and back to Operational.

Config Item

Type

Optional

Default

Description

axis_type

string

yes

LINEAR

Axis type. Allowed options are: LINEAR, CIRCULAR and CIRCULAR_OPT.

tolerance

double

yes

1 [uu]

Tolerance of the named position in user units (UU). If the actual position is in the tolerance, the device will report the named position otherwise its name will be empty.

positions

vector

of

positions

no

na

Vector of named positions, see description below.

initialisation | vector
of
steps

no

na

Vector of initialisation steps, see description below.

ctrl_config::min_pos | double

yes

0 [uu]

Minimum position in user units.

ctrl_config::max_pos

double

yes

0 [uu]

Maximum position in user units.

ctrl_config::velocity

double

yes

1.0 [uu/s]

Default velocity for moving the motor in position mode

ctrl_config::active_low_lstop

bool

yes

false

If true, the Lower Stop signal is active low.

ctrl_config::active_low_lhw

bool

yes

false

If true, the Lower Hw signal is active low.

ctrl_config::active_low_ref

bool

yes

false

If true, the Reference signal is active low.

ctrl_config::active_low_index

bool

yes

false

If true, the Index signal is active low.

ctrl_config::active_low_ustop

bool

yes

false

If true, the Upper Stop signal is active low.

ctrl_config::active_low_uhw

bool

yes

false

If true, the Upper Hw signal is active low.

ctrl_config::exec_pre_init

bool

yes

false

If true, the pre-init execution is activate

ctrl_config::exec_post_init

bool

yes

false

If true, the post-init execution is activate.

ctrl_config::exec_pre_move

bool

yes

false

If true, the pre-move execution is activate.

ctrl_config::exec_post_move

bool

yes

false

If true, the post-move execution is activate.

ctrl_config::low_brake

bool

yes

false

If true, the Brake signal is active low.

ctrl_config::low_inpos

bool

yes

false

If true, the In Position signal is active low.

ctrl_config::backlash

double

yes

0 [uu]

Backlash compensation. If value is zero means no backlash compensation is active.

ctrl_config::disable

bool

yes

false

If true, the power of the motor will be disabled after positioning.

ctrl_config::lock

bool

yes

false

If true, the motor position will be locked

ctrl_config::lock_pos

double

yes

0 [uu]

Position that will be locked in case lock configuration is activated.

ctrl_config::lock_tolerance

double

yes

0 [us]

Tolerance of the lock position

ctrl_config::init_timeout

int

yes

60000 [ms]

Motor initialisation timeout.

ctrl_config::move_timeout

int

yes

60000 [ms]

Motor move timeout.

ctrl_config::switch_timeout

int

yes

150000 [ms]

Motor timeout for going out of the switch during initialisation.

Note

An optional parameter in this context means that FCF provides a default value in the parent device type configuration. This default value will be used unless users redefine it in the device instance configuration.

Motor Initialisation

Note

The motor has a set of configuration parameters dedicated to the motor initialisation sequence. The initialisation sequence is downloaded to the LCS only when device controller is not operational.

step

Step name.

value1

Parameter 1 of the initialisation step.

value2

Parameter 2 of the initialisation step.

Note

In case parameters are not applicable (na) please use 0 instead, for instance END, 0, 0

Motor Initialisation Steps

Step

Description

Parameter 1

Parameter 2

END

Finish the sequence, no more actions are performed.

na

na

FIND_INDEX

Motor moves until finding the index pulse.

Fast velocity [UU/s]

Slow velocity [UU/s]

FIND_REF_LE

Motor moves until finding lower edge of reference switch.

Fast velocity [UU/s]

Slow velocity [UU/s]

FIND_REF_UE

Motor moves until finding upper edge of reference switch.

Fast velocity [UU/s]

Slow velocity [UU/s]

FIND_LHW

Motor moves until finding lower hardware limit.

Fast velocity [UU/s]

Slow velocity [UU/s]

FIND_UHW

Motor moves until finding upper hardware limit.

Fast velocity [UU/s]

Slow velocity [UU/s]

DELAY

Motor wait for a fixed amount of time before to continue.

time in [ms]

na

MOVE_ABS

Motor moves to an absolute position.

Velocity [UU/s]

Target position [UU]

MOVE_REL

Motor moves to a relative position.

Velocity [UU/s]

Target position [UU]

CALIB_ABS

Motor calibrates an absolute position.

Position [UU]

na

CALIB_REL

Motor calibrates a relative position.

Position [UU]

na

CALIB_SWITCH

Motor calibrates switch position.

Position [UU]

na

Note

Some of the initialisation steps require parameters, for instance the speed of the motor. These parameters are defined together with the initialisation step.

Named Positions

The motor device supports a configuration of named positions that associate specific motor position in user units (UU) to names. The aim of name positions is to facilitate the setting of motor positions by end users.

name

Position name.

value

Value of the position name in user units (UU).

Note

An example of a motor configuration is given below. This configuration file can be found in module devmgr/server.

!cfg.include fcf/devmgr/definitions/motor.yaml:

# Please note some parameters are inherited and therefore not defined here.
motor1: !cfg.type:Motor
  identifier: PLC1                             # OPCUA Object Identifier
  prefix: MAIN.Synchro1                        # OPCUA attribute prefix
  dev_endpoint: opc.tcp://134.171.59.98:4840
  sim_endpoint: opc.tcp://134.171.57.209:4840       # Simulation address
  fits_prefix: "MOT1"
  ctrl_config:
     velocity:              3.0
     min_pos:               0.0
     max_pos:               359.0
     active_low_ref:        true
     active_low_uhw:        true
  initialisation: [
     {
      step: 'FIND_LHW',
      value1: 4.0,
      value2: 4.0
     },
     {
      step: 'FIND_UHW',
      value1: 4.0,
      value2: 4.0
     },
     {
      step: 'CALIB_ABS',
      value1: 0.0,
      value2: 0.0
     },
     {
      step: 'END',
      value1: 0.0,
      value2: 0.0
     }
   ]
  positions: [
   {
    name: 'ON',
    value: 30
   },
   {
    name: 'OFF',
    value: 100
    }
   ]

Derotator Specific Configuration

As for other devices, the Derotator device defines a set of configuration parameters that will be transferred to the device controller running in the LCS (PLC). All these parameters are under the ctrl_config heading.

Since the Derotator is just an aggregated motor device, it includes all Motor configuration parameters (see fcf_devmgr_motor_config_ref) plus a few parameters specific to derotators.

Warning

The ctrl_config parameters are downloaded to the device controller when the device is not Operational. If the controller is already Operational, the user shall force the transition from Operational to NotOperational/NotReady and back to Operational.

Config Item

Type

Optional

Default

Description

ctrl_config::dir_sign

int

yes

1

Motor direction sign

ctrl_config::focus_sign

int

yes

-1

Focus direction sign.

ctrl_config::trk_period

int

yes

20 [ms]

Period of the tracking corrections within the PLC.

ctrl_config::stat_ref

double

yes

0.0 [uu]

Reference position for stationary mode.

ctrl_config::sky_ref

double

yes

0.0 [uu]

Reference position for sky mode.

ctrl_config::user_ref

double

yes

0.0 [uu]

Reference position for user mode.

ctrl_config::user_par1

double

yes

0.0

Specific parameter 1 for user mode.

ctrl_config::user_par2

double

yes

0.0

Specific parameter 2 for user mode.

ctrl_config::user_par3

double

yes

0.0

Specific parameter 3 for user mode.

ctrl_config::user_par4

double

yes

0.0

Specific parameter 4 for user mode.

Note

An example of a Derotator configuration is given below. This configuration file can be found in module devmgr/server.

!cfg.include fcf/devmgr/definitions/drot.yaml:

# Please note some parameters are inherited and therefore not defined here.
drot1: !cfg.type:Drot
    identifier: PLC1                             # OPCUA Object Identifier
    prefix: MAIN_FAST.drot                       # OPCUA attribute prefix
    dev_endpoint: opc.tcp://134.171.59.98:4840
    sim_endpoint: opc.tcp://134.171.57.209:4840       # Simulation address
    fits_prefix: "DROT1"
    initialisation: [
     {
      step: 'END',
      value1: 0.0,
      value2: 0.0
     }
     ]
    positions: [
     {
     name: 'ON',
     value: 30
     },
     {
     name: 'OFF',
     value: 100
     }
     ]
    ctrl_config:
        velocity:              3.0
        active_low_ref:        true
        active_low_uhw:        true

Note

The derotator uses Circular Optimize (CIRCULAR_OPT) as axis type. In this axis mode you have to reset the software limits to zero or simply not define them.

Derotator Control

Operation modes

Alias

Name

Description

eng

Engineering

In this mode, the Derotator behaves like a standard motor. This means that it can be moved in user units and encoders.

stat

Stationary

In this mode, the Derotator is stationary and it can be positioned at given angle according to the following formula:

pos := stat_ref + dir_sign * (posang)/2.0;

sky

Sky

The Derotator tracks following the field rotation.

fieldRotation := parallactic - focus_sign * altitude;

pos := sky_ref + dir_sign * (posang - fieldRotation)/2;

angleOnSky := posang;

modeAngle := angleOnSky;

elev

Elevation

The Derotator tracks following the pupil rotation.

pos := elev_ref + (focus_sign * dir_sign * altitude) /2.0;

angleOnSky := parallactic;

modeAngle := angleOnSky;

user

User

The Derotator tracks according to the user custom computation.

ADC Specific Configuration

As for other devices, the ADC device defines a set of configuration parameters that will be transferred to the device controller running in the LCS (PLC). These parameters are under the ctrl_config heading. Considering that the ADC is a multi-axis device, it includes as well the configuration of two standard motor devices. The configuration of each motor device is defined in separate files and they correspond to the configuration of a standard motor device (see fcf_devmgr_motor_config_ref).

Warning

The ctrl_config parameters are downloaded to the device controller when the device is not Operational. If the controller is already Operational, the user shall force the transition from Operational to NotOperational/NotReady and back to Operational.

Config Item

Type

Optional

Default

Description

ctrl_config::motors

vector

no

Vector of motors controlled by the ADC. See the table below.

ctrl_config::trk_period

int

yes

20 [ms]

Period of the tracking corrections within the PLC.

ctrl_config::pslope

double

yes

0.0023 [arcsec/mbar]

Pressure slope.

ctrl_config::poffset

double

yes

743.0 [mbar]

Pressure offset.

ctrl_config::tslope

double

yes

-0.0061 [arcsec/C]

Temperature slope.

ctrl_config::toffset

double

yes

12 [C]

Temperature offset.

ctrl_config::afactor

double

yes

3.32 [1/arcsec]

A Factor

ctrl_config::zdlimit

double

yes

0.0174533

Zenith distance limit

ctrl_config::minelev

double

yes

27.64 [deg]

Minimum Elevation.

ctrl_config::mot1_signoff

int

yes

1

Motor 1 sign for off mode

ctrl_config::mot1_signauto

int

yes

1

Motor 1 sign for auto mode

ctrl_config::mot1_signphi

int

yes

1

Motor 1 sign for phi

ctrl_config::mot1_refoff

double

yes

0 [deg]

Motor 1 offset for off mode

ctrl_config::mot1_refauto

double

yes

0 [deg]

Motor 1 offset for auto mode

ctrl_config::mot1_coffset

double

yes

1.7387 [arcsec]

Motor 1 C parameter

ctrl_config::mot1_poffset

double

yes

90 [deg]

Motor 1 Position offset

ctrl_config::mot1_drotfactor

double

yes

2

Motor 1 derotator offset

ctrl_config::mot2_signoff

int

yes

1

Motor 2 sign for off mode

ctrl_config::mot2_signauto

int

yes

1

Motor 2 sign for auto mode

ctrl_config::mot2_signphi

int

yes

1

Motor 2 sign for phi

ctrl_config::mot2_refoff

double

yes

0 [deg]

Motor 2 reference position for off mode

ctrl_config::mot2_refauto

double

yes

0 [deg]

Motor 2 reference position for auto mode

ctrl_config::mot2_coffset

double

yes

1.7387 [arcsec]

Motor 2 C parameter

ctrl_config::mot2_poffset

double

yes

90 [deg]

Motor 2 Position offset

ctrl_config::mot2_drotfactor

double

yes

2

Motor 2 derotator offset

Each element in the motor vector has the following parameters:

Config Item

Type

Optional

Default

Description

name

string

no

Name of the motor configuration.

prefix

string

no

Internal name used by the ADC for motor1 (fixed)

cfgfile

string

no

File path for the motor configuration.

Note

An example of an Adc configuration is given below. This configuration file can be found in module devmgr/server.

!cfg.include fcf/devmgr/definitions/adc.yaml:

# Please note some parameters are inherited and therefore not defined here.
adc1: !cfg.type:Adc
    identifier: PLC1                             # OPCUA Object Identifier
    prefix: MAIN_FAST.adc                       # OPCUA attribute prefix
    dev_endpoint: opc.tcp://134.171.59.98:4840
    sim_endpoint: opc.tcp://134.171.57.209:4840       # Simulation address
    fits_prefix: "ADC1"
    ctrl_config:
    motors: [
    {
        name: 'adc1_motor1',
        prefix: "motor1",
        cfgfile: "fcf/devmgr/devices/adc1Motor1.yaml"
    },
    {
        name: 'adc1_motor2',
        prefix: "motor2",
        cfgfile: "fcf/devmgr/devices/adc1Motor2.yaml"
    }
    ]

ADC Control

Operation modes

The ADC operates two motorized functions. In engineering mode, each motor can be controlled independently.

Alias

Name

Description

eng

Engineering

In this mode, the ADC behaves like the standard motor. This means that each motor can be moved in user units and encoders.

off

Off

In this mode, the ADC is stationary and it can be positioned at given angle according to the following formula:

pos := off_ref + sign_off * posang;

auto

Auto

The ADC tracks following the default formula. This formula can be replaced by the user in order to accommodate instrument specific requirements.

Piezo Specific Configuration

The Piezo device defines a set of configuration parameters that will be transferred to the device controller running in the LCS (PLC). All these parameters are under the ctrl_config heading.

Warning

The ctrl_config parameters are downloaded to the device controller when the device is not Operational. If the controller is already Operational, the user shall force the transition from Operational to NotOperational/NotReady and back to Operational.

Config Item

Type

Optional

Default

Description

ctrl_config::num_axes

short

no

3

Configured number of piezo axes. This parameter gives flexibility to adapt to different type of piezos.

ctrl_config::max_on

int

yes

0

Maximum time that outputs will be maintained. If it is zero means there is no time counter.

ctrl_config::full_range[]

short

yes

32767

Full range per axes in bits.

ctrl_config::home[]

double

yes

0

Home position per axes in user units.

ctrl_config::lower_limit[]

double

yes

0

lower limit per axes in user units.

ctrl_config::upper_limit[]

double

yes

32767

upper limit per axes in user units.

ctrl_config::user_to_bit_input[]

double

yes

3276.7

user to bit conversion factor per axes for inputs.

ctrl_config::user_offset_input[]

double

yes

0

user offset per axes for inputs.

ctrl_config::user_to_bit_output[]

double

yes

3276.7

user to bit conversion factor per axes for outputs.

ctrl_config::user_offset_output[]

double

yes

0

user offset per axes for outputs.

An example of a piezo configuration is provided below.

!cfg.include fcf/devmgr/definitions/piezo.yaml:

# Please note some parameters are inherited and therefore not defined here.
piezo1: !cfg.type:Piezo
    identifier: PLC1                             # OPCUA Object Identifier
    prefix: MAIN.Piezo1                       # OPCUA attribute prefix
    dev_endpoint: opc.tcp://134.171.59.98:4840
    sim_endpoint: opc.tcp://134.171.57.209:4840       # Simulation address
    fits_prefix: "MOT1"
    ctrl_config:
        num_axis:      3
        max_on:        180

Actuator Specific Configuration

The Actuator is one of the few devices that is not transferring any configuration to the controller in the transition from Ready to Operational. The Actuator assumes to have all the configuration defined in the controller (PLC). For knowing the controller configuration, please refer to the PLC Actuator section.

An example of a actuator configuration is provided below.

!cfg.include fcf/devmgr/definitions/actuator.yaml:

# Please note some parameters are inherited and therefore not defined here.
actuator1: !cfg.type:Actuator
    identifier: PLC1                             # OPCUA Object Identifier
    prefix: MAIN.Actuator1                       # OPCUA attribute prefix
    address: opc.tcp://134.171.59.99:4840
    simaddr: opc.tcp://134.171.12.182:4840      # Simulation address
    fits_prefix: "MECH1"
    ctrl_config:

Database Attributes

The Device Manager uses the Redis DB to store the actual server configuration and run-time parameters. The Redis keys used by the server follow a hierarchical naming convention starting with the id of the server. Specific keys for devices use the id of the device in the name. The DB keys can be monitored using the dbbrowser utility. All Device Manager keys have a flat structure in Redis DB.

alternate text

dbbrowser utility

Server configuration

The server stores the actual values of the server configuration parameters into the Redis DB . This helps to verify whether the configuration has been loaded correctly. For details of the server configuration parameters, see CII Configuration Service (config-ng).

Server configuration Redis DB keys

Redis Key

<instrument id>.<server id>.cfg.db_endpoint

<instrument id>.<server id>.cfg.db_timeout

<instrument id>.<server id>.cfg.dictionaries

<instrument id>.<server id>.cfg.filename

<instrument id>.<server id>.cfg.fits_prefi

<instrument id>.<server id>.cfg.log_properties

<instrument id>.<server id>.cfg.mon_timeout

<instrument id>.<server id>.cfg.oldb_prefix

<instrument id>.<server id>.cfg.pub_endpoint

<instrument id>.<server id>.cfg.req_endpoint

<instrument id>.<server id>.cfg.scxml

<instrument id>.<server id>.cfg.server_id

Server Status

The server stores the string representation of its state and substate into the Redis DB.

Server status Redis DB keys

Redis Key

<instrument id>.<server id>.states.state

<instrument id>.<server id>.states.substate

Common Device Keys

Each device has a number of common Redis DB keys.

Common device Redis DB keys

Redis Key

<instrument id>.<server id>.cfg.devices.<device id>.dev_endpoint

<instrument id>.<server id>.cfg.devices.<device id>.sim_endpoint

<instrument id>.<server id>.cfg.devices.<device id>.cfgfile

<instrument id>.<server id>.cfg.devices.<device id>.fits_prefix

<instrument id>.<server id>.cfg.devices.<device id>.ignored

<instrument id>.<server id>.cfg.devices.<device id>.simulated

<instrument id>.<server id>.cfg.devices.<device id>.namespace

<instrument id>.<server id>.cfg.devices.<device id>.prefix

<instrument id>.<server id>.cfg.devices.<device id>.type

Shutter

Each shutter device defines a set of specific Redis DB keys:

Shutter Specific Redis DB keys

Redis Key

<instrument id>.<server id>.cfg.devices.<device id>.lcs.ignore_closed

<instrument id>.<server id>.cfg.devices.<device id>.lcs.ignore_fault

<instrument id>.<server id>.cfg.devices.<device id>.lcs.ignore_open

<instrument id>.<server id>.cfg.devices.<device id>.lcs.initial_state

<instrument id>.<server id>.cfg.devices.<device id>.lcs.low_closed

<instrument id>.<server id>.cfg.devices.<device id>.lcs.low_fault

<instrument id>.<server id>.cfg.devices.<device id>.lcs.low_open

<instrument id>.<server id>.cfg.devices.<device id>.lcs.low_switch

<instrument id>.<server id>.cfg.devices.<device id>.lcs.timeout

<instrument id>.<server id>.devices.<device id>.lcs.stat.error_code

<instrument id>.<server id>.devices.<device id>.lcs.stat.error_str

<instrument id>.<server id>.devices.<device id>.lcs.stat.local

<instrument id>.<server id>.devices.<device id>.lcs.stat.state

<instrument id>.<server id>.devices.<device id>.lcs.stat.substate

Lamp

Each lamp device defines a set of specific Redis DB keys:

Lamp Redis DB keys

Redis Key

<instrument id>.<server id>.cfg.devices.<device id>.lcs.analog_range

<instrument id>.<server id>.cfg.devices.<device id>.lcs.analog_threshold

<instrument id>.<server id>.cfg.devices.<device id>.lcs.cooldown

<instrument id>.<server id>.cfg.devices.<device id>.lcs.ignore_fault

<instrument id>.<server id>.cfg.devices.<device id>.lcs.initial_state

<instrument id>.<server id>.cfg.devices.<device id>.lcs.invert_analog

<instrument id>.<server id>.cfg.devices.<device id>.lcs.low_fault

<instrument id>.<server id>.cfg.devices.<device id>.lcs.low_on

<instrument id>.<server id>.cfg.devices.<device id>.lcs.low_switch

<instrument id>.<server id>.cfg.devices.<device id>.lcs.maxon

<instrument id>.<server id>.cfg.devices.<device id>.lcs.timeout

<instrument id>.<server id>.cfg.devices.<device id>.lcs.warmup

<instrument id>.<server id>.devices.<device id>.lcs.stat.error_code

<instrument id>.<server id>.devices.<device id>.lcs.stat.error_str

<instrument id>.<server id>.devices.<device id>.lcs.stat.intensity

<instrument id>.<server id>.devices.<device id>.lcs.stat.local

<instrument id>.<server id>.devices.<device id>.lcs.stat.state

<instrument id>.<server id>.devices.<device id>.lcs.stat.substate

IODev

Each iodev device defines a set of specific Redis DB keys:

Sensor Redis DB keys

Redis Key

<instrument id>.<server id>.cfg.devices.<device id>.<channel id>.description

<instrument id>.<server id>.cfg.devices.<device id>.<channel id>.fits_prefix

<instrument id>.<server id>.cfg.devices.<device id>.<channel id>.header

<instrument id>.<server id>.cfg.devices.<device id>.<channel id>.log

<instrument id>.<server id>.cfg.devices.<device id>.<channel id>.map

<instrument id>.<server id>.cfg.devices.<device id>.<channel id>.type

<instrument id>.<server id>.cfg.devices.<device id>.<channel id>.unit

<instrument id>.<server id>.devices.<device id>.lcs.stat.<channel id>

<instrument id>.<server id>.devices.<device id>.lcs.stat.state

<instrument id>.<server id>.devices.<device id>.lcs.stat.substate

Motor

Each motor device defines a set of specific Redis DB keys:

Motor Redis DB keys

Redis Key

<instrument id>.<server id>.cfg.devices.<device id>.lcs.active_low_indec

<instrument id>.<server id>.cfg.devices.<device id>.lcs.active_low_lhw

<instrument id>.<server id>.cfg.devices.<device id>.lcs.active_low_lstop

<instrument id>.<server id>.cfg.devices.<device id>.lcs.active_low_ref

<instrument id>.<server id>.cfg.devices.<device id>.lcs.active_low_uhw

<instrument id>.<server id>.cfg.devices.<device id>.lcs.active_low_ustop

<instrument id>.<server id>.cfg.devices.<device id>.lcs.axis_type

<instrument id>.<server id>.cfg.devices.<device id>.lcs.backlash

<instrument id>.<server id>.cfg.devices.<device id>.lcs.brake

<instrument id>.<server id>.cfg.devices.<device id>.lcs.check_inpos

<instrument id>.<server id>.cfg.devices.<device id>.lcs.disable

<instrument id>.<server id>.cfg.devices.<device id>.lcs.exec_post_init

<instrument id>.<server id>.cfg.devices.<device id>.lcs.exec_post_move

<instrument id>.<server id>.cfg.devices.<device id>.lcs.exec_pre_init

<instrument id>.<server id>.cfg.devices.<device id>.lcs.exec_pre_move

<instrument id>.<server id>.cfg.devices.<device id>.lcs.init_seq<number>_action

<instrument id>.<server id>.cfg.devices.<device id>.lcs.init_seq<number>_value1

<instrument id>.<server id>.cfg.devices.<device id>.lcs.init_seq<number>_value2

<instrument id>.<server id>.cfg.devices.<device id>.lcs.lock

<instrument id>.<server id>.cfg.devices.<device id>.lcs.lock_pos

<instrument id>.<server id>.cfg.devices.<device id>.lcs.lock_tolerance

<instrument id>.<server id>.cfg.devices.<device id>.lcs.low_brake

<instrument id>.<server id>.cfg.devices.<device id>.lcs.low_inpos

<instrument id>.<server id>.cfg.devices.<device id>.lcs.max_pos

<instrument id>.<server id>.cfg.devices.<device id>.lcs.min_pos

<instrument id>.<server id>.cfg.devices.<device id>.lcs.tout_init

<instrument id>.<server id>.cfg.devices.<device id>.lcs.tout_move

<instrument id>.<server id>.cfg.devices.<device id>.lcs.tout_switch

<instrument id>.<server id>.cfg.devices.<device id>.lcs.velocity

<instrument id>.<server id>.devices.<device id>.lcs.stat.axis_brake

<instrument id>.<server id>.devices.<device id>.lcs.stat.axis_enable

<instrument id>.<server id>.devices.<device id>.lcs.stat.axis_info_data1

<instrument id>.<server id>.devices.<device id>.lcs.stat.inposition

<instrument id>.<server id>.devices.<device id>.lcs.stat.lock

<instrument id>.<server id>.devices.<device id>.lcs.stat.ready

<instrument id>.<server id>.devices.<device id>.lcs.stat.error_code

<instrument id>.<server id>.devices.<device id>.lcs.stat.error_str

<instrument id>.<server id>.devices.<device id>.lcs.stat.init_action

<instrument id>.<server id>.devices.<device id>.lcs.stat.init_step

<instrument id>.<server id>.devices.<device id>.lcs.stat.initialised

<instrument id>.<server id>.devices.<device id>.lcs.stat.local

<instrument id>.<server id>.devices.<device id>.lcs.stat.mode

<instrument id>.<server id>.devices.<device id>.lcs.stat.pos_actual

<instrument id>.<server id>.devices.<device id>.lcs.stat.pos_error

<instrument id>.<server id>.devices.<device id>.lcs.stat.pos_target

<instrument id>.<server id>.devices.<device id>.lcs.stat.scale_factor

<instrument id>.<server id>.devices.<device id>.lcs.stat.signal_index

<instrument id>.<server id>.devices.<device id>.lcs.stat.signal_lhw

<instrument id>.<server id>.devices.<device id>.lcs.stat.signal_lstop

<instrument id>.<server id>.devices.<device id>.lcs.stat.signal_ref

<instrument id>.<server id>.devices.<device id>.lcs.stat.signal_uhw

<instrument id>.<server id>.devices.<device id>.lcs.stat.signal_ustop

<instrument id>.<server id>.devices.<device id>.lcs.stat.state

<instrument id>.<server id>.devices.<device id>.lcs.stat.substate

<instrument id>.<server id>.devices.<device id>.lcs.stat.vel_actual

<instrument id>.<server id>.devices.<device id>.pos_actual_name

<instrument id>.<server id>.devices.<device id>.pos_enc

<instrument id>.<server id>.devices.<device id>.target_enc

Derotator

The Derotator device uses the same set of Redis keys as the Motor device plus some additional derotator specific ones that are described below:

Derotator Redis DB keys

Redis Key

<instrument id>.<server id>.cfg.devices.<device id>.lcs.trk_period

<instrument id>.<server id>.cfg.devices.<device id>.lcs.user_par1

<instrument id>.<server id>.cfg.devices.<device id>.lcs.user_par2

<instrument id>.<server id>.cfg.devices.<device id>.lcs.user_par3

<instrument id>.<server id>.cfg.devices.<device id>.lcs.user_par4

<instrument id>.<server id>.cfg.devices.<device id>.lcs.user_ref

<instrument id>.<server id>.cfg.devices.<device id>.lcs.sky_ref

<instrument id>.<server id>.cfg.devices.<device id>.lcs.tat_ref

<instrument id>.<server id>.devices.<device id>.lcs.stat.angle_on_sky

<instrument id>.<server id>.devices.<device id>.lcs.stat.alpha

<instrument id>.<server id>.devices.<device id>.lcs.stat.delta

<instrument id>.<server id>.devices.<device id>.lcs.stat.track_mode

ADC

The Adc device defines a set of specific Redis keys:

Adc Redis DB keys

Redis Key

<instrument id>.<server id>.cfg.devices.<device id>.lcs.trk_period

<instrument id>.<server id>.cfg.devices.<device id>.lcs.afactor

<instrument id>.<server id>.cfg.devices.<device id>.lcs.minelev

<instrument id>.<server id>.cfg.devices.<device id>.lcs.poffset

<instrument id>.<server id>.cfg.devices.<device id>.lcs.pslope

<instrument id>.<server id>.cfg.devices.<device id>.lcs.toffset

<instrument id>.<server id>.cfg.devices.<device id>.lcs.tslope

<instrument id>.<server id>.cfg.devices.<device id>.lcs.zdlimit

<instrument id>.<server id>.cfg.devices.<device id>.lcs.mot1_coffset

<instrument id>.<server id>.cfg.devices.<device id>.lcs.mot1_drotfactor

<instrument id>.<server id>.cfg.devices.<device id>.lcs.mot1_poffset

<instrument id>.<server id>.cfg.devices.<device id>.lcs.mot1_refauto

<instrument id>.<server id>.cfg.devices.<device id>.lcs.mot1_refoff

<instrument id>.<server id>.cfg.devices.<device id>.lcs.mot2_coffset

<instrument id>.<server id>.cfg.devices.<device id>.lcs.mot2_drotfactor

<instrument id>.<server id>.cfg.devices.<device id>.lcs.mot2_poffset

<instrument id>.<server id>.cfg.devices.<device id>.lcs.mot2_refauto

<instrument id>.<server id>.cfg.devices.<device id>.lcs.mot2_refoff

<instrument id>.<server id>.cfg.devices.<device id>.ignored

<instrument id>.<server id>.cfg.devices.<device id>.simulated

<instrument id>.<server id>.devices.<device id>.lcs.stat.alpha

<instrument id>.<server id>.devices.<device id>.lcs.stat.delta

<instrument id>.<server id>.devices.<device id>.lcs.stat.error_code

<instrument id>.<server id>.devices.<device id>.lcs.stat.error_str

<instrument id>.<server id>.devices.<device id>.lcs.stat.local

<instrument id>.<server id>.devices.<device id>.lcs.stat.state

<instrument id>.<server id>.devices.<device id>.lcs.stat.substate

<instrument id>.<server id>.devices.<device id>.lcs.stat.track_mode

<instrument id>.<server id>.devices.<device id>.lcs.stat.motor1.axis_brake

<instrument id>.<server id>.devices.<device id>.lcs.stat.motor1.axis_enable

<instrument id>.<server id>.devices.<device id>.lcs.stat.motor1.axis_lock

<instrument id>.<server id>.devices.<device id>.lcs.stat.motor1.local

<instrument id>.<server id>.devices.<device id>.lcs.stat.motor1.pos_actual

<instrument id>.<server id>.devices.<device id>.lcs.stat.motor1.pos_enc

<instrument id>.<server id>.devices.<device id>.lcs.stat.motor1.scale_factor

<instrument id>.<server id>.devices.<device id>.lcs.stat.motor2.axis_brake

<instrument id>.<server id>.devices.<device id>.lcs.stat.motor2.axis_enable

<instrument id>.<server id>.devices.<device id>.lcs.stat.motor2.axis_lock

<instrument id>.<server id>.devices.<device id>.lcs.stat.motor2.local

<instrument id>.<server id>.devices.<device id>.lcs.stat.motor2.pos_actual

<instrument id>.<server id>.devices.<device id>.lcs.stat.motor2.pos_enc

<instrument id>.<server id>.devices.<device id>.lcs.stat.motor2.scale_factor

<instrument id>.<server id>.devices.<device id>.motor1.pos_enc

<instrument id>.<server id>.devices.<device id>.motor2.pos_enc

Piezo

The Piezo device defines a set of specific Redis keys:

Piezo Redis DB keys

Redis Key

<instrument id>.<server id>.cfg.devices.<device id>.lcs.home1

<instrument id>.<server id>.cfg.devices.<device id>.lcs.home2

<instrument id>.<server id>.cfg.devices.<device id>.lcs.home3

<instrument id>.<server id>.cfg.devices.<device id>.lcs.lower_limit1

<instrument id>.<server id>.cfg.devices.<device id>.lcs.lower_limit2

<instrument id>.<server id>.cfg.devices.<device id>.lcs.lower_limit3

<instrument id>.<server id>.cfg.devices.<device id>.lcs.upper_limit1

<instrument id>.<server id>.cfg.devices.<device id>.lcs.upper_limit2

<instrument id>.<server id>.cfg.devices.<device id>.lcs.upper_limit3

<instrument id>.<server id>.cfg.devices.<device id>.lcs.max_on

<instrument id>.<server id>.cfg.devices.<device id>.lcs.num_axes

<instrument id>.<server id>.cfg.devices.<device id>.lcs.user_offset_input1

<instrument id>.<server id>.cfg.devices.<device id>.lcs.user_offset_input2

<instrument id>.<server id>.cfg.devices.<device id>.lcs.user_offset_input3

<instrument id>.<server id>.cfg.devices.<device id>.lcs.user_to_bit_input1

<instrument id>.<server id>.cfg.devices.<device id>.lcs.user_to_bit_input2

<instrument id>.<server id>.cfg.devices.<device id>.lcs.user_to_bit_input3

<instrument id>.<server id>.cfg.devices.<device id>.lcs.user_offset_output1

<instrument id>.<server id>.cfg.devices.<device id>.lcs.user_offset_output2

<instrument id>.<server id>.cfg.devices.<device id>.lcs.user_offset_output3

<instrument id>.<server id>.cfg.devices.<device id>.lcs.user_to_bit_output1

<instrument id>.<server id>.cfg.devices.<device id>.lcs.user_to_bit_output2

<instrument id>.<server id>.cfg.devices.<device id>.lcs.user_to_bit_output3

<instrument id>.<server id>.devices.<device id>.lcs.stat.actual_pos_bit1

<instrument id>.<server id>.devices.<device id>.lcs.stat.actual_pos_bit2

<instrument id>.<server id>.devices.<device id>.lcs.stat.actual_pos_bit3

<instrument id>.<server id>.devices.<device id>.lcs.stat.actual_pos_user1

<instrument id>.<server id>.devices.<device id>.lcs.stat.actual_pos_user2

<instrument id>.<server id>.devices.<device id>.lcs.stat.actual_pos_user3

<instrument id>.<server id>.devices.<device id>.lcs.stat.error_codes

<instrument id>.<server id>.devices.<device id>.lcs.stat.error_str

<instrument id>.<server id>.devices.<device id>.lcs.stat.local

<instrument id>.<server id>.devices.<device id>.lcs.stat.state

<instrument id>.<server id>.devices.<device id>.lcs.stat.substate

Actuator

Each actuator device defines a set of specific Redis DB keys:

Actuator Redis DB keys

Redis Key

<instrument id>.<server id>.devices.<device id>.lcs.stat.local

<instrument id>.<server id>.devices.<device id>.lcs.stat.state

<instrument id>.<server id>.devices.<device id>.lcs.stat.substate

<instrument id>.<server id>.devices.<device id>.lcs.stat.error_code

<instrument id>.<server id>.devices.<device id>.lcs.stat.error_str

Command Interface

The commands currently supported by the server are listed here: List of Commands.

Error Handling

FCF Commands throw exceptions in case of errors or timeouts. Client applications can catch the exceptions and obtain the error message associated with the function getDesc(). This error does not contain neither the history nor the error stack but it normally indicates precisely where the error occurred.

try {
    auto reply = client->GetStatus();
 } catch (const fcfif::ExceptionErr& e) {
    RAD_LOG_ERROR() << "Error reply " << e.getDesc()  << ").";
}

Serialization

The Device Manager uses the CII MAL ZPB (ZeroMQ + Google Proto buffers) for serialising commands.

Note

Each command has two parts: a payload and its corresponding reply, see the details in the fcfif module. The normal replies are plain strings.

Setup Command

The Setup command is intended to produce a change in the run-time configuration. It is also a way of triggering operational actions on the devices. It is possible to switch a lamp on, close a shutter and move a motor in separate messages or within the same one. This means that the content of the message varies. The devices will de-serialise the message and communicate the actions to be taken to the corresponding PLCs via the interface with the LCS.

The DevMgr is not blocked when receiving concurrent Setup commands (messages). It executes them in separate worker threads that are spawned per each new Setup command. The threads will be running until the commands have been executed successfully, an error occured, the timeout has elapsed or a Stop command is received, see figure below.

alternate text

Device Manager Setup worker threads.

Note

A Stop command finalizes all ongoing worker threads that are being handled by the Device Manager.

Warning

Conflicting requests across different Setup commands running in parallel are not handled by the Device Manager. They are pushed down to the PLC. The PLC is resolving them depending on the actual status. This means that, if the user sends two consecutive commands with conflicting requests, most likely the second one will get an error from the PLC. The exact behaviour will depend on the specific Device Controller implementation.

Setup Interface Definition

The interface definition of the Setup command can be found in module fcfif. The payload is based on an array of unions. The union may contain any device supported by the Device Manager.

<union name="DeviceUnion">
    <discriminator type="nonBasic" nonBasicTypeName="DeviceType" />
    <case>
        <caseDiscriminator value ="SHUTTER"/>
            <member name="shutter" type="nonBasic" nonBasicTypeName="ShutterDevice" />
    </case>
    <case>
        <caseDiscriminator value ="LAMP"/>
            <member name="lamp" type="nonBasic" nonBasicTypeName="LampDevice" />
    </case>
    <case>
    <caseDiscriminator value ="MOTOR"/>
            <member name="motor" type="nonBasic" nonBasicTypeName="MotorDevice" />
    </case>
    <case>
    <caseDiscriminator value ="DROT"/>
            <member name="drot" type="nonBasic" nonBasicTypeName="DrotDevice" />
    </case>
    <case>
    <caseDiscriminator value ="ADC"/>
            <member name="adc" type="nonBasic" nonBasicTypeName="AdcDevice" />
    </case>
    <case>
    <caseDiscriminator value ="PIEZO"/>
            <member name="piezo" type="nonBasic" nonBasicTypeName="PiezoDevice" />
    </case>
    <case>
    <caseDiscriminator value ="ACTUATOR"/>
            <member name="actuator" type="nonBasic" nonBasicTypeName="ActuatorDevice" />
    </case>
    <case>
    <caseDiscriminator value ="IODEV"/>
            <member name="iodev" type="nonBasic" nonBasicTypeName="IODevDevice" />
    </case>
    <case>
    <caseDiscriminator value ="CUSTOM"/>
            <member name="custom" type="nonBasic" nonBasicTypeName="CustomDevice" />
    </case>
</union>

Warning

The array does not have a fixed size but it has a limit of 100 elements. A limit is needed by the CII XML ICD.

<method name="Setup" returnType="string" throws="ExceptionErr">
    <argument name="payload" type="nonBasic" nonBasicTypeName="SetupElem" arrayDimensions="(100)"/>
</method>

Each device structure may contain parameters and one action per device that can be serialized. An example of the device ICD is shown below.

<struct name="ShutterDevice">
    <member name="id" type="string" />
    <member name="action" type="nonBasic" nonBasicTypeName="ActionShutter" />
</struct>

<struct name="LampDevice">
    <member name="id" type="string" />
    <member name="intensity" type="double" />
    <member name="time" type="uint32_t" />
    <member name="action" type="nonBasic" nonBasicTypeName="ActionLamp" />
</struct>

<struct name="BaseMotorDevice">
   <member name="id" type="string" />
    <member name="name" type="string" />
    <member name="pos" type="double" />
    <member name="enc" type="int64_t" />
    <member name="speed" type="double" />
    <member name="unit" type="nonBasic" nonBasicTypeName="MotorPosUnit" />
</struct>

<struct name="MotorDevice" baseType="BaseMotor">
    <member name="action" type="nonBasic" nonBasicTypeName="ActionMotor" />
</struct>

<struct name="DrotDevice" baseType="BaseMotor">
    <member name="mode" type="nonBasic" nonBasicTypeName="ModeDrot" />
    <member name="action" type="nonBasic" nonBasicTypeName="ActionDrot" />
</struct>

<struct name="AdcDevice" baseType="BaseMotor">
    <member name="axis" type="nonBasic" nonBasicTypeName="AxesAdc" />
    <member name="mode" type="nonBasic" nonBasicTypeName="ModeAdc" />
    <member name="action" type="nonBasic" nonBasicTypeName="ActionAdc" />
</struct>

<struct name="PiezoDevice">
    <member name="id" type="string" />
    <member name="bit1" type="uint32_t" />
    <member name="bit2" type="uint32_t" />
    <member name="bit3" type="uint32_t" />
    <member name="pos1" type="double" />
    <member name="pos2" type="double" />
    <member name="pos3" type="double" />
    <member name="action" type="nonBasic" nonBasicTypeName="ActionPiezo" />
</struct>

<struct name="ActuatorDevice">
    <member name="id" type="string" />
    <member name="action" type="nonBasic" nonBasicTypeName="ActionActuator" />
</struct>

<struct name="IODevDevice">
    <member name="digarray" type="nonBasic" nonBasicTypeName="DigitalElem" arrayDimensions="(30)" />
    <member name="anlgarray" type="nonBasic" nonBasicTypeName="AnalogElem" arrayDimensions="(30)" />
    <member name="intarray" type="nonBasic" nonBasicTypeName="IntegerElem" arrayDimensions="(30)" />
    <member name="action" type="nonBasic" nonBasicTypeName="ActionIODev" />
</struct>

<struct name="CustomDevice">
    <member name="parameters" type="string" />
</struct>

Note

The CustomDevice is to be used for implementing custom devices where the payload data can be serialized in JSON. The serialization shall be done by the client applications using the parameters in the CustomDevice structure to carry the information encoded in JSON. The above enables extendability without the need to provide specific CII XML ICDs which is a significant simplification for instruments.

DevStatus Command

The DevStatus command provides information about each device controlled by the Device Manager. An example of the output generated by the DevStatus command is shown below.

$ fcfClient zpb.rr://127.0.0.1:12083 DevStatus ""
shutter1.simulated = true
shutter1.lcs.state = Operational
shutter1.lcs.substate = Close
lamp1.simulated = true
lamp1.lcs.state = Operational
lamp1.lcs.substate = Off
lamp1.lcs.intensity = 0.000000
motor1.simulated = true
motor1.lcs.state = Operational
motor1.lcs.substate = Standstill
motor1.lcs.pos_target = 30.000000
motor1.lcs.pos_actual = 30.002197
motor1.lcs.vel_actual = 0.000000
motor1.lcs.axis_enable = true
motor1.pos_actual_name = ON
motor1.pos_enc = 341

OK

The user could request the status of a specific device or a subset of the devices, see below.

$ fcfClient zpb.rr://127.0.0.1:12083 DevStatus "motor1"
motor1.simulated = true
motor1.lcs.state = Operational
motor1.lcs.substate = Standstill
motor1.lcs.pos_target = 30.000000
motor1.lcs.pos_actual = 30.002197
motor1.lcs.vel_actual = 0.000000
motor1.lcs.axis_enable = true
motor1.pos_actual_name = ON
motor1.pos_enc = 341

OK

$ fcfClient zpb.rr://127.0.0.1:12083 DevStatus "lamp1, motor1"
lamp1.simulated = true
lamp1.lcs.state = Operational
lamp1.lcs.substate = Off
lamp1.lcs.intensity = 0.000000
motor1.simulated = true
motor1.lcs.state = Operational
motor1.lcs.substate = Standstill
motor1.lcs.pos_target = 30.000000
motor1.lcs.pos_actual = 30.002197
motor1.lcs.vel_actual = 0.000000
motor1.lcs.axis_enable = true
motor1.pos_actual_name = ON
motor1.pos_enc = 341

OK

Note

The list of devices is comma-separated.

Ignore Command

This command tells the Device Manager to completely ignore a device. It can be used when there are hardware failures or when the hardware is not yet available. The following example shows a sequence that ignores device lamp1, gets the status of the devices and then stops ignoring the device.

Note

When a device is ignored, no other information is provided for this device when processing the status command.

$ fcfClient zpb.rr://127.0.0.1:12083 Ignore "lamp1"
$ fcfClient zpb.rr://127.0.0.1:12083 Status "lamp1"
lamp1.ignored = true

OK
$ fcfClient zpb.rr://127.0.0.1:12083 StopIgn "lamp1"
$ fcfClient zpb.rr://127.0.0.1:12083 Status "lamp1"
lamp1.simulated = true
lamp1.lcs.state = Operational
lamp1.lcs.substate = Off
lamp1.lcs.intensity = 0.000000

OK

Simulate Command

This command tells the Device Manager to use the simulation address of the device. If the Device Manager is already connected, it will disconnect from the normal address and connect to the simulator. When the simulation is stopped, the server reverts the action and the device is back to normal mode.

The purpose of the simulation is to be able to validate the response of the Device Manager under different error conditions. It also allows to test the high-level SW when the HW is not yet available.

$ fcfClient zpb.rr://127.0.0.1:12083 Simulate "lamp1"
$ fcfClient zpb.rr://127.0.0.1:12083 Status "lamp1"
lamp1.simulated = true
lamp1.lcs.state = Operational
lamp1.lcs.substate = Off
lamp1.lcs.intensity = 0.000000

OK
$ fcfClient zpb.rr://127.0.0.1:12083 StopSim "lamp1"
$ fcfClient zpb.rr://127.0.0.1:12083 Status "lamp1"
lamp1.lcs.state = Operational
lamp1.lcs.substate = Off
lamp1.lcs.intensity = 0.000000

OK

DevNames Command

The DevNames command provides the list of devices managed by the Device Manager.

DevsInfo Command

The DevsInfo command provides the list of devices managed by the Device Manager with their corresponding types.

DevConfig

The DevConfig command provides the loaded configuration of a particular device.

Troubleshooting

Logging

The Device Manager has implemented logging based on the log4cplus package. The log4cplus package defines four standard logging levels that could give additional information to the developer for troubleshooting.

Name

Verbosity

Description

ERROR

very low

Provide logging only in case of errors (default).

INFO

low

Provide information for the most important actions.

DEBUG

medium

Provide additional information for the developer.

TRACE

very high

Includes all the function tracing.

To activate a new logging, the command SetLogLevel shall be used. See the example below.

$ fcfClient zpb.rr://127.0.0.1:12083 SetLogLevel "TRACE"

Note

This logging level affects only the general Devmgr logger.

Loggers

The Devmgr provides a default configuration (log_properties.cfg) for the logging. This configuration defines one general logger (app) and a logger per device type, e.g. (shutter). The device loggers will help when troubleshooting specific devices.

Logger

Description

app

General logger for common server classes.

shutter

Specific logger for Shutter classes.

lamp

Specific logger for lamp classes.

motor

Specific logger for motor classes.

sensor

Specific logger for sensor classes.

piezo

Specific logger for piezo classes.

actuator

Specific logger for actuator classes.

iodev

Specific logger for iodev classes.

drot

Specific logger for drot classes.

adc

Specific logger for adc classes.

To activate a new logging level for a specific logger, one should use the FCF CLI, see the example below.

$ fcfcli
$ fcsSh> setloglevel TRACE,lamp

The server will start logging the tracing information for the lamp classes and you should see something like the following:

2021-07-02T14:30:17.624 TRACE ENTER: virtual void fcf::devmgr::lamp::Lamp::Setup(const std::any&)
2021-07-02T14:30:17.624 TRACE EXIT:  virtual void fcf::devmgr::lamp::Lamp::Setup(const std::any&)
2021-07-02T14:30:17.638 TRACE ENTER: virtual bool fcf::devmgr::lamp::Lamp::IsSetupActive(const std::any&) const
2021-07-02T14:30:17.638 TRACE EXIT:  virtual bool fcf::devmgr::lamp::Lamp::IsSetupActive(const std::any&) const
...

Note

If a the second parameter is not provided, the logging level will affect the general logger.

Note

If you are missing some logging information for some devices, it might be that the logging is happening in the specific device classes so you need to enable the device logger to see all the logging. When you use the application logger, it affects only to the common classes.

Log File

The default log configuration provides two appenders. One for the console and another one for a file. The file is stored by default in the home directory of the user running the Devmgr. The name of the file is fcfDevmgr.log.

OPC-UA Client

Sometimes it is better to check the status of the PLC using an OPC-UA client. One of the best tools available is the UaExpert from Unified Automation. This tool enables the control and monitoring of all device variables independently of the Device Manager. The user can trigger the execution of RPCs and monitor the device state changes. The UaExpert is an essential tool for troubleshooting.

alternate text

UaExpert OPC-UA client.