IIR filter relationship between number of poles, order and second order sections

I have ported Iowa Hills Code Kit to a mcu to calculate IIR filter coefficients. They are used to initialize the CMSIS Biquad Cascade IIR Filters Using a Direct Form II Transposed Structure.

Trying to compare the output of my mcu program with a similar python script written using SciPy I realized that there is a discrepancy between the two, as explained below.

SciPy

Calculating a 4th order bandpass IIR filter using the following in SciPy,

sos = scipy.signal.iirfilter(4,
[1500, 2500],
btype='bandpass',
analog=False,
ftype='bessel',
output='sos',
fs=50000)

results in 8 zeros and 8 poles which is then converted to 4 Second-Order-Sections. This gives

My understanding however, is that the code above is producing an 8th order filter and that a 4th order filter should be represented as 2 second order sections and should have 4 poles and zeros. I might be missing something very obvious, but I'm not sure why signal.iirfilter produces this result!

IowaHills

To calculate a 4th order bandpass IIR fitler using IowaHills however, I would have to input numPoles=2 to get 2 second order sections as shown below,

TIIRCoeff coeffs = {0};              // filter coefficients struct (IowaHills)
TIIRFilterParams fparams;            // filter parameters struct (IowaHills)
fparams.IIRPassType = iirBPF;        // bandpass filter
fparams.ProtoType = BESSEL;          // proto bessel
fparams.BW = 0.10;                   // filter width
fparams.dBGain = 1.0;                // gain
fparams.Gamma = 0.0;                 // transition bandwith
// NumPoles = [order / 2] for BandPass and BandStop
// NumPoles = [order]     for LowPass and HighPass
fparams.NumPoles = 2;                // 4th order
fparams.OmegaC = 0.41;               // centre frequency for bandpass
fparams.Ripple = 0.0;                // only for chebyshev/elliptical
fparams.StopBanddB = 0.0;            // only for chebyshev/elliptical
coeffs = CalcIIRFilterCoeff(fparams);

this gives

Can anyone explain why the relationship between number of poles and filter order is different in the two programs? I'm assuming both of them are correct so what is the right way to interpret the outputs?

• If the resulting filters are equal then maybe latter just decide to implement it that way ... Sep 3, 2020 at 5:29