Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Extract coefficients from IIR filter #4

Open
sylvanoMTL opened this issue Sep 17, 2021 · 2 comments
Open

Extract coefficients from IIR filter #4

sylvanoMTL opened this issue Sep 17, 2021 · 2 comments

Comments

@sylvanoMTL
Copy link

Hi there,
I see the implementation require high knowledge of C++ coding. I have been through the example of the Butterworth filter, and I am keen on getting the b and a coefficients to compare with an algorithm I have developed on another platform.
Do you know a simple method to extract them?

Also can you confirm the filter is only specified by the cut-off frequency? (i.e. no pass band ripple, stop band attenuation?

Thank you
Sylvano

@tttapa
Copy link
Owner

tttapa commented Sep 19, 2021

The butter_coeff function returns the coefficients as a list of second-order sections (SOS). You can then use the sos2tf function to convert these SOS coefficients to a rational transfer function, see the TransferFunction class, it has b and a members you can access.

For example:

#include <Filters.h>

#include <Filters/Butterworth.hpp>

// Sampling frequency
const double f_s = 100; // Hz
// Cut-off frequency (-3 dB)
const double f_c = 25; // Hz
// Normalized cut-off frequency
const double f_n = 2 * f_c / f_s;

// Sixth-order Butterworth filter
auto butter_sos = butter_coeff<6>(f_n);
auto butter_tf = sos2tf(butter_sos);

void setup() {
  Serial.begin(115200);
  while (!Serial);
  Serial << setprecision(7);
  Serial << "fₙ: " << f_n << endl;
  Serial << "b:  " << butter_tf.b << endl;
  Serial << "a:  " << butter_tf.a << endl;
}

void loop() {}

Prints:

fₙ: 0.5000000
b:  0.0295882, 0.1775293, 0.4438233, 0.5917644, 0.4438233, 0.1775293, 0.0295882
a:  1.0000000, 0.0000000, 0.7776959, 0.0000000, 0.1141994, 0.0000000, 0.0017509

You can compare them to the coefficients generated by SciPy, for example:

from scipy.signal import butter
f_s = 100 # Hz, Sampling frequency
f_c = 25 # Hz, Cut-off frequency (-3 dB)
f_n = 2 * f_c / f_s # Normalized cut-off frequency
b, a = butter(6, f_n)
print('b:', ', '.join(map(lambda x: f'{x:10.7f}', b)))
print('a:', ', '.join(map(lambda x: f'{x:10.7f}', a)))

Prints:

b:  0.0295882,  0.1775293,  0.4438234,  0.5917645,  0.4438234,  0.1775293,  0.0295882
a:  1.0000000, -0.0000000,  0.7776960, -0.0000000,  0.1141994, -0.0000000,  0.0017509

A Butterworth filter has no ripple, apart from the filter order, the cut-off frequency is the only parameter, see https://tttapa.github.io/Pages/Mathematics/Systems-and-Control-Theory/Analog-Filters/Butterworth-Filters.html#mjx-eqn-8.

@sylvanoMTL
Copy link
Author

Great thank you for your prompt reply and the additional precisions. I have been confused by the MATLAB designfilt GUI. But it seems all make sense to me now.
regards
Sylvain

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants