1. Overview

Since every periodic waveform is a sum of sinusoids, sinusoidal waveforms can be “extracted” from periodic signals. Below, we show how to

  1. Generate a square wave from a sum of sinusoids

  2. Design an active second-order low-pass filter

  3. Use the filter to synthesize a (near) sinusoidal waveform from a square wave by attenuating all but one spectral component

2. Square Wave

Any periodic function can be represented as a sum of sinusoids. In Figure 1, the top panel shows two sinusoids. The bottom panel shows the result of adding them up. While not perfect, the resulting trace has a resemblance to a square-wave.

N filter 0
Figure 1. Approximation of square-wave with two sinusoids

Increasing the number of sinusoids improves the approximation. Figure 2 shows the result of summing six sinusoids.

N filter 1
Figure 2. Approximation of square-wave with six sinusoids

3. Low-Pass Filter

filter
Figure 3. Second-order Low-pass filter circuit

Frequency response:

\[H_{LPF}(s) = - \frac{G}{ \left(\frac{s}{\omega_o}\right)^2 + \frac{s}{Q \cdot \omega_o} + 1}\]

with corner frequency \(\omega_o = 2\pi f_c\). The variable \(s\) denotes complex frequency, \(s = j \omega\) and \(\omega = 2\pi f\).

Design Equations
\[\begin{gather} G = \frac{R_2}{R_1} \\ f_c = \frac{1}{2\pi\sqrt{R_2 R_3 C_1 C_2}} \\ Q = \sqrt{\frac{C_2}{C_1}} \frac{1}{ \frac{\sqrt{R_2 R_3}}{R_1} + \sqrt{\frac{R_3}{R_2}} + \sqrt{\frac{R_2}{R_3}} } \end{gather}\]

Design objective:

Gain G

0.15

Cutoff frequency fc

1.0 kHz

Quality factor Q

0.9

Circuit parameters as calculated and rounded to “standard” (readily available) component values:

Parameter calculated rounded

R1

154 kΩ

150 kΩ

R2

23 kΩ

22 kΩ

R3

50 kΩ

47 kΩ

C1

10.0 nF

10 nF

C2

2.2 nF

2.2 nF

Gain G

0.15

0.15

Cutoff frequency fc

1.00 kHz

1.06 kHz

Quality factor Q

0.90

0.90

Bode plot[1]:

from scipy import signal

# Response with actual component values
wo = 2*pi*fc
num = [1]
den = [1/wo**2, 1/Q/wo, 1]

tf = signal.TransferFunction(num,den)

w = 2*pi*logspace(2, 4, num=100)
w, mag, _ = tf.bode(w)

semilogx(w/2/pi, mag)
ylabel("Magnitude  [dB]")
xlabel("Frequency  [Hz]")
N filter 2
Figure 4. Normalized filter response for calculated and rounded component values.

4. Time Domain Response

Figure 5 shows the simulated filter response for square wave inputs at different frequencies. For \(f\ll f_c\) the output resembles the input with some overshoot due to the Q of the filter. As f approaches fc, the waveform gets increasingly distorted and delayed. At f = fc, the response starts resembling a sinusoid. Higher frequency inputs yield high quality sinusoids, with now very noticeable attenuation and phase shift.

N filter 3
Figure 5. Simulated filter response for a square wave stimulus

Code for simulation:

# 3 periods of 1kHz square wave sampled at 100kHz
t, v = square_wave(1000, 1e5, 3)

# time domain response
t, y, state = tf.output(v, t)

plot(t, y)

1. Uses the Python Scientific Computing library, https://www.scipy.org.