Good morning,
I encounter the following problem (In my job) :
Using a microcontroller, I sample a signal comming from a microphone at the sampling frequency of 16KHz. This signal goes through a hardware preampli. I get a buffer of 250 samples at the output.
An algorithm computes statistics on this buffer, but this one is disturbed by the presence of a 50Hz signal mixed with the noise recorded by the microphone.
I would like to realize a numeric filter on the buffer in order to remove the 50Hz (Or 60Hz depending on the country). I studied numeric filtering 15 years ago, I remember that we managed to synthetize RIF filter using Matlab (Choosing a window, the filter order an so on...) and that we managed to obtain coefficients that. I also remeber that we managed to implement this filter on a DSP.
Now, I do not remember the method, I do not rememeber how to obtain the coefficients and I do not rememebr how to implement this kind of filter practically...
Does anyone knows how to do it please ? And does anyone could explain me the method in detail and how to get the coefficients of the filter ? Moreover, could you please explain me how to implement this filter practically ?
If anyone has good knowledges on numeric filtering, thank you by advance for your help on this subject.
I wish you a good day, best regards.
Thomas TRUILHE
Numeric Filter Synthesis : CutOff Frequency 50Hz (Or 60Hz)
-
- Posts: 232
- Joined: Thu Jul 14, 2022 5:15 am
-
- Posts: 10
- Joined: Sat Feb 22, 2025 7:21 pm
Re: Numeric Filter Synthesis : CutOff Frequency 50Hz (Or 60Hz)
I am also interested in doing this on an esp, and have been looking at the esp-dsp component. I have not done any more than look at esp-dsp so far, but I have been playing with filtering in python as a precursor. You could also use matlab if you pay for it, or the free clone octave, but I prefer python. Using the jupyter notebook extension in vscode makes it really easy to paste code snippets and run quickly.
As a quick example from chatgpt (I find that chatgpt and copilot both generate pretty good python code snippets to play quickly):
You can get the coefficients from the returned b,a transfer function polynomials. This example applies the filter with filtfilt, which does a forward/backward "zero-phase" application, as opposed to the lfilter standard application. You can try it both ways.
Actually, for a notch, you probably want a pretty high order, and the previous approach can lead to numerical instability (especially when ported to an embedded controller using single-precision float or integer dsp code). I have not gone further with the iir code, but using scipy.butter I have been moving away from the standard transfer-function (b,a) approach to their "sos" (second-order-sections) options. This is a cascade of biquads which are numerically happy, and high orders are just a chain.
Anyway, I have no concrete example for you but I am on a similar path and interested in this discussion.
BTW, at fs=16kHz, 250 samples is only 15.6 ms of signal, not close to even one cycle of 50 Hz (20ms). Perhaps you want bigger buffers.
As a quick example from chatgpt (I find that chatgpt and copilot both generate pretty good python code snippets to play quickly):
- import numpy as np
- import matplotlib.pyplot as plt
- from scipy import signal
- # Sampling rate (Hz)
- fs = 1000
- # Notch filter frequency (60 Hz)
- f_notch = 60
- # Quality factor (controls the width of the notch)
- Q = 30.0
- # Design the notch filter
- b, a = signal.iirnotch(f_notch, Q, fs)
- # Create a signal that contains 60 Hz noise
- t = np.linspace(0, 1, fs, endpoint=False) # 1 second
- signal_with_noise = np.sin(2 * np.pi * 5 * t) + 0.5 * np.sin(2 * np.pi * f_notch * t) # 5 Hz signal + 60 Hz noise
- # Apply the notch filter to the noisy signal
- filtered_signal = signal.filtfilt(b, a, signal_with_noise)
- # Plot the original and filtered signals
- plt.figure(figsize=(10, 6))
- # Plot the original signal
- plt.subplot(2, 1, 1)
- plt.plot(t, signal_with_noise)
- plt.title('Original Signal with 60 Hz Noise')
- plt.xlabel('Time [s]')
- plt.ylabel('Amplitude')
- # Plot the filtered signal
- plt.subplot(2, 1, 2)
- plt.plot(t, filtered_signal)
- plt.title('Filtered Signal (60 Hz Notch Filter Applied)')
- plt.xlabel('Time [s]')
- plt.ylabel('Amplitude')
- plt.tight_layout()
- plt.show()
Actually, for a notch, you probably want a pretty high order, and the previous approach can lead to numerical instability (especially when ported to an embedded controller using single-precision float or integer dsp code). I have not gone further with the iir code, but using scipy.butter I have been moving away from the standard transfer-function (b,a) approach to their "sos" (second-order-sections) options. This is a cascade of biquads which are numerically happy, and high orders are just a chain.
Anyway, I have no concrete example for you but I am on a similar path and interested in this discussion.
BTW, at fs=16kHz, 250 samples is only 15.6 ms of signal, not close to even one cycle of 50 Hz (20ms). Perhaps you want bigger buffers.
Who is online
Users browsing this forum: sysprogs and 84 guests