Counting and timing functions
Signal shaping
Dirac pulse "dirac"
The function outputs a 0-1-0 pulse with a length of 1 ns using the global discrete sampling time discreteSampleTimeMs. The return type is <bool>.
p = dirac();
Since this function is typically used for logical functions, the return value as <bool> is directly false or true. For a "real" Dirac impulse, the integral condition
is satisfied, dirac() would have to be multiplied by .
To sample a signal with the discrete sampling time discreteSampleTimeMs, use the function sample(x).
Timer "timer"
The following formula periodically returns a pulse or the corresponding timestamp at the defined times.
pulse = timer({ interval: <dbl> // mandatory, unless at least one (*) is defined
, grid: <bool>
, readTime: <bool>
, minute: <str> // (*)
, hour: <str> // (*)
, day: <str> // (*)
, month: <str> // (*)
, weekday: <str> // (*)
});
// The configuration object is mandatory in order to define
// a unique configuration from interval or a
// (*) element to define the event times.
| Property | Value | Description |
|---|---|---|
| interval | <dbl> | Time interval in which an event is triggered. |
| grid | <bool> | If this option is set, the interval is based on 00:00:00 of the day, regardless of the start time of the calculation. |
| readTime | <bool> | If this option is set, instead of a 1 nanosecond pulse at the event time, the timestamp is output, uin64 in UTC nanoseconds since January 1, 1970. |
| minute | <str> | crontab syntax for defining event times |
| hour | <str> | crontab syntax for defining event times |
| day | <str> | crontab syntax for defining event times |
| month | <str> | crontab syntax for defining event times |
| weekday | <str> | crontab syntax for defining event times |
If the parameters hour, minute, day, month, and/or weekday are used instead of interval, explicit trigger times (UTC) can be specified.
The following information is possible for each entry in the order minute, hour, day, month, weekday (based on crontab syntax):
| Specification | Meaning |
|---|---|
| No specification | is '*' if all subsequent elements are not defined, otherwise '0' |
| '*' | always / at any time |
| '*/n' | at intervals of n |
| 'a-e' | in the range from a to e inclusive |
| 'a,b,c' | comma-separated list of any individual values Execution at/on a, b, and c |
For weekdays and months, short names corresponding to the first three letters of the English name can be used instead of numbers: e.g., "mon," "thu," "apr," "jun," "dec," ... .
The counting of weekdays starts on Sunday "sun" with 0.
Pulses can be used to reset sums or integrals or to transfer corresponding values to a latch register.
| Example | Pulse time ... |
|---|---|
{minute: 30, hour: 4} | daily at 4:30 a.m., "after closing time" |
{day: 1} | on January 1 of each month at 12:00 a.m. |
{minute: '*/15'} | every 15 minutes, x:00, x:15, x:30, x:45 |
{hour: 2, weekday: 'sun'} | weekly on Sunday at 2:00 a.m. |
{day: 15, month: 'apr-sep'} | on the 15th of the months April to September at 0:00 a.m. |
{hour: '6,9,14,18'} | daily at 6, 9, 14, and 18 o'clock |
Example
In Example 1b, the timer() function is used to generate a memory pulse at a fixed time (end of operation).
Delay
The following formulas are used to filter and delay signal edges
delayed1_s = delay(signal, {...});
delayed2_s = delay(signal, reset, {...});
// The configuration object is mandatory.
delayedX_s = delay(..., { delayOn:<dbl>
, delayOff:<dbl>
, restart:<bool>
, startup: inf|<bool>
});
| Property | Value | Description |
|---|---|---|
| delayOn | <dbl> | Time in seconds for delaying the positive edge |
| delayOff | <dbl> | Time in seconds for delaying the negative edge |
| restart | <bool> | Subsequent edges during the wait time restart the time interval |
| startup | inf/<bool> | Start condition for edge detection, see description below |
The behavior depends on the output signal state. If this is false, only positive edges on the input signal signal and the time parameter delayOn are taken into account. If the state is true, negative edges and the time parameter delayOff are taken into account.
Time measurement begins with the first arriving edge and can optionally be restarted with subsequent edges (restart: true). The output state only changes if the input signal is in the opposite state when the time expires. This means that only short signal changes are filtered and signal changes are only passed on after the signal has stabilized.
With a true at the reset input, the output state is reset to false and held.
The function can be used to filter and stabilize a "bouncing" switching signal.
For the system start, it must be specified how the past of the signal input is to be handled and whether an edge should be detected immediately at start-up, thereby triggering a waiting time. The startup property is used for this purpose:
-
inf: the first signal sample determines the value in the past and thus the output before system startup; an edge is therefore not triggered with the first sample.
-
<bool>: The input and output are assumed with this signal value (true, false) in the past before system startup. This may trigger an edge with the first sample of the input and start a delay time.
Pulse "pulse"
The following formulas convert a selectable input edge on signal into a rectangular Boolean pulse with a duration of duration (similar to a 74HC121 or 74HC122 mono flip-flop). With a true at the reset parameter, the output is reset to false and held. All parameters are interpreted as <bool> .
p1 = pulse(signal, {...});
p2 = pulse(signal, reset, {...});
p3 = pulse(signal, reset, duration, {...});
// The configuration object is mandatory.
px = pulse(..., { edge:<int>
, duration:<dbl>
, restart:<bool>
, startup: inf|<bool>
});
| Property | Value | Description |
|---|---|---|
| edge | <int> | Selection of the controlling edge: -1: negEdge, 0: anyEdge, +1: posEdge (default) |
| duration | <dbl> | Duration of the pulse in seconds |
| restart | <bool> | Extension of the pulse with renewed edge possible |
| startup | inf/<bool> | Start condition for edge detection, see description below |
The following example shows the behavior for the restart property for edge = +1:
For the system startup, it must be specified how the past of the signal input is to be handled and whether an edge should be detected immediately at startup, thereby triggering a pulse. The startup property is used for this purpose:
-
inf: the first signal sample determines the value in the past before system startup; an edge is therefore not triggered with the first sample.
-
<bool>: The input is assumed to have this signal value (true, false) in the past before system startup. This may allow an edge to be triggered with the first sample.
Function generator "periodic"
The function periodic() can be used as a function generator and generates a periodic signal with the period duration period as long as the input enable is held at true. The signal shape is determined by the mode property. The output rate is determined by the global discrete sampling time discreteSampleTimeMs or the set output rate fOut.
p1 = periodic(enable, {...});
p2 = periodic(enable, control, {...});
p3 = periodic(enable, control, period, {...});
// The configuration object is mandatory.
px = periodic(..., { period: <dbl>
, mode: <enum>
, reset: <enum>
, control: <dbl>
, fOut: <dbl>
, width: <uint>
, taps: [<uint>]|p##
});
| Property | Value | Description |
|---|---|---|
| period | <dbl> | Constant period duration of the signal curve in seconds, corresponds to input period Value range: |
| mode | <enum> | Operating mode (def.: ramp) [rect, pwm, time, ramp, ramp2, sawtooth, 2Pi…] |
| reset | <enum> | Reset of the signal waveform with [stop, start, none] |
| control | <dbl> | Constant control value for PWM, corresponds to input control |
| fOut | <dbl> | Optional output rate for data points in Hertz Value range |
| width | <uint> | PRBS signal output width Value range |
| taps | [<uint>]/p## | PRBS feedback positions or predefined polynomial p2..p12 |
The optional inputs control and period have priority over the fixed properties. If the period duration changes during signal output, the signal curve continues smoothly at the current output position (*).
Even though the selection of the period duration and output rate is not initially subject to any restrictions, sensible values should be selected with regard to the function of the smartCORE.
Values for reset:
-
stop: (default) The output value is reset with enable == false.
-
start: The output value remains until restarted and is only reset then.
-
none: The output is only stopped with enable == false, not reset.
A few examples of output modes in conjunction with the period duration period, the output rate fOut, a control signal control, and various reset settings
Mode: rect
A <bool> 0-1 square wave signal is output, where control represents the relative position of the positive edge in the period time period (default: 0.5). Reset state is 0!
Mode: pwm
A <bool> 1-0 square wave signal is output, where control represents the relative position of the negative edge in the period time period (PWM, default: 0.5). Reset state is 0!
Mode: time
Ramps with the time values in seconds are output.
Mode: ramp (def.)
Ramps are output with the relative position in the interval as a scaling value
Mode: ramp2
Ramps are output with the scaling values , whereby the return to is in the middle of the period duration.
Mode: sawtooth
A sawtooth-shaped curve is output, where control represents the relative position of the 1.0 peak in the period time period. The reset state is 0.0!
Mode: 2pi
The relative position in the interval is output as an angle value for downstream angle functions.
wave = 10.0 * sin(periodic(true, { mode : 2pi
, period: 2.0 // Signal period / s
, fOut: 100.0})); // Sample rate
Mode: prbs
Output of a pseudo binary noise signal (pseudo random binary sequence) with the output frequency fOut. The period length is determined by the configured generator; the parameter period is ignored.
NXOR feedback is provided on the internal 64-bit shift register at the positions marked by *taps[]. width (def: 0) is the bit width of the output mask for the shift register in order to use the PRBS to generate pseudo-random amplitudes. With width: 0, only a <bool> sequence is output.
For taps, predefined polynomials p2 .. p12 can also be called up as feedback for lengths 2 .. 12 bits.
The PRBS signal can be used for parameter identification of dynamic systems.
Counting and measuring
Counter "counter"
The following formulas count positive edges in various configurations.
The meaning of the parameters depends on the set operating mode!
c1 = counter(up);
c2 = counter(up, down); // mode: updown
c3 = counter(up, down, reset); // mode: updown
c4 = counter(up, down, reset, preset); // mode: updown
c5 = counter(count, dir); // mode: countdir
c6 = counter(count, dir, reset); // mode: countdir
c7 = counter(count, dir, reset, preset); // mode: countdir
c8 = counter(count, incr); // mode: countinc
c9 = counter(count, incr, reset); // mode: countinc
c10 = counter(count, incr, reset, preset); // mode: countinc
c11 = counter(A, B); // mode: qencoder
c12 = counter(A, B, reset); // mode: qencoder
c13 = counter(A, B, reset, preset); // mode: qencoder
// Optional configuration for all variants
cX = counter(..., { mode: <enum> // mandatory if not 'updown'
, start: <int>
, preset: <int>
, lower: off|<int>
, upper: off|<int>
, range: <uint>
, modulo: <uint>
, storage: <str>
});
In updown mode (default), positive edges count up on up and down on down (similar to a 74HC193). If the edges occur at exactly the same time, is counted.
In countdir mode, positive edges are counted at the count input and the direction is specified independently with the dir input of type <dbl> (similar to 74HC191). If dir > 0.0 (or true), counting is upward, otherwise with dir <= 0.0 (or false) downward. The default is 1.0 or true (upward). Using the <dbl> type for the direction allows the use of an analog speed measurement (e.g., in "m/s") to control the counting direction. On the other hand, the input is compatible with <bool> signals.
Areas of application include position determination for linear or rotary movements or direction-dependent counting of objects passing a counting station.
In countincr mode, the counting increment is added to the register via the incr input of type <int> with a rising edge on count. The default is 1 (upward). The magnitude of incr should be adjusted appropriately to the set counter width, counter limits, etc.
In qencoder mode, all edges on the phase-shifted signals A and B are counted. The use of the two inputs is therefore mandatory. The signal without an edge indicates the counting direction. Areas of application include high-precision position determination for linear or rotary movements in 4x resolution ("quadrature encoder"). For this purpose, the edges should have exactly the same spacing.
The arrangement shown in the figure results in the following counting scheme:
| A | B | Clockwise rotation Increment | Counterclockwise rotation Decrement |
|---|---|---|---|
| 0 | 0 | A: 0->1 | B: 0->1 |
| 1 | 0 | B: 0->1 | A: 1->0 |
| 1 | 1 | A: 1->0 | B: 1->0 |
| 0 | 1 | B: 1->0 | A: 0->1 |
| 0 | 0 | A: 0->1 | B: 0->1 |
With a true at the reset input, the counter is set to preset (def: 0) and held. preset can be passed via the properties or as a fourth argument.
The count register is of type <int64>
| Property | Value | Description |
|---|---|---|
| mode | <enum> | updown: Separate count inputs for up/down (def.) countdir: Count input and separate direction <dbl> (> 0.0: up)countincr: Clock input and separate increment as <int>qencoder: All edges of clock signals A, B are counted depending on direction |
| start | <int> | Start value with start of smartCORE |
| preset | <int> | Reset value with true on parameter r |
| lower | off/<int> | Count value stops at lower limit, no overflow |
| upper | off/<int> | Count value stops at upper limit, no overflow |
| range | <uint> | Count value range Overflow from the boundary values to or |
| modulo | <uint> | Count value range count %= modulo with signOverflow from the edge values to 0 |
| storage | <str> | Name of a persistent memory for the internal state. This ensures that the output receives the last stored value after a system restart. The contents of this memory cannot be used anywhere else in the smartCORE. |
Stopwatch "stopwatch"
The following formulas represent a stopwatch and measure the length of a pulse pulse or the interval between two positive edges on pulse or between the first positive edge on beg and the subsequent positive edge on end. The measurement always starts with the start condition at . An intermediate time can be output with an edge at the lap input (latch = true). True at the reset input sets the stopwatch and output to 0.0 and keeps them in this state. All inputs are interpreted as <bool>. The output is in seconds.
t1 = stopwatch(pulse);
t2 = stopwatch(beg,end);
t3 = stopwatch(beg,lap,end);
t4 = stopwatch(beg,lap,end,reset);
// Optional configuration for all variants
tx = stopwatch(..., { latch: <bool>
, period: <bool>
, hold: <bool>
, restart: <bool>
, upper: off|<dbl>
});
| Property | Value | Description |
|---|---|---|
| latch | <bool> | true: Output of the time only occurs with the controlling edges (def.) false: Continuous output of the rising measurement time |
| period | <bool> | true: Measurement between two rising edges at the pulse input false: Measurement of the time for pulse = true |
| hold | <bool> | true: The output is only set to the new measured value when the measurement is complete. false: The output is set to 0 with a new/ongoing measurement. |
| restart | <bool> | true: Each rising edge at beg restarts the measurement false: Only the first rising edge at beg starts the measurement (def.) |
| upper | off/<dbl> | When this time value is reached, the output is made and the measurement is terminated. (def.: off) |
In the first form, only one pulse signal pulse is used. The following diagram shows various configurations and output options for measurement on a pulse signal:
The first line shows any pulse signal to be measured.
The second line shows the time that has elapsed since the corresponding edge at the left footpoint for the pulse duration measurement with the ascending, dashed ramps. Finally, in magenta, the output of the stopwatch() function for various properties latch, hold or upper.
The third line shows the time that has elapsed since the corresponding edge at the left foot point for period measurement with the ascending, dashed ramps. Finally, in orange or blue, the output of the stopwatch() function depending on the properties latch or upper.
For operation with beg, lap, and end inputs, the output is configured accordingly. With the restart property, an active measurement can start again at 0.0 with each new edge at beg, measuring the distance from the last rising edge to the edge at end. In this mode, the output of intermediate times can be misleading. In the following diagram, the latch property is set to true to enable the output of intermediate times.
The first three lines show example time curves for the input signals beg, lap, and end. The lap input is optional. In the dashed areas, either a return of the signal to false (green) is possible at any time, since only a rising edge is relevant for the beg input, or the signal may assume any state (red, blue) since the clock has not started.
The bottom line again shows the output of the stopwatch() function for different settings of the restart and hold properties. The ascending, dashed ramps show the time that has elapsed since the corresponding edge at the left foot point.
stopwatch() only measures the length of a single event. To determine the total operating time of an aggregate (heating, compressor, etc.), the integrate(x, {...}) function is useful.
total_on_time = integrate(onState, {storage:'myTotalizerX'});
Here, onState is a <bool> status signal that forms the integrand as 0 or 1. Optionally, a reset signal could be used to reset the integrated value.
Conversions
Time conversion "decodeTime" 1
The function decodeTime() takes a scalar timestamp t in UTC and converts it to the corresponding date and time representation using the optional offset tzDif to the local time. Various interpretations and output formats can be set.
TM1 = decodeTime(t);
TM2 = decodeTime(t, tzDif);
// Optional configuration
TMx = decodeTime(..., { scale: <enum>
, epoch: unix|<date>
, tzDif: <int>
, format: <str>
});
| Property | Value | Description |
|---|---|---|
| scale | <enum> | Determines what the integer part of the timestamp describes: auto: The order of magnitude of the timestamp determines the resolution (def.), or the integer part of t counts... d: ... days s: ... seconds ms: ... milliseconds us: ... microseconds ns: ... nanoseconds |
| epoch | unix/<date> | The start time of the count is set to the given UTC date, format: 'yyyy-mm-dd', optionally with time specification 'yyyy-mm-dd HH:MM' (def.: unix 1970-01-01) |
| tzDif | <int> | Time offset in minutes for outputting local time, example CET: +60, CEST: +120, EST: -300 |
| format | <str> | Instead of a vector, a formatted date/time string is output. The function uses the C++ function strftime() internally. The formatting of the output is described here.In addition, the following placeholders can be used: %FMS: 3 digits milli-seconds %FUS: 6 digits micro-seconds %FNS: 9 digits nano-seconds each with leading zeros |
Unless the format property is used to request the output of a formatted date-time text, the result is a vector with the following <uint> values:
// Return of the date-time information as a vector corresponding to
// the following content:
TM = [ year, month, day
, hour, minute, second, nanoseconds
, weekday // 0..6, 0 := Sunday
, yearday];