_beckhoffdev/implementation_specification:
Implementation Specification for BeckhoffDevice¶
Authors: | A. Beckmann and A. Parenti, for the Control and Data Analysis Software Group |
---|---|
Version: | 3.0, July 2016 |
Revisions¶
Version | Date | Description |
---|---|---|
1.0 | 18 Jan 2016 | Initial version |
1.1 | 15 Feb 2016 | Added PLC framework version check |
1.2 | 29 Mar 2016 | Renamed Safe state |
1.2a | 18 Apr 2016 | Update of FSM |
2.0 | 9 May 2016 | Change to sychronous services |
3.0 | 7 Oct 2016 | Migrated to Karabo consolidated version |
3.3 | 6 Apr 2018 | Schedule Push first refactor |
4.0 | 22 Nov 2018 | Asynchronous refactoring of call, write and read |
Preface¶
This document provides details on the implementation of the BeckhoffDevice class, which is the base class used for all Karabo devices to control PLC hardware.
This specification covers software release 3.0.
Introduction¶
The photon beamlines and experiments use hardware devices, such as motors, valves, pumps, which are connected via field bus to a Programmable Logic Controller (PLC). The PLC program is modular in the sense that a specific PLC module or so called Program Organization Unit (POU) controls a specific piece of hardware. Within the XFEL PLC framework library, these POUs are called softdevices.
Each PLC has an associated BeckhoffCom device, which acts as a transparent gateway for data exchange between the Karabo framework and the PLC [1].
Each softdevice has an associated Beckhoff device, which is used to control the hardware connected to that softdevice. All Beckhoff devices are derived from the BeckhoffDevice base class, which
- abstracts the low-level communication with BeckhoffCom into rather simple methods,
- provides a default set of expected parameters valid for all Beckhoff devices,
- and defines the device states using a finite state machine (FSM).
The Beckhoff device adds additional expected parameters according to the type of hardware it supports.
Information Model¶
Each PLC softdevice provides properties or commands. A property is a variable that stores a value of a specific type. The supported value types are listed in Table 5. A command is a method that can be called to initiate an action on the PLC.
Type | Bits | KARABO Type | Comment |
---|---|---|---|
tBOOL | 8 | BOOL_ELEMENT | |
tBYTE | 8 | UINT8_ELEMENT | |
tSINT | 8 | INT8_ELEMENT | |
tWORD | 16 | UINT16_ELEMENT | |
tINT | 16 | INT16_ELEMENT | |
tDWORD | 32 | UINT32_ELEMENT | |
tDINT | 32 | INT32_ELEMENT | |
tULINT | 64 | UINT64_ELEMENT | |
tLINT | 64 | INT64_ELEMENT | |
tREAL | 32 | FLOAT_ELEMENT | |
tLREAL | 64 | DOUBLE_ELEMENT | |
tSTRING | STRING_ELEMENT | maximum supported length is 28 characters | |
tVOID | SLOT_ELEMENT | for commands only | |
tMULTI | n*32 | VECTOR_UINT32_ELEMENT | a struct of several above mentioned types, except tSTRING and tVOID, handled internally as an array of 32 bit integer |
Information on the PLC is addressed using strings, specifying the name of the softdevice instance and the name of the property or command. By convention, the softdevice instance name is the same as the Beckhoff device instance name. property and command names are specified as an alias to an associated expected parameter.
If for example, there is a softdevice instance named ‘AI1_1’ connected
to an analog input and a property of type tREAL
called ‘AValue’ to
contain the actual analog value at the input, then the Beckhoff device
will have an expected parameter for the analog value in the form:
FLOAT_ELEMENT(expected).key("value")
.alias<string>("AValue")
.tags("plc")
.displayedName("Value")
.description("Analog input of ADC.")
.readOnly()
.commit();
By default, the instance name of the Beckhoff device is used to
address the softdevice, so that in this case the Beckhoff device is
instantiated with the name ‘AI1_1’. Since the property is of type
tREAL
, the expected parameter must be a FLOAT_ELEMENT
.
Finite State Machine¶
The FSM of BeckhoffDevice is depicted in Fig. 5. The initial state is the UNKNOWN state. The FSM changes from the UNKNOWN into the KNOWN state with the connect event, which is triggered by a registration from BeckhoffCom. If the connection to BeckhoffCom is lost, the disconnect event is triggered, and the FSM changes back into the UNKNOWN state.
The KNOWN state is a compound state, with its states being defined based on information from the associated PLC soft device. Depending on the state value of the PLC softdevice, the FSM changes from the NORMAL into either ERROR or DISABLED state, though the ERROR state has precedence over DISABLED state.
In the NORMAL state, the state word as it is visible e.g. in the GUI, is overwritten by decoding the hardware state of the soft device to give this state a more descriptive name. Since this is device dependent, a derived device needs to overwrite the decoding method (see Section decodeHardwareState()).
BeckhoffDevice¶
The BeckhoffDevice is the base class for all derived devices. It provides methods to exchange information with the PLC, wait methods to wait for state updates from the PLC, and virtual methods, that derived classes need to override to change the state word and to handle PLC value updates.
It also implements the FSM methods and starts threads to poll properties and to watch the connection to BeckhoffCom.
FSM Methods¶
Behavior is implemented in FSM entry and exit methods, which are explained in more detail in this section. If methods are time consuming, i.e. they communicate with the hardware, they are implemented as background worker in order to allow the FSM to finish the transition.
KNOWN State Entry¶
On entry of the KNOWN state, the device schema and hardware values are requested. It also starts a polling and watchdog thread, and initializes the wait for a state change.
Requesting Schema¶
The device schema is requested using the ‘plcBrowseRequest’ slot of the BeckhoffCom device. The argument to the request is the device name. The reply contains a schema with expected parameters for all properties and commands that are currently defined on the PLC softdevice. If they are already existing, then they are removed from the schema. All remaining parameters are then injected dynamically by appending the schema. Access type (read-only) and modes (expert, admin) are not set, since this information is currently not included in the schema.
For parameters, which are already existing, an additional type check is performed. In case of a mismatch, a warning is generated.
For commands, which do not yet exist, the generic slot method plcCommand() is registered using the command name as an argument to the slot call.
Requesting Hardware Values¶
The hardware values are requested by sending the ‘CSendAll’ command to the soft device. This triggers an update of all PLC properties, which includes also the hardware state. The hardware state has bits to indicate, whether the hardware is in error or safe state [2]. Depending on the values, the FSM changes from the NORMAL into either ERROR or DISABLED state, though the ERROR state has precedence over DISABLED state.
While receiving the property updates, the PLC Framework version is checked against a built-in constant. The version is a compound number in the form major.minor.patch. If the major number does not match, the state machine changes into the UNKNOWN state by triggering the disconnect event and an error message is generated. If the minor number does not match, a warning message is generated, but the state does not change. The patch number is ignored.
Starting Threads¶
The polling and watchdog threads are started.
KNOWN State Exit¶
On exit of the KNOWN state, all threads and conditional waits are terminated.
Threads¶
While in the KNOWN state, BeckhoffDevice starts threads to watch the connection to BeckhoffCom, and to poll PLC properties.
Watchdog Thread¶
The watchdog thread decrements a counter each second. The counter is reset to 30 at thread start, and also whenever a message has been received from BeckhoffCom. Thus, if after 30s nothing has been, an error is logged and the disconnect event is triggered.
Polling Thread¶
The polling thread issues a read command towards the PLC, if there are any properties specified. The polling period is configurable.
Slots¶
The BeckhoffDevice provides slots that are called by BeckhoffCom.
registerComDevice¶
The registerComDevice slot stores the name of the BeckhoffCom device for later reference, and triggers the connect event, if not already connected.
Care has to be taken, that this slot is not processed while the FSM is not yet fully started.
deregisterComDevice¶
The deregisterComDevice slot clears the stored BeckhoffCom device name and triggers the disconnect event. If BeckhoffDevice is already disconnected, this slot call is ignored.
Care has to be taken, that this slot is not processed while the FSM is not yet fully started.
Karabo Methods¶
The BeckhoffDevice class overrides the following methods from the Karabo base device.
preReconfigure()¶
In case expected parameters have been changed, this method filters all PLC related parameters from the incoming reconfiguration using the ‘plc’ tag, and creates one write hash to send to the PLC.
If any of the scheduled push triggers have been changed, then it decides based on the value of the key ‘enable’, whether to create or to delete a scheduled push.
Warning
In case of deleting a scheduled push (i.e. key ‘enable’ has value false), then the property name may not be changed at the same time.
Virtual Methods¶
The methods described in this chapter may need to be overridden in derived BeckhoffDevices.
decodeHardwareState()¶
This method is used to convert a state word (i.e. a 32 bit integer) into a corresponding string. This is definitely device dependent, so that there is no default implementation in the base device. Derived classes are required to override this method.
onPlcUpdate()¶
This method is a callback of the base device that is called from BeckhoffDevice base class, whenever a value update has been received from the PLC. Derived classes may override this method to add specific processing for value updates. The argument to this method is a hash with the value updates.
onIntendedHardwareReconfiguration()¶
This method is a callback of the base device that is called from BeckhoffDevice base class, whenever one of the expected parameters has been changed by a user. Derived classes may override this method to add specific processing of the changes before they are sent to the PLC.
PLC Methods¶
The methods described herein use the synchronous request-reply pattern between BeckhoffDevice and BeckhoffCom. The caller (i.e. the derived class) is blocked until a reply has been received from BeckhoffCom.
The request payload is defined as non-hierarchical [†] Karabo hashes of basic types, as listed in Table 5. The key specifies the name of the requested property or command.
Replies return a copy of the hash, as received with the request. The keys are annotated with a ‘status’ attribute, containing the status code as defined in [1]. If at least one of the status codes is non-zero, an error event is triggered.
plcRead()¶
This method is used to read values from the PLC. The signature is:
void plcRead(const vector<string>& properties)
The argument is a vector of names of properties that should be read. The vector is converted into a hash, where the keys are the names of the specified properties. The hash is sent to slot “plcReadRequest” of the registered BeckhoffCom device.
The method asynchronously waits for a reply from BeckhoffCom. The reply contains a hash with the read values for all requested properties and the annotated status codes.
Values with status code 0 are used to update the associated expected parameters. Values with non-zero status code are ignored, and a warning is logged.
If the reply contains a value update for the hardware state, then in addition the next FSM state is evaluated and the Karabo state word is updated.
plcWrite()¶
This method is used to write values to the PLC. The signature is:
void plcWrite(const Hash& values)
The argument is a hash with key value pairs for each property to write. The hash is sent to slot “plcWriteRequest” of the registered BeckhoffCom device.
The method asynchronously waits for a reply from BeckhoffCom. The reply contains a hash with a copy of the write values and the annotated status codes.
Values with status code 0 are used to update the associated expected parameters. Values with non-zero status code are ignored, and a warning is logged.
plcCall()¶
This method is used to execute a command on the PLC. The signature is:
void plcCall(const string& command)
The argument is the command name (alias). The name is converted into a hash, where the key is the name of the specified command. The hash is sent to slot “plcCallRequest” of the registered BeckhoffCom device.
The method “plcCallRequest” asynchronously reacts to a reply from BeckhoffCom. The reply contains a hash with a copy of the call value and the annotated status code.
This method will not issue a reply to the slot requestor.
More on command implementation will be detailed below.
plcPush()¶
This method is used to create a scheduled push on the PLC. The signature is:
void plcPush(const string& propertyName, double interval,
unsigned int triggerId)
The argument is the name of the property to be pushed with the specified interval. The property name and interval is sent to slot “plcSetPushRequest” of the registered BeckhoffCom device.
The method asynchronously waits for a reply from BeckhoffCom. The reply contains the status code of the operation, the triggerId and the propertyName set.
plcUnpush()¶
This method is used to delete a scheduled push from the PLC. The signature is:
void plcUnpush(const string& propertyName, unsigned int triggerId)
The argument is the name of the property to be unpushed. The property name is sent to slot “plcSetPushRequest” of the registered BeckhoffCom device.
The method asynchronously waits for a reply from BeckhoffCom. The reply contains the status code of the operation, the triggerId and the propertyName set.
Derived Devices¶
Derived Beckhoff devices extend the base class by adding device specific expected parameters, implementing slot methods and overriding the base class methods as described in Section Karabo Methods.
Expected Parameters¶
Expected parameters are added as usual, e.g. like:
FLOAT_ELEMENT(expected).key("targetPosition")
.alias<string>(SD_STEPPERAXIS_ATARGETPOS)
.tags("plc")
.description("Target position in position mode.")
.displayedName("Target position")
.unit(Unit::METER)
.metricPrefix(MetricPrefix::MILLI)
.assignmentOptional().noDefaultValue()
.reconfigurable()
.commit();
for variables and:
SLOT_ELEMENT(expected).key("move")
.alias<string>(SD_STEPPERAXIS_CMOVE)
.displayedName("Move")
.description("Move to target position.")
.commit();
for commands.
It is important to add the ‘plc’ tag to writable parameters. Otherwise, changes are not propagated to the PLC. On read only parameters, the tag can be omitted.
The alias is always specified using a text macro, which is defined in a separate header file, generated using external tools [‡].
Commands¶
in case of command implementation, the derived classes need to add corresponding slot methods. They need to be registered in the constructor of the derived class as usual using the KARABO_SLOT macro. The two most used solutions are plcCall and plcCallToState
plcCommand¶
The slot methods simply call plcCommand() and the base class will reply _asynchronously_ to the slot call once the Acknowledge/Echo message is received from the PLC. The command name passed as the argument to plcCommand() is taken from the alias of the expected parameter. For example, the resetController command of the TurboPump does not need to receive a state update. It is implemented as follows:
void BeckhoffPfeifferTCDriveUnit::resetController() {
plcCommand(getAliasFromKey<string>("resetController"));
}
Below the sequence diagram of the plcCommand in case of success is shown:
Below the sequence diagram of the plcCommand in case of timeout is shown:
It is important to pass to the plcCommand
function the alias obtained
calling the getAliasFromKey
helper function.
If a slot is removed from the self description, and automated deprecation
process will overwrite the alias of the key in the static schema.
plcCallToState¶
If the slot call is supposed to create a state change of the device, then a call plcCallToState with the target state as second argument should be used. The asynchronous reply of the slot will now be sent when the PLC both acknowledged/echoed the call and the state was actually changed. See the sequence diagram below.
For example the on command of the digital output is implemented as:
void BeckhoffDigitalOutput::on() {
plcCallToState(getAliasFromKey<string>("on"), State::ON);
}
In case the target state depends from internal variables, the implementation will be:
void BeckhoffSimpleMotor::move() {
if (isOpenLoop) {
plcCallToState(getAliasFromKey<string>("move"), State::MOVING);
} else {
plcCallToState(getAliasFromKey<string>("move"), State::ACTIVE);
}
}
Below is the sequence diagram of the plcCallToState in case of Success
Below is the sequence diagram of the plcCallToState in case of timeout
The plcCallToState method will reply either when the target state (or an error state) is reached, when the BeckhoffCom device detects a PLC disconnection, or when the timeout is expired. If multiple hardware state updates are sent, they will not cause a reply.
BeckhoffGeneric¶
A special derived device is the BeckhoffGeneric device. It does not define any expected parameters, so that when requesting the device schema during entry of the KNOWN state, all properties defined on the PLC are injected at run time. Slots are registered automatically with the generic plcCommand() method defined by the BeckhoffDevice base class, which simply sends the related PLC command to the soft device. Additional information, such as access rights or allowed states, are not available, so that all parameters are always enabled and can be used by operators.
The decoded state is always STATIC.
Abbreviations and acronyms¶
Beckhoff device | A device plugin that is run on a Karabo device server |
Hardware device | A physical piece of hardware, such as a motor, valve, or pump |
PLC | Programmable Logic Control |
POU | Program Organization Unit |
Softdevice | A program organization unit on the PLC |
References¶
[1] | (1, 2)
|
[2] |
|
[*] | This can happen, if BeckhoffCom has deregistered itself, but there are pending updates that are still sent afterwards |
[†] | The term non-hierarchical means that hashes of hashes are not allowed in service requests. |
[‡] | PlcCodeGenerator.py or PlcCodeGeneratorKarabo.py can be used to generate a C++ header file containing the macro definitions. Both programs are stored in the bin/ folder of this repository. |