An update about my Code

2 次查看(过去 30 天)
Danny
Danny 2025-3-19
I decided on focusing on the magnitude where I do the normalization on low and high pass and have the bandpass as dB(dB(decibel), with frequency cutoff, I manage to get accurate but I have trouble in managing the frequency cutoff accurate. As such I need help.
My Code:
% Define frequency range for the plot
f = logspace(1, 5, 500); % Frequency range from 10 Hz to 100 kHz
w = 2*pi*f; % Angular frequency
% Parameters for the filters (you can modify these)
R = 1e3; % Resistance in ohms (1 kOhm)
C = 1e-6; % Capacitance in farads (1 uF)
L = 10e-3; % Inductance in henries (10 mH)
% Transfer function for Low-pass filter: H_low = 1 / (1 + jωRC)
H_low = 1 ./ (1 + 1i*w*R*C);
% Transfer function for High-pass filter: H_high = jωRC / (1 + jωRC)
H_high = 1i*w*R*C ./ (1 + 1i*w*R*C);
% Transfer function for Band-pass filter: H_band = jωRC / (1 + jωL/R + jωRC)
H_band = 1i*w*R*C ./ (1 + 1i*w*L/R + 1i*w*R*C);
% Calculate the cutoff frequency where the gain is 0.707 (about -3 dB)
f_cutoff_RC = 1 / (2 * pi * R * C); % Cutoff frequency for RC filters (Low-pass and High-pass)
% Normalize the gain for Low-pass and High-pass filters: Normalize the maximum gain to 1
H_low_normalized = abs(H_low) / max(abs(H_low)); % Normalize low-pass filter gain
H_high_normalized = abs(H_high) / max(abs(H_high)); % Normalize high-pass filter gain
% Find the frequency where the gain is 0.707 for both filters
% This is where the magnitude |H(f)| = 1 / sqrt(2) = 0.707
% Low-pass filter cutoff is at f_cutoff_RC where |H_low(f_cutoff)| = 0.707
% High-pass filter cutoff is at f_cutoff_RC where |H_high(f_cutoff)| = 0.707
% For Band-pass filter, calculate lower and upper cutoff frequencies
f_lower_cutoff = 1 / (2 * pi * sqrt(L * C)); % Lower cutoff frequency for Band-pass
f_upper_cutoff = 1 / (2 * pi * sqrt(L * C)); % Upper cutoff frequency for Band-pass
% Plot magnitude responses
figure;
% Plot for Low-pass Filter (Normalized Gain)
subplot(3,1,1);
semilogx(f, H_low_normalized); % Low-pass filter normalized magnitude response
hold on;
% Mark the cutoff value where gain = 0.707 (at cutoff for low-pass)
line([f_cutoff_RC f_cutoff_RC], ylim, 'Color', 'r', 'LineStyle', '--'); % Cutoff frequency for Low-pass
text(f_cutoff_RC, 0.7, ['Cutoff: ' num2str(f_cutoff_RC, '%.2f') ' Hz'], ...
'HorizontalAlignment', 'left', 'VerticalAlignment', 'bottom');
title('Magnitude Response of Low-pass Filter (Normalized)');
xlabel('Frequency (Hz)');
ylabel('Magnitude (Normalized Gain)');
grid on;
legend('Low-pass Filter', ['Cutoff Frequency = ' num2str(f_cutoff_RC, '%.2f') ' Hz']);
hold off;
% Plot for High-pass Filter (Normalized Gain)
subplot(3,1,2);
semilogx(f, H_high_normalized); % High-pass filter normalized magnitude response
hold on;
% Mark the cutoff value where gain = 0.707 (at cutoff for high-pass)
line([f_cutoff_RC f_cutoff_RC], ylim, 'Color', 'r', 'LineStyle', '--'); % Cutoff frequency for High-pass
text(f_cutoff_RC, 0.7, ['Cutoff: ' num2str(f_cutoff_RC, '%.2f') ' Hz'], ...
'HorizontalAlignment', 'left', 'VerticalAlignment', 'bottom');
title('Magnitude Response of High-pass Filter (Normalized)');
xlabel('Frequency (Hz)');
ylabel('Magnitude (Normalized Gain)');
grid on;
legend('High-pass Filter', ['Cutoff Frequency = ' num2str(f_cutoff_RC, '%.2f') ' Hz']);
hold off;
% Plot for Band-pass Filter (dB Scale)
subplot(3,1,3);
semilogx(f, 20*log10(abs(H_band))); % Band-pass filter magnitude response in dB
hold on;
line([f_lower_cutoff f_lower_cutoff], ylim, 'Color', 'r', 'LineStyle', '--'); % Lower cutoff for Band-pass
line([f_upper_cutoff f_upper_cutoff], ylim, 'Color', 'g', 'LineStyle', '--'); % Upper cutoff for Band-pass
% Mark lower and upper cutoff values for the Band-pass filter
text(f_lower_cutoff, max(20*log10(abs(H_band))) - 3, ['Lower Cutoff: ' num2str(f_lower_cutoff, '%.2f') ' Hz'], ...
'HorizontalAlignment', 'left', 'VerticalAlignment', 'bottom');
text(f_upper_cutoff, max(20*log10(abs(H_band))) - 3, ['Upper Cutoff: ' num2str(f_upper_cutoff, '%.2f') ' Hz'], ...
'HorizontalAlignment', 'left', 'VerticalAlignment', 'bottom');
title('Magnitude Response of Band-pass Filter (dB)');
xlabel('Frequency (Hz)');
ylabel('Magnitude (Gain in dB)');
grid on;
legend('Band-pass Filter', ...
['Lower Cutoff = ' num2str(f_lower_cutoff, '%.2f') ' Hz'], ...
['Upper Cutoff = ' num2str(f_upper_cutoff, '%.2f') ' Hz']);
hold off;

回答(1 个)

Mathieu NOE
Mathieu NOE 2025-3-31
hello Danny
that looks quite similar to another answer of mine :
see below your code fixed . The main problem IMHO is that the bandpass filter equation was wrong (basically the inductor and capacitor where soing the same function) , so I corrected it, assuming this is a classical 1st oder serial implementation like this :
NB you can see below the comparsion between the theoretical (approximated) cut offf frequencies vs the "true" ones from the magnitude plot (needed some extra function implemented at the bottom of your code)
code :
% Define frequency range for the plot
f = logspace(1, 5, 500); % Frequency range from 10 Hz to 100 kHz
w = 2*pi*f; % Angular frequency
% Parameters for the filters (you can modify these)
R = 1e3; % Resistance in ohms (1 kOhm)
C = 1e-6; % Capacitance in farads (1 uF)
L = 10e-3; % Inductance in henries (10 mH)
% Transfer function for Low-pass filter: H_low = 1 / (1 + jωRC)
H_low = 1 ./ (1 + 1i*w*R*C);
% Transfer function for High-pass filter: H_high = jωRC / (1 + jωRC)
H_high = 1i*w*R*C ./ (1 + 1i*w*R*C);
% % Transfer function for Band-pass filter: H_band = jωRC / (1 + jωL/R + jωRC)
% H_band = 1i*w*R*C ./ (1 + 1i*w*L/R + 1i*w*R*C);
% Transfer function for Band-pass filter: H_band = 1 / (1 + jωL/R + 1/jωRC)
H_band = 1 ./ (1 + 1i*w*L/R + 1./(1i*w*R*C));
% Calculate the cutoff frequency where the gain is 0.707 (about -3 dB)
f_cutoff_RC = 1 / (2 * pi * R * C); % Cutoff frequency for RC filters (Low-pass and High-pass)
% Normalize the gain for Low-pass and High-pass filters: Normalize the maximum gain to 1
H_low_normalized = abs(H_low) / max(abs(H_low)); % Normalize low-pass filter gain
H_high_normalized = abs(H_high) / max(abs(H_high)); % Normalize high-pass filter gain
% Find the frequency where the gain is 0.707 for both filters
% This is where the magnitude |H(f)| = 1 / sqrt(2) = 0.707
% Low-pass filter cutoff is at f_cutoff_RC where |H_low(f_cutoff)| = 0.707
% High-pass filter cutoff is at f_cutoff_RC where |H_high(f_cutoff)| = 0.707
% For Band-pass filter, calculate lower and upper cutoff frequencies
% f_lower_cutoff = 1 / (2 * pi * sqrt(L * C)); % Lower cutoff frequency for Band-pass
% f_upper_cutoff = 1 / (2 * pi * sqrt(L * C)); % Upper cutoff frequency for Band-pass
f_resonance = 1 / (2 * pi * sqrt(L * C)); % resonance frequency for Band-pass
f_lower_cutoff_theoretical = 1 / (2 * pi * R * C) % Lower cutoff frequency for Band-pass
f_lower_cutoff_theoretical = 159.1549
f_upper_cutoff_theoretical = 1 / (2 * pi * L / R) % Upper cutoff frequency for Band-pass
f_upper_cutoff_theoretical = 1.5915e+04
% "true" values obtained from H_band magnitude plot
[f_lower_cutoff,f_upper_cutoff] = find_zc(f,abs(H_band),0.7) % find both -3 dB cut off frequencies
f_lower_cutoff = 154.5408
f_upper_cutoff = 1.6392e+04
% Plot magnitude responses
figure;
% Plot for Low-pass Filter (Normalized Gain)
subplot(3,1,1);
semilogx(f, H_low_normalized); % Low-pass filter normalized magnitude response
hold on;
% Mark the cutoff value where gain = 0.707 (at cutoff for low-pass)
line([f_cutoff_RC f_cutoff_RC], ylim, 'Color', 'r', 'LineStyle', '--'); % Cutoff frequency for Low-pass
text(f_cutoff_RC, 0.7, ['Cutoff: ' num2str(f_cutoff_RC, '%.2f') ' Hz'], ...
'HorizontalAlignment', 'left', 'VerticalAlignment', 'bottom');
title('Magnitude Response of Low-pass Filter (Normalized)');
xlabel('Frequency (Hz)');
ylabel('Magnitude (Normalized Gain)');
grid on;
legend('Low-pass Filter', ['Cutoff Frequency = ' num2str(f_cutoff_RC, '%.2f') ' Hz']);
hold off;
% Plot for High-pass Filter (Normalized Gain)
subplot(3,1,2);
semilogx(f, H_high_normalized); % High-pass filter normalized magnitude response
hold on;
% Mark the cutoff value where gain = 0.707 (at cutoff for high-pass)
line([f_cutoff_RC f_cutoff_RC], ylim, 'Color', 'r', 'LineStyle', '--'); % Cutoff frequency for High-pass
text(f_cutoff_RC, 0.7, ['Cutoff: ' num2str(f_cutoff_RC, '%.2f') ' Hz'], ...
'HorizontalAlignment', 'left', 'VerticalAlignment', 'bottom');
title('Magnitude Response of High-pass Filter (Normalized)');
xlabel('Frequency (Hz)');
ylabel('Magnitude (Normalized Gain)');
grid on;
legend('High-pass Filter', ['Cutoff Frequency = ' num2str(f_cutoff_RC, '%.2f') ' Hz']);
hold off;
% Plot for Band-pass Filter (dB Scale)
subplot(3,1,3);
semilogx(f, 20*log10(abs(H_band))); % Band-pass filter magnitude response in dB
hold on;
line([f_lower_cutoff f_lower_cutoff], ylim, 'Color', 'r', 'LineStyle', '--'); % Lower cutoff for Band-pass
line([f_upper_cutoff f_upper_cutoff], ylim, 'Color', 'g', 'LineStyle', '--'); % Upper cutoff for Band-pass
% Mark lower and upper cutoff values for the Band-pass filter
text(f_lower_cutoff, max(20*log10(abs(H_band))) - 3, ['Lower Cutoff: ' num2str(f_lower_cutoff, '%.2f') ' Hz'], ...
'HorizontalAlignment', 'left', 'VerticalAlignment', 'bottom');
text(f_upper_cutoff, max(20*log10(abs(H_band))) - 3, ['Upper Cutoff: ' num2str(f_upper_cutoff, '%.2f') ' Hz'], ...
'HorizontalAlignment', 'left', 'VerticalAlignment', 'bottom');
title('Magnitude Response of Band-pass Filter (dB)');
xlabel('Frequency (Hz)');
ylabel('Magnitude (Gain in dB)');
grid on;
legend('Band-pass Filter', ...
['Lower Cutoff = ' num2str(f_lower_cutoff, '%.2f') ' Hz'], ...
['Upper Cutoff = ' num2str(f_upper_cutoff, '%.2f') ' Hz']);
hold off;
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function [ZxP,ZxN] = find_zc(x,y,threshold)
% put data in rows
x = x(:);
y = y(:);
% positive slope "zero" crossing detection, using linear interpolation
y = y - threshold;
zci = @(data) find(diff(sign(data))>0); %define function: returns indices of +ZCs
ix=zci(y); %find indices of + zero crossings of x
ZeroX = @(x0,y0,x1,y1) x0 - (y0.*(x0 - x1))./(y0 - y1); % Interpolated x value for Zero-Crossing
ZxP = ZeroX(x(ix),y(ix),x(ix+1),y(ix+1));
% negative slope "zero" crossing detection, using linear interpolation
zci = @(data) find(diff(sign(data))<0); %define function: returns indices of +ZCs
ix=zci(y); %find indices of + zero crossings of x
ZeroX = @(x0,y0,x1,y1) x0 - (y0.*(x0 - x1))./(y0 - y1); % Interpolated x value for Zero-Crossing
ZxN = ZeroX(x(ix),y(ix),x(ix+1),y(ix+1));
end

类别

Help CenterFile Exchange 中查找有关 Multirate and Multistage Filters 的更多信息

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!

Translated by