Exploring the effectiveness of the Goertzel Algorithm for different frequencies and sampling rates.
Here we first implement the algorithm itself and then make a little wrapper function for simulating it's response.
Notice that k and \omega are defined a bit differently than in the lab reference. This way gives improved SNR and matching to the target frequency.
|
|
In this next section we look at how the values given by the Goertzel across a range of frequencies. Notice that not only does 20 samples per Goertzel result in a lower response than 24 samples, but its peak response is not on the target frequency.
Here we approximate fairly closely the actual signal received by the ADC on the MSP430F2012 from a square wave transmission, as opposed to a perfect sine wave. The maximum and minimum Goertzel results can be calculated. This process takes a long time to do and so isn't shown in this published version of the worksheet.
Traceback (click to the left of this block for traceback) ... __SAGE__ Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "_sage_input_3.py", line 10, in <module>
exec compile(u'open("___code___.py","w").write("# -*- coding: utf-8 -*-\\n" + _support_.preparse_worksheet_cell(base64.b64decode("RlMgPSAyOTk1MApyZWFsX3NpbSA9IFtnb2VydHplbChnZW5fZGF0YShmcz1GUywgcGhpPWkqMjUuMC8xMDBlLTYpLCBmcz1GUykgZm9yIGkgaW4gcmFuZ2UoMjUpXQ=="),globals())+"\\n"); execfile(os.path.abspath("___code___.py"))
File "", line 1, in <module>
File "/tmp/tmpcKFo4T/___code___.py", line 4, in <module>
exec compile(u'real_sim = [goertzel(gen_data(fs=FS, phi=i*_sage_const_25p0 /_sage_const_100en6 ), fs=FS) for i in range(_sage_const_25 )]
File "", line 1, in <module>
File "/tmp/tmpDu2rbv/___code___.py", line 53, in gen_data
data = [sw*fn(x,fg,phi) + nw*random() for x in X]
File "/tmp/tmpDu2rbv/___code___.py", line 27, in f_real
while t > period: t -= period
KeyboardInterrupt
__SAGE__
|
Traceback (click to the left of this block for traceback) ... NameError: name 'real_sim' is not defined Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "_sage_input_4.py", line 10, in <module>
exec compile(u'open("___code___.py","w").write("# -*- coding: utf-8 -*-\\n" + _support_.preparse_worksheet_cell(base64.b64decode("bWluKHJlYWxfc2ltKSwgbWF4KHJlYWxfc2ltKQ=="),globals())+"\\n"); execfile(os.path.abspath("___code___.py"))
File "", line 1, in <module>
File "/tmp/tmpymbfNL/___code___.py", line 2, in <module>
exec compile(u'min(real_sim), max(real_sim)
File "", line 1, in <module>
NameError: name 'real_sim' is not defined
|
In this next section we look at how the values given by the Goertzel across a range of frequencies.
Frequency response for F_T = 10000Hz and F_S = 30000Hz Frequency response for F_T = 10000Hz and F_S = 30000Hz |
Next we examine the minimum relative signal response as a function of how long the true signal is active during the sampling period. Not pictures, but on average, the signal needs to be active over half of the time for a 50% response. However, the minimum represents a worst case scenario. Interestingly, the best case requires still just 2 fewer live samples than the worst case. Worst is shown in blue and best in gray.
Traceback (click to the left of this block for traceback) ... __SAGE__ Traceback (most recent call last): best = [0.0] * S
File "", line 1, in <module>
File "/tmp/tmpMb5bFn/___code___.py", line 12, in <module>
next = [goertzel([_sage_const_0 ]*(S-u) + partial[u:]) for u in x]
File "/tmp/tmpuLIKXO/___code___.py", line 17, in goertzel
Q0 = N(s + coef*Q1 - Q2)
KeyboardInterrupt
__SAGE__
|
Here is some data generated across a range of input frequencies and number of samples for the target frequency of 10kHz and sampling at 30ksps.
|
|
And then it is plotted. As you can see, a higher value of N has a great effect. But also notice that some increases in N have much greater effect than others (plateaus and slopes along the rising ridge).
|