Shop OBEX P1 Docs P2 Docs Learn Events
How to utilize DDS/Goertzel LUT mode — Parallax Forums

How to utilize DDS/Goertzel LUT mode

soohan_kimsoohan_kim Posts: 6
edited 2021-02-16 20:52 in Propeller 2

I'm having trouble understanding how to implement DDS/Goertzel on the P2. I have a sine wave being output from one pin in the first spin2 file. Another pin measures the sine wave and displays it on the debug scope.

I have another snippet of code that uses the regular DAC/ADC modes to output and measure DC voltages.

What I'd like to do is measure the sine wave from the first snippet of spin2. However, rather than using the normal ADC mode, I'd like to be able to use DDS/Goertzel to measure the frequency content of the signal and extract the real/imaginary components. I'm a little lost on how to implement that in spin2.

Comments

  • cgraceycgracey Posts: 14,206

    Soohan_kim, let me write an object that does this in PASM, so that it interfaces to Spin2. This way, the timing can be independent of your Spin2 code and the interface can become a few input and output variables. Hopefully, I can have this done today.

  • @cgracey said:
    Soohan_kim, let me write an object that does this in PASM, so that it interfaces to Spin2. This way, the timing can be independent of your Spin2 code and the interface can become a few input and output variables. Hopefully, I can have this done today.

    Wow, that's more than I could've asked for. Thank you Chip!

  • cgraceycgracey Posts: 14,206

    I didn't get to it yesterday, but I will work on it this morning.

  • @cgracey said:
    I didn't get to it yesterday, but I will work on it this morning.

    No worries, thanks for helping out on this!

  • cgraceycgracey Posts: 14,206
    edited 2021-02-18 05:26

    Here is the program. It outputs SINE and !SINE on two adjacent pins, then does the Goertzel input over another pin.

    In this example (which is easily modified) it is outputting 10KHz over a little speaker connected directly to two opposite-phase 75-ohm DAC pins, while it inputs from a dynamic microphone coupled through a capacitor using 100x magnification ADC mode. The data is shown on the SCOPE_XY display in LOGSCALE mode.

    In the video, you can see the phase winding around as I pull and push the microphone away/towards the speaker on the JonnyMac board.

    It occurred to me that you could measure distance by varying the frequency a little and observing a phase-multiplying effect on the input side.

  • Great demo, Chip. Better find those Ultrasonic transceivers

  • cgraceycgracey Posts: 14,206

    @Tubular said:
    Great demo, Chip. Better find those Ultrasonic transceivers

    Yes, but the microphone and speaker have greater frequency response, so some interesting stuff is possible.

    I modified the program to output 10KHz and take a measurement, then 11KHz and take a measurement. The two return phases change at different rates. It's kind of scrappy, but to make it better, I'll use two LUT halves to each output 10KHz + 11KHz, then toggle between the halves which will have unique bytes in the upper words, to make separate 10KHz and 11KHz input tables. This way, I can toggle, back to back, between measurement modes while outputting a continuous 10KHz + 11KHz function to the speaker. It will then be as smooth as the video, but have TWO dots which change angles at different rates. This amounts to a measurement distance of the 10KHz period multiplied by the 11KHz period. Measurement becomes the phase delta between the two, ignoring power.

  • @cgracey said:
    Here is the program. It outputs SINE and !SINE on two adjacent pins, then does the Goertzel input over another pin.

    In this example (which is easily modified) it is outputting 10KHz over a little speaker connected directly to two opposite-phase 75-ohm DAC pins, while it inputs from a dynamic microphone coupled through a capacitor using 100x magnification ADC mode. The data is shown on the SCOPE_XY display in LOGSCALE mode.

    In the video, you can see the phase winding around as I pull and push the microphone away/towards the speaker on the JonnyMac board.

    It occurred to me that you could measure distance by varying the frequency a little and observing a phase-multiplying effect on the input side.

    That was a great demo! Thanks for putting your time into this. I want to make sure I understand the PASM, so I have a few questions:

    1. My main application for this is to try to use the propeller p2 as an multichannel impedance analyzer, similar to the AD5933, which sends a excitation signal at a known frequency and measures the response signal from the unknown impedance.
    2. For my use case, I don't need to do a frequency sweep. I only need to measure the impedance at a specific frequency, which was the main factor as to why I'm using goertzel rather than FFT.
    3. It seems like your example calculates the magnitude (power) and phase from (x, y), which were the Goertzel readings. What does (x, y) represent however?
    4. I see that the frequency, cycles, and phase are read at every iteration of the loop. If I understand this correctly, cycles refers the number of periods, which ultimately determines the duration of the measurement per loop. What would be a reason to change this parameter?

    Let me know if you have any suggestions for how I should modify the program to suit this application. Otherwise, this is a great starting point for me to work off of. Thanks again!

  • @soohan_kim said:

    @cgracey said:
    Here is the program. It outputs SINE and !SINE on two adjacent pins, then does the Goertzel input over another pin.

    In this example (which is easily modified) it is outputting 10KHz over a little speaker connected directly to two opposite-phase 75-ohm DAC pins, while it inputs from a dynamic microphone coupled through a capacitor using 100x magnification ADC mode. The data is shown on the SCOPE_XY display in LOGSCALE mode.

    In the video, you can see the phase winding around as I pull and push the microphone away/towards the speaker on the JonnyMac board.

    It occurred to me that you could measure distance by varying the frequency a little and observing a phase-multiplying effect on the input side.

    That was a great demo! Thanks for putting your time into this. I want to make sure I understand the PASM, so I have a few questions:

    1. My main application for this is to try to use the propeller p2 as an multichannel impedance analyzer, similar to the AD5933, which sends a excitation signal at a known frequency and measures the response signal from the unknown impedance.
    2. For my use case, I don't need to do a frequency sweep. I only need to measure the impedance at a specific frequency, which was the main factor as to why I'm using goertzel rather than FFT.
    3. It seems like your example calculates the magnitude (power) and phase from (x, y), which were the Goertzel readings. What does (x, y) represent however?
    4. I see that the frequency, cycles, and phase are read at every iteration of the loop. If I understand this correctly, cycles refers the number of periods, which ultimately determines the duration of the measurement per loop. What would be a reason to change this parameter?

    Let me know if you have any suggestions for how I should modify the program to suit this application. Otherwise, this is a great starting point for me to work off of. Thanks again!

    Also, what's the way to go to represent the raw values for power and angle from the debug?

  • cgraceycgracey Posts: 14,206
    edited 2021-02-18 23:01

    The (X,Y) that comes out of the Goertzel via GETXACC+MOV are the Imaginary and Real terms. The QVECTOR instruction converts those into both magnitude and phase, which I termed "power" and "angle".

    The "cycles" variable tells how many integral cycles to measure for. The bigger this number, the more selective the process becomes.

    To know what 1x gain looks like, set "adcmag" to 0 and connect the ADC pin to one of the DAC output pins. The resultant reading will be your 1x level. Now, you can connect your ADC to other points in whatever circuit you've got and take measurements from those points, as well. We could also automate the ADC pin changing. As well, up to four pins in a set of four (%xxxxyy, where %xxxx is the group and %yy are the members) can be added/subtracted from the measurement, allowing you to make differential measurements, for example.

  • @cgracey said:
    The (X,Y) that comes out of the Goertzel via GETXACC+MOV are the Imaginary and Real terms. The QVECTOR instruction converts those into both magnitude and phase, which I termed "power" and "angle".

    The "cycles" variable tells how many integral cycles to measure for. The bigger this number, the more selective the process becomes.

    To know what 1x gain looks like, set "adcmag" to 0 and connect the ADC pin to one of the DAC output pins. The resultant reading will be your 1x level. Now, you can connect your ADC to other points in whatever circuit you've got and take measurements from those points, as well. We could also automate the ADC pin changing. As well, up to four pins in a set of four (%xxxxyy, where %xxxx is the group and %yy are the members) can be added/subtracted from the measurement, allowing you to make differential measurements, for example.

    Gotcha, that makes sense. Really appreciate your help!

  • I've just found this thread and suddenly had an idea which has nothing to do with the original question but might be useful to others:

    You can put sine/cosine waves with different frequencies into bytes 1/2 and 3/4 of the lookup table, for example the base frequency (one cycle) into bytes 1+2 which goes to the output pins and the third overtone into bytes 3+4 which are used for multiplication and summing. This way it's possible to detect non-linearities of the transmission line like clipping or overshot.

Sign In or Register to comment.