How to implement a filtered derivative

That’s true if you specify it as a differential equation as in the original post, but if it is specified as a rational transfer function H(z) as in the later post then the discrete-time function is specified uniquely. It depends on what @ufechner7 is comparing to.

1 Like

The point is, that the Simulink component I try to port to Julia is a hybrid that is working both in continues and discrete time… Which is a pain, you cannot easily know what it is really doing, and the documentation mixes both implementations…
Sorry for posting a continues time problem in the first place, this is not what I am looking for…

Yes the discrete time version posted later will be unique. I was comparing to the continuous time one.

If you have access to MATLAB you can select the block and press Ctrl+U to look under the mask. Most probably it would be using Variant subsystem somewhere and in that will implement the continuous and discrete versions.

1 Like

Just for completeness my current, verified implementation:

using PyPlot

# this implements the function (1/T)(z - 1)/(z + Ts/T -1)
function filtered_derivative(Ω; Ts=0.01, T=0.1)
    dΩ = zeros(length(Ω))
    a = [Ts/T - 1]
    b = [1, -1] / T
    for n in eachindex(Ω)
        if n > 1
            dΩ[n] = b[1] * Ω[n] + b[2] * Ω[n-1] - a[1] * dΩ[n-1]
        end
    end
    dΩ
end

N = 200
Ts = 0.01
Ω = zeros(N)
for i in 101:200
    Ω[i] = 1
end
dΩ = filtered_derivative(Ω; Ts)
P = zeros(N)
PyPlot.step((1:N)*Ts, dΩ)
grid(true)

Thanks a lot @A_C and @stevengj for all your input!

Looks like you’ve got it working, but here’s some context. First, the original continuous-time equations @ufechner7 provided are not a filtered derivative. They are equivalent to transfer function
\frac{K_d}{T_d} \frac{1}{(T_d s+1)}
which is a first-order low-pass filter. Almost certainly you want
\frac{K_d s}{(T_d s+1)}
which is what your reference shows in block diagram (a), but their implementation (b) forgets the s in numerator, which means derivative. (T_d s+1) in denominator is a low-pass filter, so you need both to get a filtered derivative. The frequency response asymptotes to K_d/T_d at high frequencies, which you can understand by taking s \to\infty. Here s is the Laplace transform operator, or kind of a derivative operator, or a complex frequency for a one-sided Fourier transform.

How did they get the discrete-time implementation? Any sampling of a continuous-time system will be an approximation, and it’s a matter of what you prioritize. Here they discretize a derivative as backward rectangular rule. So each s \gets (1 - z^{-1})/T_s, i.e. current sample minus previous sample and divide by sample period. Then multiply by whatever you need get the high-frequency gain above.

All this is from discrete-time control systems. @stevengj was able to figure it out because it’s math, but you can look up some textbooks if you want background for designing filters. (Personally I think this IIR implementation is standard and am skeptical there’s much to gain from FIR.)

BTW @ufechner7 I believe your implementation is still missing something, because your reference also shows a signal limiter, so you won’t truly reproduce their system until you put it in.

2 Likes

The implementation in block diagram (b) seems correct to me. The transfer function can be written as:
y(s)=\frac{K_{d}s}{1+sT_{d}}u(s)=\left(\frac{K_{d}}{T_{d}}\right)\left(\frac{1}{1+\frac{1}{sT_{d}}}\right)u(s),
which is what the block diagram (b) implements. The code that I have posted above actually implements the backward euler discretization of the block diagram along with saturation.

2 Likes

Thanks for your comments!

I am only porting a model to Julia that does not make use of the limiters, so I don’t need them. Another question is if this filter should be part of a package, DSP.jl or another package… I considered to create a Filters.jl package, but for now the code is so simple that it is not really worth creating a package for it…

I learned this all at university, but that is long time ago… From an engineering point of view it would be nice to have a set of often used filters available in a package that you can use without understanding the math…

Might be nice to have some convenience filters within DSP.jl, as non-exported but public functions. It’s already pretty close, because you can do digitalfilter(Highpass(1/T, 1/Ts), Butterworth(1)). The “filtered derivative” is not exactly a Butterworth, which I believe is usually digitized with bilinear (trapezoidal) transform rather than backward difference.

But all first-order filters are pretty similar, perhaps differing slightly in cut-off and pass-band gain. The filter could even be designed in analog but implemented digitally with analogfilter. (I’ve not verified any of the above.)