Skip to main content

Control and Regulation

Control and regulation with the math module

Given the extensive function library of the math module, it makes sense to also implement control and regulation functions in this scripting language.

This is actually possible with a few restrictions and taking the following points into account:

Signal processing, time behavior

The process of control and regulation requires hard real-time calculations, i.e., a fixed, as short as possible signal propagation time from the acquisition of the measured variable to the output of the control variable to the process. In control systems, this is typically around 1 to 10 ms. This hard constraint cannot be met with the smartCORE architecture!

Measurement data is acquired by specific plug-ins and written to the channels of the smartCORE. For this purpose, the formula set of the math module is calculated asynchronously in approximately constant, large time intervals on the available data, provided that all required channels also provide data at a given point in time. The results are written to smartCORE channels at the rate of this calculation. For this purpose, data from the smartCORE channels is output to the process asynchronously, e.g., via CAN.

There are therefore enough places where the real-time requirement is violated by the asynchrony in smartCORE, the channels as buffers or ring memory, and the batch processing of the math module.

If the processes to be influenced are slow1 enough, it is at least possible to adjust the calculation process and the output so that the discrete sampling time discreteSampleTimeMs matches the execution time of the batch process evaluationTimeMs and the output to the process. Possible values here are in the range of 50 to 1000 ms. Then the asynchrony and buffering of the data streams become tolerable.

Controller

PID controller "pidCtrl"

Under Construction This function is currently being implemented and is not yet intended for productive operation.

The function pidCtrl() implements a controller with configurable proportional (P), integral (I), and derivative (D) behavior.

The input parameters of the function are at least the reference variable (setpoint) sp and the process variable to be controlled (actual value, current value) cur. The output is the control variable.

Optionally, the operating mode can be selected via the input mode:

modeDescription
0, falseNormal control mode (Enable)
1, trueHold control variable (Hold)
2Control variable follows the manual control input u_man (Bypass)

Optionally, the control parameters [K, Ti, Td] can also be assigned dynamically using the input vector parVec. The vector can contain 1 to 3 parameter values. These overwrite the specifications in the configuration object.

important

The calculation is always performed with the discrete sampling time discreteSampleTimeMs. To ensure that the control variable can be transferred to the process in a timely manner, the execution time of the batch process evaluationTimeMs must be set to the same value.

u1 = pidCtrl(sp, cur, {...});
u2 = pidCtrl(sp, cur, mode, {...});
u3 = pidCtrl(sp, cur, mode, u_man, {...});
u4 = pidCtrl(sp, cur, mode, u_man, parVec, {...});
// Mandatory configuration for all variants
ux = pidCtrl(..., { K: <dbl>
, Ti: off|<dbl>
, Td: off|<dbl>
, reverse: <bool>
, commonK: <bool>
                 , dWidth: <uint>
, lower: off|<dbl>
, upper: off|<dbl>
});

The properties are described using examples from the time domain, although the function calculates internally in discrete sampling steps.

PropertyValueDescription
K<dbl>Amplification of the controller
Tioff|<dbl>Activation and integration time for I component
I(e)=1Tie(t)dtI(e) = \frac{1}{T_i} \cdot \int e(t) dt
Tdoff|<dbl>Activation and differentiation time for D component
D(e)=Tdddte(t)D(e)=T_d \cdot \frac{d}{dt} e(t)
reverse<bool>Reversal of control direction
false: e=spcure=sp-cur, (def.)
true: e=curspe=cur - sp
commonK<bool>Interpretation of gain:
false: u=K(e)+I(e)+D(e)u = K(e) + I(e) + D(e)
true: u=K(1+I(e)+D(e))u=K\cdot(1+I(e)+D(e)), (def.)
dWidth<uint>Number of sampling intervals for weighted averaging of the differential value (def.: 3)
loweroff|<dbl>Lower limit of the control variable,
the integral component is tracked to enable shock-free resumption.
upperoff|<dbl>Upper limit of the control variable,

Controller structure: The commonK property switches the interpretation of the gain factor K. In control engineering, K usually acts equally on all three paths P, I, and D (commonK: true, def.!) and also converts the physical dimensions between control deviation (e.g., in hPa) and control variable (e.g., in %). Thus, K does not influence the dynamic behavior of the controller, which is determined by its poles and zeros, but only the agility and stability of the closed control loop. Many tuning rules for PID controllers are based on this structure.

It is rarely interpreted that K actually only influences the proportional path of the controller (commonK: false). This shifts the task of unit conversion to the time parameters Ti and Td, and changing K directly changes the poles and zeros of the controller and thus its dynamic behavior. This makes it considerably more difficult to calibrate the controller.

Using the D component: Since the controller function is tied to the very slow discrete clocking of the math module, the evaluation of the gradient of the control deviation in the D component should also be used with caution. Due to the "on-change" philosophy used to provide measurement data in a smartCORE channel, there may be long periods of time during which the signal does not change. In order to be able to detect a slow drift in temperature, for example, the values are calculated over several sampling steps using a weighting function to obtain the value of the derivative. The width of this window is specified by the dWidth property. However, this also creates additional dead time (dWidth/2 * discreteSampleTimeMs) in the controller's D path, which can have a negative impact on the control process. dWidth should therefore be as small as possible but as large as necessary. This depends on the process to be controlled.

Time reference: If the reference variable sp comes from a (shared) attribute and is only updated rarely, this channel should definitely be detached from the time reference using the macro #timeless. The same may also apply to the process variable cur.

Finite State Machine

Finite state machine "states"

Under Construction This function is currently being implemented and is not yet intended for productive operation.

Implementation of a finite state machine (FSM) This function states() can be used to model behavior consisting of states, state transitions, and actions.

A general description can be found in the article Finite-state machine - Wikipedia or here (DE).

In this implementation, evaluation is clocked with the global discrete sampling time discreteSampleTimeMs. In each clock cycle, exactly one transition can cause a state change.

This finite state machine has a finite number of states, which are identified by a unique identifier sx. Each state is stable until a state transition triggers a change. This means that a state can contain information about the past, since the system has reached it on its previous path, i.e., it reflects to a certain extent the changes in the input since the system started up until the current point in time.

s1, … sN: define the identifiers of the states sx of the state machine as const <uint/int/str> (!) The first state is the start state, unless another is specified via the property init: sx. The output of states() is the respective value of sx of the active state, unless the output of the state index is forced as [1, 2, … N] with the property outIdx: true. All sx must be unique, as they are used in the transit() functions to specify the next state.

A state transition is a transition from the current state to a new (different) state. This transition occurs when the specified logical conditions / "inputs" are present, which must be fulfilled to enable the transition. In this implementation, a Boolean condition, a definable time window, a repeat counter, and a priority value for release are available for this purpose.

trXY: define transit() objects that are evaluated for the aforementioned state. The first transit() function for which the configured conditions apply triggers the state transition.

State transitions defined before the first state play a special role. They are evaluated in any state before the transitions defined in the state itself are evaluated. They thus take on the role of "from any" transitions, e.g., to catch error conditions, implement timeouts, or force resets.

The parameters of the states() function thus describe the automaton in which a const <uint/int/str> parameter either defines a new state or defines state transitions from this state using transit().

act = states(tr00, tr01, …
, s1, tr10, tr11, …
, s2, tr20, tr21, …);
// Optional configuration
actX = states(..., { init: <sx>
, outIdx: <bool>
, ageVar: <str>
, dbgVar: <str>
});
PropertyValueDescription
init<var>Start state for the automaton, unless defined as the first
outIdx<bool>true: Output of the index of the active state <uint> [1,2,N][1, 2, … N]
false: Output of the identifier defined for the state <uint/int/str>
ageVar<str>The "age" of the active state in seconds can be published in the variable designated here.
dbgVar<str>The node number of the triggering transition is written to the variable specified here. "0" if no transition is pending.
storage<str>(in preparation)

An action is the "output" of the FSM that occurs in a specific situation. There are four types of actions:

  • Input action: The action is executed/output when entering a state (regardless of which state transition was used to reach the state, if there are several).

  • Exit action: The action is generated when leaving a state (regardless of which state transition is used to leave the state).

  • Input action: The action is generated depending on the current state and the input. This means that several actions can be assigned to a state, which are executed depending on the state transition via which it is reached/left.

  • Transition action: The action is executed during a state transition.

If act = state(…) is a variable that maps the active state, the state-dependent actions can be implemented as follows:

  • Input action: posedge(act == K)

  • Output action: negedge(act == K)

  • Input action: (act == K)

With the actVar: "TR" that can be defined in the transition, the following can also be implemented

  • Transition actions: TR

can also be implemented.

Transitions "transit"

Under Construction This function is currently being implemented and is not yet intended for productive operation.

The function transit() generates the transition objects that are passed as parameters to the state machine states(). The result of this function can only be processed in the function states().

  • sx: is the next state, provided that the transition condition is met. If sx is missing, the transition returns to the currently active initial state without restarting it. sx can also come from a calculation or a variable. If sx does not refer to a known state, the replacement value sFail is used.

  • cond: Condition for the state transition, def.: true

  • tBegin, tEnd: Time interval relative to the active time of the state in which the condition is evaluated. Def.: [tBegin,tEnd[=[0,[[t_{Begin}, t_{End}[ = [0, \infty[

states(..., transit({...})        // Transition to the initial state
, transit(sx, {...}) // Transition to sx
, transit(sx, cond) // ...with dynamic condition
, transit(sx, cond, tBegin)        // ...valid from time
, transit(sx, cond, tBegin, tEnd) // ...valid in time interval
, ...);
// Optional configuration for all variants, unless
// explicitly required
transit(..., { tBegin: <dbl>
, tEnd: <dbl>
, sFail: <var>
, nMax: <int>
, nVar: <str>
, actVar: <str>
, edge: <int>
, prio: <int>
})
PropertyValueDescription
tBegin<bool>Time in seconds relative to the active time of the state from which the condition is evaluated, def.: 0.0
tEnd<uint>Time in seconds relative to the active time of the state until which the condition is evaluated, def.: \infty
sFail<var>Replacement identifier / target state if sx does not designate a valid state
nMax<int>Maximum number of consecutive activations (loop counter), reset if the state is exited with any other transition.
nVar<str>The loop counter can be published in the designated variable and is updated when the transition is triggered.
actVar<str>As long as a transition is triggered, true is output on the designated variable.
edge<int>Determines whether the transition is triggered statically (0), with posedge (1) or negedge (-1) of the condition.
prio<int>Optional priority if several transitions trigger simultaneously. In principle, the first with the highest prio level wins in the order of definition.

Examples

Footnotes

  1. The fastest time constant of the process (T0=12πf0T_0 = \frac{1}{2\pi f_0}) should be 10 to 15 times the sampling time of the control/regulation system.