Contents
- Introduction
- Filter Transfer Function
- Step Response
- Matlab Filter
- Simulink Filter
- Measuring the Actual Filter
- Comparison of Real vs Simulation
- Filter System Identification
- Conclusion
- Sources
What do Starbucks, airliners, and stock markets have in common? Filtering! Filtering is essential for making coffee as well as many scientific and engineering applications. For control systems, you want to reject noise that might not be useful, for example, an airliner should ignore small changes due to turbulence so as not to overcontrol the aircraft and drive it into an undesirable oscillation. Financial analysts also use filtering to smooth out noise in a time-series price dataset. In this article, I will introduce a simple low-pass filter. In this article we will look at simulating the expected responses before testing it in hardware. Finally, we will measure our actual filter and reverse the process to build a very basic data-driven model that we can use for future analysis and simulation.
Introduction
In this filter design, we use a resistor and a capacitor to make a low-pass filter. It is one of the common first-order filters used in passive electronics. Because this filter design only has one reactive component, this filter is considered a first-order filter. The input voltage to this filter is applied in series to the resistor, and the output voltage is taken across the capacitor.
Capacitive reactance is the resistance to the change of voltage across a component. It is inversely proportional to the frequency applied to the circuit, which means that at low frequencies, the voltage drop is small, and the voltage potential is large. At a high frequency, the voltage drop is very high, and the voltage potential is less. We use this mechanism to drive the low-pass behavior of the low-pass filter circuit by this specific arrangement of a resistor and capacitor.
In the next section, we will go into how to calculate the transfer function of the filter.
Filter Transfer Function
As our filter is designed to operate on frequencies, we can use the frequency response of the ideal resistor and capacitor to determine the frequency-domain transfer function of the filter. This makes it easier to design the filter as well as analyze its performance. The frequency domain is represented by a complex number, therefore we use the complex impedance for our circuit elements. The complex impedance for our resistor is
$$Z_R(s)=R$$
and the complex impedance equation for our capacitor is
$$Z_C(s)=\frac{1}{Cs}$$
When we arrange the impedances for the filter, we can see that the output impedance is simply the impedance of the capacitor, and the input impedance is the impedance of the resistor plus the impedance of the capacitor.
This allows us to make an equation for the input \(U(s)\)and the output \(Y(s)\) of the filter.
$$\begin{matrix}
U(s)=Z_R+Z_C \\
Y(s)=Z_C
\end{matrix}$$
Therefore our transfer function for the entire filter becomes
$$\frac{Y(s)}{U(s)}=\frac{Z_c}{Z_r+Z_c}=\frac{\frac{1}{Cs}}{R+\frac{1}{Cs}}$$
We can simplify this by multiplying the entire function by \(\frac{Cs}{Cs}\) to get
$$\frac{Y(s)}{U(s)}=\frac{1}{RCs+1}$$
Step Response
The step response of an RC filter is a decaying exponential with the time constant of \(RC\). The slope of the output function is \(\frac{1}{\tau}\) imediately after the step input, and the output settles to a final value of 1.
Matlab RC Filter
We can use Matlab to analyze the expected response of our filter and see how it compares with the measured response. We will use our resistor and capacitor values to implement the transfer function of our system
$$\begin{matrix}
\tau=RC \\
G(s)=\frac{1}{\tau s+1}
\end{matrix}$$
First we save our resistor and capacitor values as our filter parameters.
% Filter Parameters
R=220 % 220 Ohm Resistor
C=1e-7 %0.1 uF Capacitor
Next we can set the transfer function for our system. First we initialize the variable \(s\) as a continous transfer function using the tf() function.
% Transfer function
s=tf('s')
By doing this we can build up any transfer function that we want by just expressing it as a function of \(s\). Now we can generate our function \(G(s)\)
tau=R*C %Time constant
G=1/(tau*s+1)
To view the Bode plot we can use the bode() function
% Bode Plot
bode(G)
By default the units of frequency are rad/s but we would like to see it in Hz. Right click on one of the plots and select ‘Properties’. In the units tab change the frequency units to Hz.
We can see that at 1Khz, there is almost no signal attenuation and the phase angle is around -8 degrees.
Our cutoff frequency is around 7.3kHz with a phase angle of -45 degrees.
Looking at a 10Khz signal we can see that we have passed the cutoff frequency because the magnitude is attenuated past the 3dB level. The phase angle is around -54 degrees.
We can also view the step response
% Step Response
step(G)
From this plot it looks like the rise time of our filter is around 50us.
Now that we know what to expect of our filter system, let’s try to simulate what we might see when we hook up the oscilloscope.
Simulink Filter Model
When you open up Matlab, Click on the Simulink Icon on the home toolbar.
This brings you to the Simulink start page. Click on “Blank Model” to open up a new blank model.
Your Simulink model then opens up in a new window.
If you double-click in the main workspace you open up a block search tool. Type “scope” and select the block from the ‘Simulink/Sinks’ library as shown below the block name. You should now see the scope block in the workspace.
Next add a sine wave source block using the same method. Search for “Sine Wave” from the “Simulink/Sources” library and add the block to the workspace.
Next connect the output of the sine wave block to the input of the scope block by clicking and dragging from the sine wave to the source blocks. You should have something that looks like this.
Double clicking on the scope block will open up the scope in a new window.
From here we can run a simulation by clicking the green play circle.
Our result should be a sine wave.
Now that we can view our input signal, let’s view the results when we add our filter. First we need to add another input to the scope block so that we can view the input and output at the same time. Select ‘Configuration Properties’ from the ‘View’ dropdown menu. From her eyou can change the number of imports to the block. Let’s change it to 2.
Next Press ‘Ok’ and then close out of our scope window. Add a new block ‘Transfer Fcn’ from the ‘Simulink/Continuous’ library.
Connect the output of the transfer function to the second input of the scope, and connect the input of the transfer function to the line between the sine wave block and the scope block.
Now open the scope and click the green ‘Run’ button on the top to see the result. If the legend isn’t showing click on ‘Legend’ from the ‘View’ menu. We can see the output of our transfer function along with the input from our sine wave source. We can see that the output signal is attenuated and there is a time delay. This is expected behavior for a low-pass RC filter system.
If we want to check the step response of our filter we can add a step input to our model. Search for the ‘Step’ block and the ‘Manual Switch’ block and add them into our workspace.
We can then rearrange our sine and step sources to connect to the input of the switch as shown below. We can double-click on the switch block to change the imput from the sine to the step function.
Open up the scope and run the simulation again with the step function as the input. You should get something that looks like this.
This is our standard step response for a first order filter. Now we can use our filter coefficients that we determined before to simulate the actual response of our circuit. We can open up the block parameters for our transfer function and plug in the transfer function for our expected filter. As we found before our time constant was \(\tau=2.2e^{-5}\) we can put that into our denominator coefficient.
We need to modify the block parameters for our step function as well because the default block doesn’t start the step until 1 second has passed. Open up the block parameters for the steop block and change the initial value to 1. This eliminates the time delay for the signal.
Now, in the simulation bar at the top, change the stop time to 0.0003s.
Open up the scope and run the simulation again.
We can see that our simulated filter rises to the input value in a little under 100us. This tracks with the value that we calculated in the first Matlab section. Remember this plot, as we’re going to compare it with the actual oscilloscope trace. Now let’s switch the input to the sine wave.
We will be testing a few frequencies for the input sine wave signals. The sine wave block uses frequency in rad/s so we first need to convert all of our setpoints.
frequency (Hz) | frequency (rad/s) |
---|---|
100hz | 628.3 |
200hz | 1257 |
1kHz | 6238 |
2kHz | 12566 |
10 kHz | 62832 |
20 kHz | 125664 |
100 kHz | 628319 |
200 kHz | 1.257e6 |
When we open up the parameters of the sine wave block we can set our desired frequency.
For our first frequency of 100hz we can see that there is almost no attenuation and a very small phase delay.
Looking at the 200hz input signal we see almost the same
For the 1kHz signal lets reduce our simulation time to 0.001s to avoid cluttering the scope screen. When we run this signal through our system we can see that there is a very slight attenuation but the phase delay is much more pronounced.
The 2kHz signal shows more attenuation and phase delay.
Once again we reduce our simulation time to 0.0001 for the 10kHz signal and we can see that there is significant attenuation and a large phase delay.
A 20 kHz signal give us even more attenuation and phase delay.
Further reducing our simulation timestep to 0.00002s we can see that the 100 kHz signal is almost entirely suppressed.
And same with the 200 kHz signal.
Now that we know what to expect from the oscilloscope readout, we can breadboard the actual filter and examine its response.
Measuring the Actual Filter
Next, we breadboard out an actual filter using the earlier capacitor values. (220 Ohm Resistor and 0.1 uF Capacitor)
It’s hard to see from this rats nets of wires, but I have a function generator hooked up to the input of the filter via the alligator clips, and I have two oscilloscope probes. One is measuring the input signal from the function generator, and the other is connected across the output capacitor.
Let’s look at a step input for our filter. We can view this on the oscilloscope by using a square wave as the input to our filter.
We can see that our rise time for the filter is a little bit below 100us. This tracks with the expected values.
Now let’s go through our desired frequencies and record the measurements for amplitude and phase that we got from the oscilloscope. For these images, the pink signal in Channel 2 is the input sine wave, and the yellow signal in channel 1 is the output of our filter.
When we look at the 100KhZ signal we can see that there is almost no attenuation or phase delay.
For the 200Hz signal there also doesn’t seem to be any noticeable attenuation or delay.
When we switch to the 1Khz signal we can see that there is a noticeable phase delay and a slight attenuation.
With the 2khz signal there is more delay and more attenuation.
Jumping to the 10khz signal we can see a significant attenuation and phase delay in the filtered signal.
The 20khz signal shows even more attenuation and delay. If we were to go back to the simulink section we can see that these oscilloscope readings match with our simulation.
For the 100khz signal, the filter almost completely supresses the signal.
And same for the 200khz signal.
From these measured points we can make a graph of the bode plot of our actual filter to compare it to our simulated filter.
Frequency | Amplitude | Phase |
---|---|---|
100 Hz | 388mv | 2.93 |
200 Hz | 380mv | 3.36 |
1 kHz | 364mv | 12.55 |
2 kHz | 344mv | 18.01 |
10 kHz | 148mv | 57.72 |
20 kHz | 68mv | 62.91 |
100 kHz | 10mv | 143.97 |
200 kHz | 4mv | N/A |
With this data we can compare the frequency response of the actual filter with our simulated data.
Comparison of Real and Simulated Filter
We can extract individual points for our magnitude and phase data for the ideal filter by setting a return value for the bode() function in matlab.
% Bode Plot
[mag,phase,wout] = bode(G)
Next we have to put our measured data into vectors so that we can plot it agains the simulated data. The magnitude of our measured data is a voltage so we have to normalize it into a range between 0 and 1 with our highest voltage of 388 corresponding to 1. We also will need to shift the frequency array wout_r by 10 to match it up with the bode plot.
% measured filter
mag_r = [388;380;364;344;148;68;10;4];
mag_r=mag_r/388;
phase_r=[2.93;3.36;12.55;18.01;57.72;62.91;143.97;143.97];
wout_r=[100;200;1e3;2e3;1e4;2e4;1e5;2e5];
wout_r=wout_r*10;
We can use the subplot() function to make our own bode plots comparing the simulated data with our measured data. The bode plots are a semi-log plot so we need to change the x-axis scaling to logarithmic. I will also add a legend and change the plot marker to plusses instead of circles.
% measured vs simulated bode plot
figure %magnitude
subplot(2,1,1)
scatter(wout_r, mag2db(mag_r),'+')
set(gca,'xscale','log')
hold on;
semilogx(wout, mag2db(mag(:)))
legend(['Measured'],['Simulated'])
title('Magnitude (dB)')
xlabel('Frequency (Hz)')
ylabel('Magnitude')
subplot(2,1,2)
scatter(wout_r,-phase_r,'+')
set(gca,'xscale','log')
hold on;
semilogx(wout,phase(:))
legend(['Measured'],['Simulated'])
title('Phase')
xlabel('Frequency (Hz)')
ylabel('Phase (deg)')
This gives us our comparison. We can see that the measurements follow the simulations pretty well, except for the phase angle at the higher frequencies.
We can then use matlab to estimate the transfer function of the actual RC filter system from our test data.
Filter System Identification
To identify the system we need to use 2 main matlab functions, idfrd(), and tfest().
First we need to convert our measured filter response data into a single array of complex response variables. We can do this by using the following equation to reduce our two arrays of magnitude and phase into a single array of complex numbers.
$$C=magnitude\cdot e^{(j\cdot phase\cdot\frac{pi}{2})}$$
We can do this with the following matlab code:
response = mag_r.*exp(1j*-phase_r*pi/180) % complex variable response
The idfrd() function creates a data structure that stores the frequency response as a complex value over a range of frequencies. To do this we use the following code:
frdata = idfrd(response,wout_r,0) % change to frequency data
This takes our previously calcuated complex freuqency response, the measured frequency data wout_r, and a ‘0’ to represent a continuous time system. Next we use the tfest() function to estimate the transfer function that created this data. The inputs to this function is the array of complex responses, the number of poles in the expected transfer function, and the number of zeros in the expected transfer function. Because we know that our system is a first-order low-pass filter, we use a single pole and no zeros for our transfer function.
sys1 = tfest(frdata,1,0) % estimate transfer function
From the output of this function we can see that it uses a different form of the transfer function than we used at the beginning of this article.
We want to get this in terms of the time constant \(RC\) therfore we can normalize it by dividing by the value in the numerator.
$$G(s)=\frac{\frac{4.635e04}{4.635e04}}{\frac{s}{4.825e04}+\frac{4.635e04}{4.635e04}}=\frac{1}{\frac{1}{4.825e04}s+1}$$
The value of \(\frac{1}{4.825e04}\) is our time constant \(RC=2.157e^{-05}\) which is very close to the ideal value of \(2.2e^{-5}\) from the matalb simulation at the beginning of the article. Therefore, using the measured frequency response data from our oscilloscope we estimate the transfer function for our filter system to be.
$$G(s)=\frac{1}{2.157\times10^{-5}s+1}$$
Conclusion
Although a single-pole low-pass filter is a very simple system, it is a good problem for introducing engineers to system identification and frequency design. This article has gone through all the important stages of system design. We started with the mathematical model of our ideal system; we then examined that system using numerical tools and verified our results with hand calculations. After that, we built the system using physical hardware and tested it to compare it with our model. Finally, we used the data gathered from the tests to update our model and accurately represent the actual physical system. System Identification is a very powerful tool because if we ever were to use this specific filter in a larger design, we now have a data-driven model that we can use later.
Sources
Administrator. “First Order and Second Order Passive Low Pass Filter Circuits.” Electronics Hub (blog), January 17, 2019. https://www.electronicshub.org/passive-low-pass-rc-filters/.
“First-Order Systems: The Happy Family – Jason Sachs.” Accessed January 25, 2023. https://www.embeddedrelated.com/showarticle/590.php.