Skip to main content

Instrumentation and control engineering

Control engineering with the math module

With the extensive function library of the math module, it seems natural to also implement system control functions in this script language.

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

Signal processing, time response

The process of open and closed-loop control requires hard real-time calculations, i.e. a fixed signal runtime that is as short as possible from the acquisition of the measured variable to the output of the manipulated variable to the process. In control systems, this is typically approx. 1 ... 10 ms. This hard boundary condition cannot be met with the architecture of the smartCORE!

Measurement data is recorded by certain plug-ins and written to the channels of the smartCORE. For this purpose, asynchronously, the formula set of the math module is calculated on the available data at approximately constant, large time intervals, provided that all required channels also provide data for a point in time. The results are written to smartCORE channels in time with this calculation. 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 asynchronicity in smartCORE, the channels as buffers or ring memories and the batch processing of the math module.

If the processes to be influenced are slow 1 enough, you can at least 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 50 ... 1000 ms. Asynchrony and buffering of the data streams then become tolerable.

Correct time calculation

As essential as it is to calculate measurement data at the correct time for subsequent analysis and process monitoring, it is also a hindrance for system control processes. The basic rule in the math module is that extrapolation into the future is not permitted. This means that a history of measured values is only valid and usable up to the exact point in time at which it was last updated.

Assuming that certain setpoints or switching commands are supplied as a shared attribute from a dashboard, it may well take 2-5 seconds before a new value is available.

Assume that weather data required for parameterizing the control process is only supplied by the weather station once a minute.

In both cases, the controller would remain in place until new values are available. However, this is undesirable. Using the macro #timeless, corresponding channels can be removed from the time-based calculation. The last value in the channel is then also valid in the future until a new value is added. The trade-off for this behavior is that (short-term) value changes that lie before the last result value calculated on the basis of the forecast are no longer taken into account.

Controller

PID controller "pidCtrl"

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

The pidCtrl() function implements a controller with configurable proportional (P), integrating (I) and differentiating (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 manipulated variable.

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

modedescription
0, falseNormal control mode (Enable)
1, trueControl value hold
2Control value follows the manual control input u_man (Bypass)

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

important

The calculation is always performed with the discrete sampling time discreteSampleTimeMs. The execution time of the batch process evaluationTimeMs must be set to the same value so that the control variable can be transferred to the process promptly.

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>Gain 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 the actuating direction
false: e=spcure=sp-cur, (def.)
true: e=curspe=cur - sp
commonK<bool>Interpretation of the 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 manipulated variable,
the integral component is tracked to enable shock-free resumption.
upperoff|<dbl>Upper limit of the manipulated 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 handles the conversion of the physical dimensions between control deviation (e.g. in hPa) and manipulated variable (e.g. in %). This means that K does not influence the dynamic behavior of the controller, which is determined by its poles and zero points, but only the agility and stability of the closed control loop. Many setting rules for PID controllers are based on this structure.

It is rare to find the interpretation 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, making it considerably more difficult to adjust the controller.

On the use of the D component: As 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 only be used with caution. Due to the "on-change" philosophy when providing the measurement data in a smartCORE channel, long periods of time can occur in which the signal does not change. In order to be able to recognize a slow drift of a temperature, for example, the values of several sampling steps are calculated with a weighting function to the value of the derivative. The width of this window is specified by the dWidth property. However, this also results in an additional dead time (dWidth/2 * discreteSampleTimeMs) in the D-path of the controller, which can have a negative effect on the control process. Therefore, dWidth should be as small as possible but as large as necessary. This depends on the process to be controlled.

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

State machine (Finite State Machine)

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 a behavior that consists 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, the evaluation is clocked with the global discrete sampling time discreteSampleTimeMs. Exactly one transition can cause a change of state in each cycle.

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, as the system has reached it on its previous path, i.e. it reflects to a certain extent the changes to the input since the system was started up to 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 a different one is defined 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 as [1, 2, ... N] is forced 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 as well as a definable time window, a repeat counter and a priority value for the 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 that are 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 therefore take on the role of "from any" transitions, e.g. to intercept error conditions, realize timeouts or forced 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 state transitions from this state are defined 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 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 respective triggering transition is written to the variable designated 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/issued when a state is entered (regardless of which state transition was used to reach the state, if there are several).

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

  • Input action**: The action is generated depending on the current status and the input. A state can therefore be assigned several actions that are executed depending on which state transition is used to reach/leave it.

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

If act = state(...) is a variable that represents the active state, the state-dependent action can be realized as follows:

  • Input action: posedge(act == K)

  • Initial action: negedge(act == K)

  • Input action: (act == K)

The actVar: "TR" that can be defined in the transition can ultimately also be used to

  • Transitional actions: TR

reslized.

Transitions "transit"

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

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

  • sx: is the next state, provided the condition of the transition is fulfilled. If sx is missing, the transition returns to the active initial state without restarting it. sx can also originate from a calculation or a variable. If sx does not denote a known state, the substitute value sFail is used.

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

  • tBegin, tEnd: Time interval related 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 point in time
, transit(sx, cond, tBegin, tEnd) // ...valid in the 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 in relation to the active time of the state from which the condition is evaluated, def.: 0.0
tEnd<uint>Time in seconds in relation to the active time of the state up to which the condition is evaluated, def.: \infty
sFail<var>substitute identifier / target state if sx does not denote a valid state
nMax<int>maximum number of activations in a row (loop counter), is 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 to 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 are triggered simultaneously. In principle, the first one 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 - 15 times the sampling time of the open-loop/closed-loop control system.