Weave.jl/previews/PR311/examples/FIR_design.txt

170 lines
3.5 KiB
Plaintext

# Introduction
This an example of a julia script that can be published using
[Weave](http://mpastell.github.io/Weave.jl/latest/usage/).
The script can be executed normally using Julia
or published to HTML or pdf with Weave.
Text is written in markdown in lines starting with "`#'` " and code
is executed and results are included in the published document.
Notice that you don't need to define chunk options, but you can using
`#+`. just before code e.g. `#+ term=True, caption='Fancy plots.'`.
If you're viewing the published version have a look at the
[source](FIR_design_plots.jl) to see the markup.
# FIR Filter Design
We'll implement lowpass, highpass and ' bandpass FIR filters. If
you want to read more about DSP I highly recommend [The Scientist
and Engineer's Guide to Digital Signal
Processing](http://www.dspguide.com/) which is freely available
online.
## Calculating frequency response
DSP.jl package doesn't (yet) have a method to calculate the
the frequency response of a FIR filter so we define it:
~~~~{.julia}
using Plots, DSP
gr()
function FIRfreqz(b::Array, w = range(0, stop=π, length=1024))
n = length(w)
h = Array{ComplexF32}(undef, n)
sw = 0
for i = 1:n
for j = 1:length(b)
sw += b[j]*exp(-im*w[i])^-j
end
h[i] = sw
sw = 0
end
return h
end
~~~~~~~~~~~~~
~~~~
FIRfreqz (generic function with 2 methods)
~~~~
## Design Lowpass FIR filter
Designing a lowpass FIR filter is very simple to do with DSP.jl, all you
need to do is to define the window length, cut off frequency and the
window. We will define a lowpass filter with cut off frequency at 5Hz for a signal
sampled at 20 Hz.
We will use the Hamming window, which is defined as:
$w(n) = \alpha - \beta\cos\frac{2\pi n}{N-1}$, where $\alpha=0.54$ and $\beta=0.46$
~~~~{.julia}
fs = 20
f = digitalfilter(Lowpass(5, fs = fs), FIRWindow(hamming(61)))
w = range(0, stop=pi, length=1024)
h = FIRfreqz(f, w)
~~~~~~~~~~~~~
~~~~
1024-element Array{Complex{Float32},1}:
1.0f0 + 0.0f0im
0.99546844f0 + 0.095055714f0im
0.98191506f0 + 0.1892486f0im
0.95946306f0 + 0.28172377f0im
0.9283168f0 + 0.37164196f0im
0.8887594f0 + 0.45818728f0im
0.84115064f0 + 0.54057467f0im
0.7859234f0 + 0.618057f0im
0.72357976f0 + 0.6899319f0im
0.65468615f0 + 0.7555481f0im
0.00043952762f0 - 0.00041908873f0im
0.0005152718f0 - 0.00040521423f0im
0.0005873293f0 - 0.00037745363f0im
0.0006531789f0 - 0.0003367371f0im
0.0007105166f0 - 0.00028444792f0im
0.0007573364f0 - 0.00022237403f0im
0.0007920005f0 - 0.00015264557f0im
0.0008132961f0 - 7.766036f-5im
0.0008204784f0 - 3.1148685f-18im
~~~~
## Plot the frequency and impulse response
The next code chunk is executed in term mode, see the [script](FIR_design.jl) for syntax.
~~~~{.julia}
julia> h_db = log10.(abs.(h));
1024-element Array{Float32,1}:
0.0
-1.5272748f-6
-6.0314724f-6
-1.3538573f-5
-2.394518f-5
-3.7173842f-5
-5.3121257f-5
-7.165827f-5
-9.257809f-5
-0.00011577748
-3.2165928
-3.1834154
-3.1560452
-3.1337893
-3.1161458
-3.102753
-3.0933545
-3.0877802
-3.0859327
julia> ws = w/pi*(fs/2)
0.0:0.009775171065493646:10.0
~~~~~~~~~~~~~
~~~~{.julia}
plot(ws, h_db,
xlabel = "Frequency (Hz)", ylabel = "Magnitude (db)")
~~~~~~~~~~~~~
![](figures/FIR_design_4_1.png)\
And again with default options
~~~~{.julia}
h_phase = unwrap(-atan.(imag.(h),real.(h)))
plot(ws, h_phase,
xlabel = "Frequency (Hz)", ylabel = "Phase (radians)")
~~~~~~~~~~~~~
![](figures/FIR_design_5_1.png)\