1
$\begingroup$

I would expect the FFT of a periodic pulse signal to look like a sinc function, like shown here. However, if I try to replicate that, what I get is a single peak at the signal frequency, and then another peak at 3 times the signal frequency. Shouldn't I see a sinc function, as a pulse contains a wide range of frequencies?

enter image description here

import numpy as np
from scipy.fftpack import fft
import math
import matplotlib
import matplotlib.pyplot as plt

# Parameters
M            = 64
f_sig        = 200e3
nr_of_cycles = 1e3

# Local parameters
f_s     = f_sig * M
T_s     = 1/f_s
N       = int(nr_of_cycles * M)

test_signal = np.repeat([0, 1], M // 2)
test_signal = np.tile(test_signal, int(N / M))
# test_signal = np.cos(2 * math.pi * f_sig * T_s * np.arange(N))
fft_test_signal = fft(test_signal)[0 : N//2]

fig, axs = plt.subplots(2, sharex = False, sharey = False, figsize=(8,7), num='FFT + Time')

freq = np.fft.fftfreq(N, T_s)
freq_axis = freq[0 : N//2]

axs[0].grid(which='both', axis='both')
axs[0].plot(freq_axis, abs(fft_test_signal), label='FFT Test Signal')

# axs[1].set_xscale("symlog")
axs[0].set_xlim(0, f_sig * 4)
axs[0].legend(loc='upper right', shadow=True, fontsize='x-small')
axs[0].set_ylabel('Magnitude')
axs[0].set_xlabel('Frequency [Hz]')

time_vec = np.arange(N) * T_s * 1e6
axs[1].plot(time_vec[0 : 10*M-1], test_signal[0 : 10*M-1], label='Test Signal')
axs[1].legend(loc='upper right', shadow=True, fontsize='x-small')
axs[1].set_ylabel('Amplitude')
axs[1].set_xlabel('Time [us]')

plt.show()
$\endgroup$
1
  • $\begingroup$ Try increasing the distance between your pulses and you will start seeing it more clearly. $\endgroup$
    – learner
    Jan 27, 2023 at 19:00

2 Answers 2

3
$\begingroup$

The OP is indeed seeing what is approximately samples of a Sinc function (Because the FFT was used, the Fourier Transform is aliased and what is specifically shown are samples of the Dirichlet Kernel, which approximates a Sinc as the sampling rate increases, or more specifically the number of samples representing each pulse. I will refer to it as a Sinc for the remainder of this post). The aliasing is due to a lower sampling rate but that isn't the primary issue here, as the shape of a Sinc function even with the aliasing now occurring will still be visibly clear.

What is happening is any waveform that repeats in time will be discrete in frequency starting with a fundamental frequency given by the repetition rate as well as all higher integer harmonics (and DC if there is a DC offset); the OP used a 50% duty cycle waveform which results in every even harmonic being in the null of the underlying Sinc. To see the underlying Sinc more clearly, lower the duty cycle of the repeating waveform.

There are two useful takeaways here:

  • Given a pulse of width $\tau$ seconds, the Fourier Transform of the pulse will be a Sinc function with its first null at $1/\tau$ Hz. (And nulls every $n/\tau$ Hz for all integer $n$ not including $n=0$.)

  • Given any base function (such as a Sinc), if it is repeated continously in time at period $T$, the Fourier Transform will be the same as that described above, except its non-zero values will be discrete and can only exist at integer harmonics of the fundamental frequency $1/T$, as well as DC if there is a mean value. These frequencies will sample the Fourier Transform of the base function that is being repeated!

It may be helpful to recall the Fourier Series Expansion in understanding the second point given above: any waveform over duration $T$ seconds can be decomposed into a series of sinusoids each at frequency $1/T$ and it's higher harmonics, as well as DC if there is an mean value). So if we lower the duty cycle while keeping the same repetition rate, this means all the frequency tones will still exist at the same frequencies (harmonics of the repetition rate) but we have decreased the width $T$ of the pulse, which will move the first null of the underlying Sinc out to a higher frequency. In doing this, more frequencies will be in the first main lobe of the Sinc, making it more visible. Alternatively we can lower the duty cycle while keeping the same pulse width, which lowers the repetition rate, and therefore the frequency of all the harmonics go down while the frequency of the first null in the Sinc remains the same-- having the same effect of moving more frequencies into the first null of the Sinc and making it more visible.

These points are demonstrated with my graphic below and then with simple modifications to the OP's code:

50% duty cycle

25% duty cycle

Basically in the case of 50% duty cycle, the period is split into two parts (one up, one down) and with that the 2nd harmonic is in the first null. For the 25% duty cycle, the period is split into four parts (three up, one down) and with that the 4th harmonic is in the first null. Yes if we did a 10% duty cycle, the 10th harmonic would be in the first null.

We can see the same with the OP's example by modifying one line to change the duty cycle while maintaining the same pulse width (so doing the option that lowers the repetition rate of waveform):

With a 25% duty cycle, the 4th harmonic is in the first null:

test_signal = np.repeat([0, 0, 0, 1], M // 2)

25% duty cylcle

With a 10% duty cycle, the 10th harmonic is in the first null:

test_signal = np.repeat([0,0,0,0,0,0,0,0,0,1], M // 2)

10% duty cycle

Increase the sampling rate higher so that there are more samples in every pulse and the result will show more sidelobes of the Dirichlet Kernel and will more closely approach an actual Sinc function, although as we see above with the sampling rate chosen we visually see a reasonable approximation for the main lobe and first side-lobe of a Sinc function.

$\endgroup$
1
$\begingroup$

Let's tackle this in the continuous time domain first.

Your signal is a periodic repetition of a rectangular pulse. This can be written as

$$x(t) =\text{rect}(t/\tau)*\sum_{n=-\infty}^{\infty}\delta(t-nT)$$

where $*$ is the convolution operator, $\tau$ the width of the rectangle and $T$ the repetition period. The Fourier Transform (FT) of a rectangle is indeed a sinc, the convolution turns into multiplication and the FT of a dirac train is also a dirac train, so we get

$$X(\omega) = \tau \cdot \text{sinc}(\omega\tau/2) \cdot \frac{2\pi}{T}\sum_{-\infty}^{\infty}\delta(\omega-n/T)= \frac{2\pi\tau}{T}\sum_{-\infty}^{\infty}\text{sinc}(n\frac{\tau}{2T}) $$

(no guarantees on the exact scale factors here).

A single rectangular pulse will give you a sinc but the periodic repetition samples it in frequency. So it's a line spectrum with the shape of a sinc.

In order to simulate this inside a computer, you actually have to sample it first. That's a problem, since the function is clearly not bandlimited and regardless of how high a sample rate you choose, you will always end up with aliasing.

So what you can expect is a line spectrum that follows the shape of an aliased sinc function.

$\endgroup$
2
  • $\begingroup$ I think you need to fix the right-hand side of that $X(\omega)$ equation, Hil. I see no $\omega$ in it. It's still a function of $\omega$. $\endgroup$ Jan 27, 2023 at 21:10
  • $\begingroup$ Good point. I'll take another look at it when I have a chance $\endgroup$
    – Hilmar
    Jan 27, 2023 at 23:17

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.