Shop OBEX P1 Docs P2 Docs Learn Events
Audio sine wave — Parallax Forums

Audio sine wave

I am going to use audio to indicate small variations from a set of sensors (- in stereo). The ear is extremely sensitive to changes in frequency, but it needs to be a pure tone - sine - in order to work well. Square wave contains an endless series of harmonics, which appears to be confusing. Can anyone point me to a source or a technique that will allow me to generate variable frequency (300Hz-5kHz) sine wave with few harmonics in it? Yes, I will put in a hardware filter, but that generally is only good for the very high hramonics. And I prefer it to be in Spin or other high level language.

Happy New Year,
Erlend

Comments

  • There was discussions on using DDS to generate sine waves.
    Requires building an R2R D/A
    One of the biggest contributors was Drone.
    I found a link to his post
    forums.parallax.com/discussion/121470/a-sine-wave-dds-in-pasm-comments/p1

    DDS would allow you to switch between tones easily

    Tom
  • Heater.Heater. Posts: 21,230
    I don't think those harmonics in a square wave are as confusing as you make out.

    Humans are very good at picking out sounds of interest in what looks like noise.

    Give it a try with your sensors, you might be surprised.
  • Try the functions in this object:
    http://obex.parallax.com/object/688
  • You can use the frequency synthesis object on the Obex exchange. Then use a filter with a couple of 1k resistors in series and capacitors to ground this is shown in the propeller manual. You will have to build an amplifier out of the filter with amplitude control. The amplitude will be high at the low hertz and decrease as the hertz increase or use a dds chip like the AD9851. The DDS is the better way to go.
  • jmgjmg Posts: 15,173
    DigitalBob wrote: »
    ... The amplitude will be high at the low hertz and decrease as the hertz increase or use a dds chip like the AD9851. The DDS is the better way to go.

    Do you mean use AD9851 , or SW DDS on Prop ?
    A dedicated DDS will have higher performance, but for 300Hz-5KHz sound-alert, a dedicated DDS is way-overkill.

    With a upper target of a modest 5KHz, you may find the DAC can be simplified.
    eg sqrt(80M/5k) = 126.49
    means you can have ~7 bits in the X axis and ~7 bits from PDM DAC in the Y axis.

    Not top-shelf Audiophile performance, but very good for a sound-alert.- and just a simple RC filter.
  • The Raspberry Pi apparently uses PWM and an output filter to produce stereo audio. Here's a link to the Hackaday discussion.. The schematic looks simple enough to recreate, and from what I've read the two "halves" are completely independent so if you only need mono you don't need to do the full stereo implementation.
  • MrBi11 wrote: »
    Try the functions in this object:
    http://obex.parallax.com/object/688
    Exactly what I need - did not find it on OBEX myself. Thanks.

    Erlend

  • Heater. wrote: »
    I don't think those harmonics in a square wave are as confusing as you make out.

    Humans are very good at picking out sounds of interest in what looks like noise.

    Give it a try with your sensors, you might be surprised.
    This is what I thought too, but when I tested it out with a signal generator, I found the difference was significant. Also, the square wave was more 'wearisome' to listen to.
    I remember back in the (original) hifi vinyl days, how even a microscopic instability in record player speed would be picked up by the ear - and ruin the listening experience. Now I want to see if I can use that sensitivity to my advantage.

    Erlend
  • Alternatively, I was thinking, since in this case there will be plenty of P1 pin capacity, that I could use a few (6-8) pins connected to a resistor network of R, 2R, 4R, 8R, etc to do binary summing. With this scheme all I need to do is to output the sine in (6-8bit) binary, and it will translate into an analoge waveform.

    Erlend
  • Heater.Heater. Posts: 21,230
    edited 2016-01-02 11:31
    I did the resistor ladder DAC with an AVR years ago. With a 741 for amplifying and filtering. Worked a treat.

    I had a simple DDS in software. Just a simple loop that increments a 32 bit counter as fast as possible. The top 8 bits of the counter go out to the resistor ladder. The size of the increment determines the output frequency.

    Of course the Prop has counters for that.
  • AribaAriba Posts: 2,690
    The Propeller counters can generate the DDS and can replace the DAC.
    A DUTY mode PWM output is much better than a 8bit R-2R DAC and needs only one pin.

    Here is a very simple tone generator, that outputs a triangle - very close to a sine. All you need is a ~250 Ohm resistor between the output and the Earphone.
    CON
      _clkmode  = xtal1 + pll16x
      _xinfreq  = 5_000_000
    
      DAPIN = 15
    
    VAR
      long freq
      long stack[10]
    
    PUB Main : hertz
      cognew(Sound,@stack)
      repeat
        repeat hertz from 50 to 2000
          freq := 54 * hertz
          waitcnt(clkfreq/50 + cnt)
    
    PUB Sound
      ctra := %00110 << 26 + DAPIN
      ctrb := %00100 << 26 
      dira[DAPIN] := 1
      repeat
        frqb := freq
        frqa := ||phsb
    

    Andy
  • Heater.Heater. Posts: 21,230
    edited 2016-01-02 12:53
    Myself above:
    I had a simple DDS in software. Just a simple loop that increments a 32 bit counter as fast as possible. The top 8 bits of the counter go out to the resistor ladder. The size of the increment determines the output frequency.
    Oops I missed out one major detail here.

    Those top 8 bits of the 32 bit counter are used to index an array containing 8 bit samples of a sine wave. It's the result of the array look up that is output to the resistor ladder.

    Or use those 8 bits to fetch sin values from the PROM table. Probably slower.
  • Check out the AD9851 demo on the obex exchange. The filter is actually listed in the Basic stamp syntax and reference manual page 200 version 2.2(my mistake). It has a 1K resistor out of your pin then a 0.1 uf cap out of the resistor (the other cap leg to ground) after that another 1K resistor in series with another 0.01 uf cap (the other cap leg to ground)and then the output goes to your amplifier. As you go from 300hz to 5k hz. you will have to use different filters. The low range from 300 hz. to 800 hz. will have one filter and 800 hz. to 1500 hz. will have different filter etc.


  • {{
    *****************************************
    * Frequency Synthesizer demo v1.1 *
    * Author: Beau Schwabe *
    * Copyright (c) 2007 Parallax *
    * See end of file for terms of use. *
    *****************************************
    Original Author: Chip Gracey
    Modified by Beau Schwabe
    *****************************************
    }}
    {
    Revision History:
    Version 1.0 - original file created

    Version 1.1 - For Channel "B" there was a typo in the 'Synth' object
    The line that reads...
    DIRB[Pin]~~ 'make pin output
    ...should read...
    DIRA[Pin]~~ 'make pin output
    }
    PUB Synth(CTR_AB, Pin, Freq) | s, d, ctr, frq

    Freq := Freq #> 0 <# 128_000_000 'limit frequency range

    if Freq < 500_000 'if 0 to 499_999 Hz,
    ctr := constant(%00100 << 26) '..set NCO mode
    s := 1 '..shift = 1
    else 'if 500_000 to 128_000_000 Hz,
    ctr := constant(%00010 << 26) '..set PLL mode
    d := >|((Freq - 1) / 1_000_000) 'determine PLLDIV
    s := 4 - d 'determine shift
    ctr |= d << 23 'set PLLDIV

    frq := fraction(Freq, CLKFREQ, s) 'Compute FRQA/FRQB value
    ctr |= Pin 'set PINA to complete CTRA/CTRB value

    if CTR_AB == "A"
    CTRA := ctr 'set CTRA
    FRQA := frq 'set FRQA
    DIRA[Pin]~~ 'make pin output

    if CTR_AB == "B"
    CTRB := ctr 'set CTRB
    FRQB := frq 'set FRQB
    DIRA[Pin]~~ 'make pin output

    PRI fraction(a, b, shift) : f

    if shift > 0 'if shift, pre-shift a or b left
    a <<= shift 'to maintain significant bits while
    if shift < 0 'insuring proper result
    b <<= -shift

    repeat 32 'perform long division of a/b
    f <<= 1
    if a => b
    a -= b
    f++
    a <<= 1
    DAT
    {{
    ┌──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐
    │ TERMS OF USE: MIT License │
    ├──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┤
    │Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation │
    │files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, │
    │modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software│
    │is furnished to do so, subject to the following conditions: │
    │ │
    │The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.│
    │ │
    │THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE │
    │WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR │
    │COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, │
    │ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. │
    └──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
    }}
  • The object posted above works well for me
  • jmgjmg Posts: 15,173
    DigitalBob wrote: »
    Check out the AD9851... As you go from 300hz to 5k hz. you will have to use different filters. The low range from 300 hz. to 800 hz. will have one filter and 800 hz. to 1500 hz. will have different filter etc.

    ? I do not follow the separate filters ?

    Any DDS with a lookup table, has small triangular errors that are related to the number of steps.
    For even a modest DDS, that spectral content is up at 76kHz, way above the 5kHz target.
    The expensive AD9851 has content nearer 300kHz

    For what the OP needs, a Prop COG will be fine.

  • If you don't use a DDS and run the frequency syn object with the basic2 filter the wave form will need tweeking as you go from 300hz. to 5k hz. I have run this hz. range when driving LVDT's and resolvers with the simple bs2 filter and a power amp. I used an AGC to control the amplitude as it goes through the hz. range. Maybe I'm doing it the hard way but it worked for me.
  • I'm all open for a better idea. Plenty of guys on here with much better spin and pasm skills than me. I'm just a novice
  • jmgjmg Posts: 15,173
    DigitalBob wrote: »
    If you don't use a DDS and run the frequency syn object with the basic2 filter the wave form will need tweeking as you go from 300hz. to 5k hz...

    Ah, ok - I thought you were saying a scaled filter was needed with DDS / AD9851 designs.
    The Prop can manage DDS with faster PWM in a single COG.

  • MrBi11 wrote: »
    Try the functions in this object:
    http://obex.parallax.com/object/688
    This works very nice, and the sine is not too bad. The drawback is i do not undestand how it works - I am poor at reading PASM. It does look like it reads sine values from ROM though, and I like the idea of using this P1 feature.

    Erlend

Sign In or Register to comment.