fpe
fpe

Reputation: 13

Problem with persistent states within embedded function

I am currently implementing a second order low-pass filter employing Tustin discretization as embedded function within a Simulink model. The function has currently deployed as follows:

function y = SecondOrderLowpassFilterTustin(u,fn,dn,Ts)

persistent xs
if isempty(xs)
    xs = [u 0]';
end

% Convert frequency from Hz to rad/s
wn = fn*2*pi;

% Construct state-space matrices in continuous time
A = [0 1 ; -wn^2 -2*dn*wn];
B = [0 ; wn^2];
C = [1 0];
D = 0;

% Construct equivalent state-space matrices in discrete time
I = eye(size(A));
K1 = (I + 0.5*A*Ts);
K2 = (I - 0.5*A*Ts)^-1;
Ad = K1*K2;
Bd = K2*B*Ts;
Cd = C*K2;
Dd = (0.5*Ts*C*K2*B) + D;

% Calculate output
xs = Ad*xs + Bd*u;
y  = Cd*xs + Dd*u;

end

I am then calling such function from within another function which looks like this:

function u1 = fcn(u,fn,dn,Ts)

u1 = SecondOrderLowpassFilterTustin(u(1),fn,dn,Ts);

In all those cases when I call the function a single time, as in the case

y1 = SecondOrderLowpassFilterTustin(u1,fn,dn,Ts);

the results are ok Figure 1. Filtering single signal

However, as soon as I would like to filter multiple signals concurrently, as in the following case

function [u1,u2,u3] = fcn(u,fn,dn,Ts)

u1 = SecondOrderLowpassFilterTustin(u(1),fn,dn,Ts);
u2 = SecondOrderLowpassFilterTustin(u(2),fn,dn,Ts);
u3 = SecondOrderLowpassFilterTustin(u(3),fn,dn,Ts);

the results are poor as in Figure 2. Figure 2. Multiple signal filtering

I believe that it has to do with the persistent state variable xs, which should undergo a reset or initialization as soon as the SecondOrderLowpassFilterTustin(u,fn,dn,Ts) is being called.

I have tried different things out, unfortunately with little success. Therefore, your suggestions are highly appreciated.

Upvotes: 1

Views: 65

Answers (1)

rinkert
rinkert

Reputation: 6863

Indeed, the persistent variable is not reset when calling the filter function the second and third time, and thus the initial xs is not set correctly. Since you want to use the function for multiple signals, the persistent variable cannot be inside SecondOrderLowpassFilterTustin.

You can however let this function output xs and take xs as input argument, and keep this persistent in fcn.

function [y, xs] = SecondOrderLowpassFilterTustin(u,fn,dn,Ts,xs)

    if isempty(xs)
        xs = [u 0].';
    end

    % Convert frequency from Hz to rad/s
    wn = fn*2*pi;

    % continue with the rest...

end

And fcn would look like:

function [u1,u2,u3] = fcn(u,fn,dn,Ts)

    persistent x1 x2 x3

    % x1, x2 and x3 will be [] on first iteration, thus xs will be set to [u 0].'
    [u1,x1] = SecondOrderLowpassFilterTustin(u(1),fn,dn,Ts,x1);
    [u2,x2] = SecondOrderLowpassFilterTustin(u(2),fn,dn,Ts,x2);
    [u3,x3] = SecondOrderLowpassFilterTustin(u(3),fn,dn,Ts,x3);

end

BTW, don't think you expect any complex output, but just in case ' is not transpose, .' is.

Upvotes: 2

Related Questions