xentara-cpp-control v1.0.1
The Xentara C++ Control Framework
Loading...
Searching...
No Matches
Write Safe Values

Overview

In this tutorial, we will explore how to safely disable a control by implementing safe values for a servo motor. The process includes:

  • Setting initialization flags in the enterPreOp phase.
  • Performing readiness checks in the enterOperational phase.
  • Safely disabling the servo motor in the enterPostOp phase.
  • Verifying the safe state of the system in the final phase.

The safe value process ensures that the servo motor transitions to a safe state when exiting the operational phase.

The objectives of this tutorial are to:

  • Implement a control class for a servo motor with safe value handling.
  • Set safe values in the enterPostOp phase.
  • Perform final readiness checks in the final phase to confirm that the system is in a safe state.

Step 1: Define the ServoMotorControl Class

The ServoMotorControl class handles the initialization, operation, and safe value management of a servo motor. It includes methods for setting safe values and verifying the safe state of the servo motor.

#pragma once
#include <xentara/cpp-control.h>
class ServoMotorControl final : public xentara::Control
{
public:
/// Initializes the control and sets up data points.
void initialize(xentara::InitContext &context) override;
/// Handles pre-operational initialization, setting up and verifying servo motor flags.
void enterPreOp(xentara::RunContext &context) override;
/// Checks readiness before entering the operational stage.
void enterOperational(xentara::RunContext &context) override;
/// Safely disables the servo motor by setting safe values.
void enterPostOp(xentara::RunContext &context) override;
/// Verifies that the servo motor is in a safe state.
void final(xentara::RunContext &context) override;
/// Executes the main control logic.
void step(xentara::RunContext &context) override;
private:
/// Xentara-managed output data points for servo motor flags
xentara::BooleanOutput resetFault;
xentara::BooleanOutput releaseBrake;
xentara::BooleanOutput enableVoltage;
xentara::BooleanOutput enableCurrent;
xentara::BooleanOutput enableOperationState;
/// Xentara-managed output data points for servo motor flags status
xentara::BooleanOutput faultStatus;
xentara::BooleanOutput releaseBrakeStatus;
xentara::BooleanOutput enableVoltageStatus;
xentara::BooleanOutput enableCurrentStatus;
xentara::BooleanOutput enableOperationStateStatus;
};
An interface class which provides declaration of all the callbacks for this control.
Definition Control.hpp:19
virtual auto enterPreOp(RunContext &context) -> void
Called by the framework at the beginning of the pre-operational stage.
virtual auto initialize(InitContext &context) -> void=0
Callback that is called by the framework to initialize the control object.
virtual auto step(RunContext &context) -> void=0
Main callback responsible for executing the core control logic.
virtual auto enterOperational(RunContext &context) -> void
Called by the framework once at the conclusion of the pre-operational stage, just before entering int...
virtual auto enterPostOp(RunContext &context) -> void
Called by the framework at the beginning of the post-operational stage.
An initialization context with configuration information and access to Xentara Elements.
Definition InitContext.hpp:35
An run context with execution information and is required for the read and write for Input and Output...
Definition RunContext.hpp:46

Step 2: JSON Configuration for Initialization and Safe Values

The JSON configuration file defines the data points for initializing and safely disabling the servo motor.

{
"children": [
{
"@Skill.CPP.Control": {
"name": "Servo Motor Control",
"UUID": "8f9a0b1c-2d3e-4f5a-6b7c-8d9e0f1a2b3c",
"controlPath": "libservo-motor-control.so",
"parameters": {
"releaseBrake": "Servo Motor.Release Brake",
"releaseBrakeStatus": "Servo Motor.Release Brake Status",
"enableVoltage": "Servo Motor.Enable Voltage",
"enableVoltageStatus": "Servo Motor.Enable Voltage Status",
"enableCurrent": "Servo Motor.Enable Current",
"enableCurrentStatus": "Servo Motor.Enable Current Status",
"enableOperationState": "Servo Motor.Enable Operation State",
"enableOperationStateStatus": "Servo Motor.Enable Operation State Status",
"resetFault": "Servo Motor.Reset Fault",
"faultStatus": "Servo Motor.Fault Status"
}
}
},
{
"@Group": {
"name": "Servo Motor",
"UUID": "8688c4d5-1323-4b01-a3c2-e15fb534f3da",
"children": [
{
"@Skill.SignalFlow.Register": {
"name": "Release Brake",
"UUID": "5b654ce4-dcb6-4000-8463-051a7204a1b4",
"defaultValue": [ "bool", false ]
}
},
{
"@Skill.SignalFlow.Register": {
"name": "Release Brake Status",
"UUID": "a4aaebac-af3e-49b7-bccb-6c63690d15b4",
"defaultValue": [ "bool", false ]
}
},
{
"@Skill.SignalFlow.Register": {
"name": "Enable Voltage",
"UUID": "adf70317-8f4a-402f-b417-9ea65af43f9e",
"defaultValue": [ "bool", false ]
}
},
{
"@Skill.SignalFlow.Register": {
"name": "Enable Voltage Status",
"UUID": "904251d4-c355-4839-a8df-beda5dcbdaf1",
"defaultValue": [ "bool", false ]
}
},
{
"@Skill.SignalFlow.Register": {
"name": "Enable Current",
"UUID": "26982854-97a6-43e7-bc48-b8043ed3117d",
"defaultValue": [ "bool", false ]
}
},
{
"@Skill.SignalFlow.Register": {
"name": "Enable Current Status",
"UUID": "f46d6405-4624-48ee-84bb-2562cc377db8",
"defaultValue": [ "bool", false ]
}
},
{
"@Skill.SignalFlow.Register": {
"name": "Enable Operation State",
"UUID": "659599fb-a93e-41ba-aaba-f3be266796fc",
"defaultValue": [ "bool", false ]
}
},
{
"@Skill.SignalFlow.Register": {
"name": "Enable Operation State Status",
"UUID": "9820a1d7-234b-436c-96d5-7e33cb0cfbd2",
"defaultValue": [ "bool", false ]
}
},
{
"@Skill.SignalFlow.Register": {
"name": "Reset Fault",
"UUID": "f2dce75b-6ae0-4ea1-a301-33c092324a04",
"defaultValue": [ "bool", false ]
}
},
{
"@Skill.SignalFlow.Register": {
"name": "Fault Status",
"UUID": "3cef8cdd-e544-4a49-9f64-b4044046a53f",
"defaultValue": [ "bool", false ]
}
}
]
}
},
{
"@Track": {
"name": "Control Track",
"UUID": "fb0a26f8-7d84-4af9-9345-4145263d09c7",
"children": [
{
"@Timer": {
"name": "Timer",
"UUID": "e6580c24-dbf9-43a0-aa81-c5ed8da6f734",
"period": "50ms"
}
},
{
"@Pipeline": {
"name": "Pipeline",
"UUID": "040f156e-2744-4008-8195-cd7f17078668",
"triggers": [
"Control Track.Timer.expired"
],
"checkpoints": [
{},
{}
],
"segments": [
{
"start": 0,
"end": 1,
"tasks": [
{
"function": "Servo Motor Control.step"
}
]
}
]
}
}
]
}
}
]
}

Note
The @Skill.SignalFlow.Register skill is used for simplicity in this example. For real-world systems, other skills like EtherCAT, Modbus, or OPC UA should be used depending on the communication protocol supported by the servo motor.

Step 3: Implement the Safe Values Logic

The initialize method configures the data points. The enterPreOp phase sets the initialization flags, and the enterOperational phase performs readiness checks. The enterPostOp phase sets the safe values, and the final phase verifies the safe state.

#include "ServoMotorControl.hpp"
/// Registers the ServoMotorControl with Xentara.
void ServoMotorControl::initialize(xentara::InitContext &context)
{
// Configure output data points for servo motor flags
resetFault = context.config().getDataPoint("resetFault");
releaseBrake = context.config().getDataPoint("releaseBrake");
enableVoltage = context.config().getDataPoint("enableVoltage");
enableCurrent = context.config().getDataPoint("enableCurrent");
enableOperationState = context.config().getDataPoint("enableOperationState");
// Configure status data points for readiness and safe state checks
releaseBrakeStatus = context.config().getDataPoint("releaseBrakeStatus");
enableVoltageStatus = context.config().getDataPoint("enableVoltageStatus");
enableCurrentStatus = context.config().getDataPoint("enableCurrentStatus");
enableOperationStateStatus = context.config().getDataPoint("enableOperationStateStatus");
faultStatus = context.config().getDataPoint("faultStatus");
}
void ServoMotorControl::enterPreOp(xentara::RunContext &context)
{
// Set flags to initialize the servo motor
resetFault.write(context, true);
releaseBrake.write(context, true);
enableVoltage.write(context, true);
enableCurrent.write(context, true);
enableOperationState.write(context, true);
}
void ServoMotorControl::enterOperational(xentara::RunContext &context)
{
// Perform readiness checks for the operational phase
if (!releaseBrakeStatus.read(context))
{
// handle error for Readiness check failed - 'Release Brake Status' flag is not set.
}
if (!enableVoltageStatus.read(context))
{
// handle error for Readiness check failed - 'Enable Voltage Status' flag is not set.
}
if (!enableCurrentStatus.read(context))
{
// handle error for Readiness check failed - 'Enable Current Status' flag is not set.
}
if (!enableOperationStateStatus.read(context))
{
// handle error for Readiness check failed - 'Enable Operation State Status' flag is not set.
}
if (faultStatus.read(context))
{
// handle error for Readiness check failed - 'Fault Status' flag is unexpectedly set.
}
}
void ServoMotorControl::enterPostOp(xentara::RunContext &context)
{
// Safely disable the servo motor by reversing the initialization flags
enableOperationState.write(context, false);
releaseBrake.write(context, false);
enableVoltage.write(context, false);
enableCurrent.write(context, false);
}
void ServoMotorControl::final(xentara::RunContext &context)
{
// Verify that the servo motor is in a safe state
if (releaseBrakeStatus.read(context))
{
// handle error for Safe state check failed - 'Release Brake Status' flag is unexpectedly set.
}
if (enableVoltageStatus.read(context))
{
// handle error for Safe state check failed - 'Enable Voltage Status' flag is unexpectedly set.
}
if (enableCurrentStatus.read(context))
{
// handle error for Safe state check failed - 'Enable Current Status' flag is unexpectedly set.
}
if (enableOperationStateStatus.read(context))
{
// handle error for Safe state check failed - 'Enable Operation State Status' flag is unexpectedly set.
}
if (faultStatus.read(context))
{
// handle error for Safe state check failed - 'Fault Status' flag is unexpectedly set.
}
}
void ServoMotorControl::step(xentara::RunContext &context)
{
// Placeholder for servo motor control logic (to be implemented later)
}
A class used to export your control class with Xentara.
Definition ControlExporter.hpp:38
auto config() const -> const Config &
Gets the configuration.

Conclusion

In this tutorial, we extended the complex initialization process to include safe value handling. This involved:

  • enterPreOp: Setting initialization flags.
  • enterOperational: Confirming readiness for operation.
  • enterPostOp: Setting safe values to disable the servo motor.
  • final: Verifying the safe state of the servo motor.

This implementation ensures that the servo motor transitions to a safe state when exiting the operational phase, guaranteeing safe and reliable operation in industrial environments.