
An update about my Code
2 次查看(过去 30 天)
显示 更早的评论
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;
0 个评论
回答(1 个)
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_upper_cutoff_theoretical = 1 / (2 * pi * L / R) % Upper cutoff frequency for Band-pass
% "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
% 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 Center 和 File Exchange 中查找有关 Multirate and Multistage Filters 的更多信息
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!