'11/18/2006
'This block of code performs a discrete Fourier transform (DFT). You may use it freely
'but I would appreciate if you would leave this title block in place. This and more free
'examples (in MathCad and Excel) can be found at my website. Updates to this particular
‘code block can be found at www.planetsource.code
'
'Russell W. Patterson, P.E.
'rwpatterson357@aol.com
'http://webpages.charter.net/rwpatterson357/
'
'Reference: "The Scientist and Engineer's Guide to Digital Signal Processing"
'by Steven W. Smith ISBN: 0-9660176-3-3, Website: www.DSPguide.com '
'Below I load up 16 values of sampled data in the "Sample" array. These are from the
'original sampled waveform. Since one complete cycle of fundamental is 16 samples in
'this case, N = 16. This number is variable of course depending on how many samples are
'taken across the fundamental frequency.
'Sample(0) = 4.943
'Sample(1) = 4.215
'Sample(2) = 1.655
'Sample(3) = -1.144
'Sample(4) = -2.546
'Sample(5) = -4.467
'Sample(6) = -6.195
'Sample(7) = -5.658
'Sample(8) = -4.743
'Sample(9) = -4.015
'Sample(10) = -1.455
'Sample(11) = 1.344
'Sample(12) = 2.746
'Sample(13) = 4.667
'Sample(14) = 6.395
'Sample(15) = 5.858
Dim Real(16) As Single 'You can make this double if need. This array holds the real
'value results of the DFT
Dim Imag(16) As Single 'Likewise, this array holds the imaginary results
Dim Mag(16) As Single 'This array holds the magnitude of the DFT results
Dim Phase(16) As Single 'This array holds the phase angles of the DFT results
Dim pi As Single
pi = 4 * Atn(1) 'Computes pi (3.14)
'In this case the sample frequency is 960Hz and I am interested in a 60Hz fundamental.
'N works out to 16 samples per cycle, Nyquist tells us that we can get information about
'the harmonics up to N/2, and that if any higher frequencies are present that aliasing
'will occur and our results will be suspect (which is why low-pass filtering may be required).
N = 960 / 60 'samples per 60Hz cycle
'calulate the real and imaginary components of each harmonic (perform DFT)
'This is the only code needed to perform the DFT.
For F = 0 To (N / 2) 'F=0 is the zero frequency (DC) component, F=1 is the fundamental
For i = 0 To (N - 1) 'step through each of the 16 samples in 1 fundamental cycle
Real(F) = Real(F) + Sample(i) * Cos(2 * pi * i * F / N)
Imag(F) = Imag(F) + Sample(i) * Sin(2 * pi * i * F / N)
Next i
Imag(F) = -Imag(F)
Next F
Real(0) = Real(0) / 2 'correct the magnitudes of the end bin components
Real(N / 2) = Real(N / 2) / 2
'This remaining code is aimed at putting the DFT rectangular complex (r + jx) results
'in polar form.
'compute harmonic magnitudes from the real and imaginary results
For F = 0 To (N / 2)
Mag(F) = (Real(F) ^ 2 + Imag(F) ^ 2) ^ 0.5 * (2 / N) 'the 2/N is required to correct mag
Next F
'this iteration removes very small values (not required depending on the amplitudes of
'interest. in this case it zeros harmonics that are less than 1000th of the fundamental)
'The only reason to do this is to improve ability to display results cleaner
For F = 0 To (N / 2)
If (Mag(F) / Mag(1)) < 10 ^ -3 Then Mag(F) = 0 'get rid of bug dust
Next F
'calculate the phase angle of each harmonic (in radians, multiply by 180/pi for degrees)
For F = 0 To (N / 2)
'get rid of zeros to allow proper phase angle calculation, this is required so the Atn
'function won't blow up
If Abs(Real(F)) < 10 ^ -10 Then Real(F) = 10 ^ -10
Phase(F) = Atn(Imag(F) / Real(F)) 'phase angles in radians
If Abs(Phase(F)) < 10 ^ -10 Then Phase(F) = 0 'zero out small phase angles, not required
If Mag(F) < 10 ^ -10 Then Phase(F) = 0 'zero out phase of zero amplitude harmonics
Next F
'correct phase angle of zero frequency component (DC)
If Sgn(Real(0)) < 0 Then
Phase(0) = -pi
Else
Phase(0) = pi
End If
'correct phase angle of non zero frequency components
For i = 1 To (N / 2)
If Sgn(Real(i)) > 0 Then
'leave phase as-is
Else
If Sgn(Imag(i)) > 0 Then
Phase(i) = Phase(i) + pi
Else
Phase(i) = Phase(i) - pi
End If
End If
Next i
‘end of code block