[MAT logo][Prev][Up][Next]

Digital Signal Processing


The DSP module carries out various sorts of floating point operations, including arithmetic, speed and acceleration limiting, PID control, scaling, alarming and so on. It can also handle integer registers by converting them to floating point first.

The operations to be carried out by the DSP module are specified directly in the matplc.conf file (or in a separate file, using *include filename), in the fblock table.

The fblock table has the usual stepladder semantics: at the top, register values and contacts are read from the rest of the MatPLC (inputs, HMI, or other logic modules). The table is then scanned from top to bottom, with the operations being done in order. At the bottom of the table, register values and coils are written to the MatPLC core, to be used by the rest of the system (outputs, HMI or other logic modules).


The dsp config has one main parameter, and one table (fblock).

The fblock table is used to configure the function blocks the dsp module will execute.

The main parameter is:

  out_time_pt = <plc_pt>
where plc_pt is where the dsp will store the current time
out_time_pt = time
The scan_period parameter is valid for any module, but it will probably be used extensively by the dsp module.
scan_period = x
  time in seconds
scan_period = 0.1

The fblock table is used to configure the function blocks the dsp module will execute. The function blocks are executed in the same order in which they are configured (ie top to bottom). In the usual stepladder way, inputs are read once at the top of the table and results are not available to other modules until the bottom of the table.

Supported function block types

copy the value in an input point in one format, to an output point in another format. Supported formats are i16 (16 bit int), u16 (16 bit unsigned int), i32 (32 bit int), u32 (32 bit unsigned int), and f32 (32 bit float). All other function blocks use input and output points in the f32 format.

Add (with a specified multiplier) a maximum of 10 PLC points.

Multiply a maximum of 10 PLC points.

Raise a plc point to the power of x (x being a parameter).

Implements an open loop PID function. For closed loop controllers, use an add block to close the loop.

Filter the input, using an iir (infinite impulse response) filter.

Limit the maximum speed (dx/dt) and aceleration (d2x/dt2) with which the value of a given variable (x) may change.

Implements a deadband and limiting function.

Compares the value of a PLC point to up to a maximum of 10 limit values, and sets the value of output points accordingly.

Copy one of the input points to the output point. The input point that is copied is dependent on the value of a control point.

Typeconv block

#fblock typeconv <in_pt1> <in_pt1_type> <out_pt1> <out_pt1_type>
               [<in_pt2> <in_pt2_type> <out_pt2> <out_pt2_type>] ...

<out_pt_type> : How to interpret the bits in the previous point.
                = {i32 | u32 | f32}

Add block

#fblock add <out_pt>     <in_pt1> <in_pt1_mult> [<in_pt2> <in_pt2_mult>] ...

 out_pt = (in_pt1 * in_pt1_mult) + (in_pt2 * in_pt2_mult) + ...

 Note: currently a maximum of 10 in_pt are supported.

Mult block

#fblock mult <out_pt>     <in_pt1> <in_pt1_ofs> [<in_pt2> <in_pt2_ofs>] ...

 out_pt = (in_pt1 + in_pt1_ofs) * (in_pt2 + in_pt2_ofs) * ...

 Note: currently a maximum of 10 in_pt are supported.

Pow block

#fblock pow <out_pt> <in_pt> <in_pt_pow>

  out_pt    : matplc point to be used as output
  in_pt     : matplc point to be used as input
  in_pt_pow : raise in_pt to in_pt_pow (f32 value)

  out_pt = (in_pt)

PID block

fblock pid <in_pt> <out_pt> [<P> [<I> [<D>]]] [max_out <upper_limit>] [min_out <lower_limit>] [man_mode <manual_mode_pt>] [man_out <manual_value_pt>]

This block implements a parallel PID controler.
out_pt = P*in_pt + I*integral(in_pt, dt) + D*din_pt/dt

The output is guaranteed to stay within the configured limits (lower_limit <= output <= upper_limit) in automatic mode. This is achieved by adjusting the integral, which means that the pid will not 'wind up' when the output is saturated.

The man_mode and man_out settings work together to provide bumpless manual-to-automatic transfer. See the bumpless transfer section for more details.

When man_mode_pt is ON, the block is in manual mode:
out_pt = manual_value_pt
In manual mode, the integral is adjusted in such a way that when man_mode_pt goes OFF, the PID block will smoothly take over from the operator.

Note that manual mode ignores the upper and lower limits; if necessary, pass the operator's setting through a nonlinear block to clip it to the limits (and perhaps also through the ramp block). This also means that if the operator sets the process outside the limits and switches to automatic, there will be a bump as the PID immediately jumps to within the limits.

Also note that bumpless transfers are only supported when I is non-zero.

settingmeaningdefault value
Pproportional coefficient of PID1
Iintegral coefficient of PID0
Dderivative coefficient of PID0
upper_limitmaximum output value for automatic modenone
lower_limitminimum output value for automatic modenone
manual_mode_ptmanual/automatic selectionnone (always automatic)
manual_value_ptvalue to be output in manual modenone (always zero)

Filter block

fblock filter iir [<C> [<A1> [<A2> [<B1> [<B2>]]]] ...
fblock filter <filter_type> <filter_shape> <gain> <passband_tol> <stopband_tol> <f1> <f2> [<f3> <f4>]

C, A1, A2, B1, B2second order iir filter parameters directlyPlease see below for an explanation of what an iir filter is. These five parameters completely specify the filter, so no further parameters are necessary.
filter_type{butterworth | chebyshev | elliptic} This method is used to configure the filter as an equivalent to an analog filter. At setup these parameters are transformed into the equivalent iir filter, which will be executed at run-time.
filter_shape{lowpass | highpass | bandpass | bandstop} NOTE: These transformations have not been completely debuged. lowpass and highpass *should* be working correctly. bandpass and bandstop are known to be buggy.
gain the gain of the filter for the passband frequencies
Forlowpass,gain = g(0)i.e. gain at f = 0 Hz
highpass,gain = g(F/2)i.e. gain at f = F/2 Hz
bandpass,gain = g(fp1/2 + fp2/2)i.e.jgain at f = (fp1 + fp2) / 2 Hz
bandstop,gain = sqrt [ g(0)*g(0) + g(F/2)*g(F/2) ]
(F is sampling frequency)
passband_tol (stopband_tol)max(min) atenuation for pass(stop)band maximum(minimum) atenuation, in positive dB, for the passband(stopband) frequencies
fX frequency limits in Hz NOTE: The meaning of f1, f2, f3 and f4 depends on the filter shape. The idea is to have valid frequencies always in increasing value.
f1:passband frequency limit
f2:stopband frequency limit
f1:stopband frequency limit
f2:passband frequency limit
f1:lower stopband frequency limit
f2:lower passband frequency limit
f3:higher passband frequency limit
f4:higher stopband frequency limit
f1:lower passband frequency limit
f2:lower stopband frequency limit
f3:higher stopband frequency limit
f4:higher passband frequency limit

The filter block implements X second order iir filters in series. A second order iir filter:
         | \
 in >----|C >-->(+)-->(+)----------------------->(+)-->(+)---> out
         | /     ^     ^               |          ^     ^
         |/      |     |               |          |     |
                 |     |               v          |     |
                 |     |             (z-1)        |     |
                 |     |   /|    /|    |    |\    |     |
                 |     |  / |   / |    |    | \   |     |
                 |     --<-1|--<B1|<---|--->|A1>---     |
                 |        \ |   \ |    |    | /         |
                 |         \|    \|    v    |/          |
                 |                   (z-1)              |
                 |         /|    /|    |    |\          |
                 |        / |   / |    |    | \         |
                          \ |   \ |         | /
                           \|    \|         |/
where (z-1) is a delay block, i.e., in the z transform, z to the power of -1.

Ramp block

fblock ramp <in_pt> <out_pt> [dxdt <xx>] [pos_dxdt <xx>] [neg_dxdt <xx>] [d2xdt2 <xx>] [pos_d2xdt2 <xx>] [neg_d2xdt2 <xx>]

in_pt:the plc_pt where the input value (x) is stored
out_pt:the plc_pt where to store the output value
dxdt:maximum speed with which x may change (both positive and negative changes).
pos_dxdt:maximum speed with which x may rise. Defaults to no limit.
neg_dxdt:maximum speed with which x may fall. Defaults to no limit.
d2xdt2:maximum speed with which dx/dt may change (both positive and negative changes).
pos_d2xdt2:maximum speed with which dx/dt may rise. Defaults to no limit.
neg_d2xdt2:maximum speed with which dx/dt may fall. Defaults to no limit.

Nonlinear Block

fblock nonlinear <in_pt> <out_pt> [cutoff_top <xx>] [cutoff_bot <xx>] [deadband_top <xx>] [deadband_bot <xx>] [deadband_out <xx>] [gain <xx>]

Defaults are:
This function block implements a nonlinear block supporting both a deadband function centered around a configured offset, and a limiter. In addition, it also allows for a linear gain and offset to be applied to the output of it's nonlinear function. These last two are essentially to reduce the number of function blocks eventually required to implement a specific global user function.

The nonlinear part, implements the following function:

    out = nl_f(in):
#			   out
#			    ^
#			    |
#			    |
#		     co_top |.............................--------
#			    |                            /
#			    |                           /
#			    |                          /
#			    |                         /
#			    |                        /
#			    |                       /
#			    |                      /
#			    |                     / inclination = 1
#			    |                    /
#			    |                   /
#		     db_out |...----------------
#			    |  /.              .
#			    | / .              .
#			    |/  .              .
#			    |   .              .
#		   	   /|   .              .
#		          / |   .              .
#		         /  |   .              .
#		        /   |   .              .
 <--------------------------------------------------------------> in
#		      /     | db_bot         db_top
#		     /      |
#		    /       |
#		   /        |
 ----------------.........| co_bot
#			    |
#			    |
#			    |
#			    v

#	(co = cutoff      db = deadband)

The linear part implements the following function:

out = l_f(in) = in * gain

The output of the complete nonlinear block is:

out =  nl_f( in * gain )

Alarm block

#fblock alarm <in_pt> {true_val|abs_val} <out_pt1> <comp1> <limit1> [<out_pt2> <comp2> <limit2>] ...
  in_pt   : matplc point to be used as input for the alarm block
  true_val: use the value in in_pt without any changes
  abs_val : use the absolute value in in_pt for determining the alarms
  out_pt  : matplc point to be used as output for the alarm block
  limitl  : f32 value used for the alarm comparison
  comp    : specifies when the alarm should be set.
            one of:
              {less | lt | smaller | st |
               less_or_equal | le | smaller_or_equal | se |
               greater | gt | greater_or_equal | ge |
               equal | eq | not_equal | ne}
             Note: less, lt, smaller, and st, are all equivalent
                    greater and gt are equivalent
                    greater_or_equal and ge are equivalent

fblock alarm in_pt true_val out_1 10 lt out_2 10 gt out_3 20.55 eq
 (consider in_pt_val the value currently stored in the in_pt PLC point)
  then the above config line will have the efect of:
   - out_1 being true (1) when in_pt_val < 10, and (false) 0 otherwise
   - out_2 being true (1) when in_pt_val > 10, and (false) 0 otherwise
   - out_1 being true (1) when in_pt_val = 20.55, and (false) 0 otherwise

Multiplexor block

#fblock multiplexor <out_pt> <ctrl_pt> <in_pt1> [<limit1> <in_pt2>] ...

  out_pt : matplc point to be used as output for the multiplexor block
  ctrl_pt: matplc point used to decide which input to copy to the output
  in_ptX : matplc point to be used as input for the multiplexor block
  limitX : limit value at which the output switches from one input to another

  out_pt = in_pt1 -> if (ctrl_pt <  limit1)
  out_pt = in_pt2 -> if (ctrl_pt >= limit1) AND (ctrl_pt < limit2)
  out_pt = in_pt3 -> if (ctrl_pt >= limit2) AND (ctrl_pt < limit3)


$Date: 2006/07/20 16:59:02 $