Shop OBEX P1 Docs P2 Docs Learn Events
My poor brain struggling with tricky low pass filter challenge — Parallax Forums

My poor brain struggling with tricky low pass filter challenge

WossnameWossname Posts: 174
edited 2012-01-26 05:25 in Propeller 1
Hi guys, I wonder if some of you mixed-signal guys could lend me a hand with my current task...

My goal is to generate DTMF audio tones for dialling a telephone number. I can understand how the code should work but I'm having real difficulty understanding how I should create the output filtering circuitry that will effectively low pass filter my square wave output and convert it into a nice clean audio waveform that can be amplified and passed through to a speaker.

I've tried using a PWM square wave frequency of (80_000_000 / 4096) = 19531 Hz. So the duty cycle can be changed 19531 times per second - I chose that because it's a power of two and also more than 10x higher freq than the highest tone that DTMF uses (1633Hz). So my thought was if I use a low pass filter that attenuates everything above say 3000Hz then I should get good audio without the PWM buzz. Is that sensible?

I can get my Propeller code to output a sine-modulated duty cycle square wave but I'm lost as to how to filter this modulated square wave. I've tried to calculate the values for an RC filter but it only seems to work for certain duty cycles and not others.

Has anyone done this before and have a good idea how to design a filter circuit for PWM-audio?

Comments

  • LeonLeon Posts: 7,620
    edited 2012-01-15 07:55
    Why don't you generate a sine wave with PWM?
  • T ChapT Chap Posts: 4,223
    edited 2012-01-15 08:34
    If you are only generating a fixed frequency, why do you need to use a low pass? I think you may be confused as to what the low pass is doing. For phones, sine is the solution and you an easily generate a sine wave with the prop.

    There may already be DTMF objects in the obj exchange, as well as sine wave generators.
  • kwinnkwinn Posts: 8,697
    edited 2012-01-15 09:49
    @T Chap You need to generate 2 sine waves at different frequencies simultaneously for DTMF.

    A low pass filter is usually not required but if you need one a simple RC filter should work.

    Take a look at http://obex.parallax.com/objects/823/. It includes a DTMF generator.
  • Dr_AculaDr_Acula Posts: 5,484
    edited 2012-01-15 14:36
    kwinn's link will work. Any time a "RC filter" is mentioned, that is a low pass filter. Ballpark figures, for audio frequencies say with a cutoff of 20khz, 0.001uF and 15k. But your pwm is 19531hz so yes, lower that to 3000Hz and that will work with 0.001uF and 56k.

    Re
    but it only seems to work for certain duty cycles and not others.

    A low pass filter has a fixed frequency which can't be varied (unless you use fancy things like switched capacitor filters). So if you plug in the R and the C for 3000hz and use PWM at around 20khz then you should get nice sine waves on your CRO.

    Try that object kwinn mentioned.
  • WossnameWossname Posts: 174
    edited 2012-01-16 06:16
    Leon wrote: »
    Why don't you generate a sine wave with PWM?
    That's what I am trying to do but it will need low pass filtering to attenuate the PWM carrier frequency.



    Thinking aloud...
    The plan is to pick the low tone and high tone I need for any given DTMF digit, calculate the next sine value for each, sum them, scale the result and then use that as the next duty cycle value which causes the filtered voltage to change a bit, doing this 19531 times per second (the PWM frequency) will give a nice audio waveform.

    I understand the DTMF part of it and how to mix two sine values to generate a DTMF tone pair, actually I've done this before using a regular c program and a PC sound card. My problem was that I wasn't getting far enough to even start thinking about the tones themselves, because I couldn't be sure that my RC filter was working right (it wasn't, as it happens).

    Yep, the PWM frequency never changes (which makes the RC filter happy), but the PWM duty cycle needs to be sine-modulated which, when passed through a sensible RC low pass filter, will cause the output voltage to become a smooth sine wave - the frequency of which is entirely determined by the PWM duty cycle (not freq) and the RC attenuation curve.

    I've actually just found a nice site that helps me calculate this stuff...
    http://sim.okawa-denshi.jp/en/PWMtool.php

    Anyway, thanks for that link, it looks interesting. For this project, though, I'd rather do it all myself instead of using something from the OBEX, as I'm still learning electronics at a novice level. The chance to understand PWM and RC filtering at the nuts and bolts level will be more valuable to me than using someone else's code.

    Anyway, I'll detail what I'm going to use for the time being (pending further analysis)...

    - Propeller outputting 19,531.25Hz (80_000_000 / 4096) square wave.
    - Resistor: 4.7kΩ (1% tolerance)
    - Capacitor: 10nF (10% tolerance)
    This should give something like -3db attenuation point of 3400Hz hopefully.

    I'm having flashbacks to A-Level maths and all that hideous integration stuff they made us do. :)

    Thanks for the tips guys.
  • T ChapT Chap Posts: 4,223
    edited 2012-01-16 06:27
    If you want to learn more about PWM, study this app note:

    http://www.parallaxsemiconductor.com/an001

    If you want to build the code from scratch, that is fine but maybe using the DTMF object will help you understand more quickly how and what the Prop can do as a starting point.
  • ChrisGaddChrisGadd Posts: 310
    edited 2012-01-16 11:11
    If you don't mind a somewhat squarish DTMF signal, you could try something like this:
    {{ DTMF
     Use ctra and ctrb to produce the two frequencies                                         
      Clear an accumulator and add 1 if phsa or phsb is negative             10K               
      If acc has a value of 2, output a high                          ────╋──       
      If acc has a value of 1, set DTMF_pin to input                    100  10K               
      If acc has a value of 0, output a low                                                     
                                                                                                
    }}                                                                                           
    CON
    _clkmode = xtal1 + pll16x                            
    _xinfreq = 5_000_000
    DTMF_pin = 16
    
    PUB Main
      cognew(@DTMF, 0)                                      
    
    DAT                     org
    DTMF
                            movi      ctra,#%0_11111_000                            ' Increment phsa on every clock
                            movi      ctrb,#%0_11111_000                            ' Increment phsb on every clock
    
    Send_1
                            mov       frqa,Col_A
                            mov       frqb,Row_1
    
    Loop
                            mov       counter,#0                                    
                            test      half,phsa                   wc
              if_c          add       counter,#1                                    ' Add 1 if high freq is high
                            test      half,phsb                   wc
              if_c          add       counter,#1                                    ' Add 1 if low freq is high
                            tjz       counter,#Low_out
                            sub       counter,#1
                            tjz       counter,#No_out
    'High_out                                                                       ' If both freqs high, output a high
                            or        outa,DTMF_mask                               
                            or        dira,DTMF_mask
                            jmp       #Loop
    No_out                                                                          ' If only one freq high, set to input
                            andn      dira,DTMF_mask
                            jmp       #Loop
    Low_out                                                                         ' If both freqs low, output a low
                            andn      outa,DTMF_mask
                            or        dira,DTMF_mask
                            jmp       #Loop
    '-----------------------------------------------------------------------------------------
    DTMF_mask               long      1<<DTMF_pin
    
    Half                    long      $8000_0000
    
    Col_A                   long      64_907                                        '       1209    1336    1477    1633      
    Col_B                   long      71_726                                        ' 697   1       2       3       A         
    Col_C                   long      79_296                                        ' 770   4       5       6       B         
    Col_D                   long      87_671                                        ' 852   7       8       9       C         
    Row_1                   long      37_420                                        ' 941   *       0       #       D         
    Row_2                   long      41_339                                                          
    Row_3                   long      45_741
    Row_4                   long      50_520
    
    Counter                 res       1
                            fit
    
    This code is based on something I wrote for a different micro, which read fine when connected directly to a DTMF decoder IC, but has never been tested through phone lines.

    The yellow trace in the attached image is the output from the micro, the blue trace is from a DTMF generator.
    DTMF Synth.jpg
    525 x 452 - 130K
  • Dr_AculaDr_Acula Posts: 5,484
    edited 2012-01-16 15:08
    Propeller outputting 19,531.25Hz (80_000_000 / 4096) square wave.
    - Resistor: 4.7kΩ (1% tolerance)
    - Capacitor: 10nF (10% tolerance)
    This should give something like -3db attenuation point of 3400Hz hopefully.

    That should work.

    Can I ask what it is you are driving, and more specifically, is it a high impedance load? A CRO is a high impedance load (megohms), but as an example, a speaker is a very low impedance load (8 ohms) and so will greatly distort your waveform.

    A simple solution is a small amplifier, eg an amplifier chip, or amplified computer speakers or something.

    In general, you want the impedance of the load to be bigger (10x bigger or more) than the resistor you use in your low pass filter.

    If you ever get stuck with impedance matching, an op amp voltage follower solves the problem - put the input into the + side, join the - and the output, and the output follows the input. But the impedance of an op amp is very high so it doesn't load the low pass filter.
  • WossnameWossname Posts: 174
    edited 2012-01-17 02:47
    ChrisGadd wrote: »
    If you don't mind a somewhat squarish DTMF signal...

    That's an interesting technique, but I'm trying to generate a waveform that is as close to perfect as possible with simple components.

    My 3 stage filter looks like this at the moment (I've not gotten around to adding the opamp yet though)...
                          4k7   4k7    4k7
                    P0 &#61609;&#9472;&#9472;&#61629;&#61630;&#9472;&#9523;&#9472;&#9472;&#61629;&#61630;&#9472;&#9472;&#9523;&#9472;&#9472;&#61629;&#61630;&#9472;&#9472;&#9523;&#9472;&#61627;  ~~~~  [op-amp]  &#9472;&#9472;&#61627;  output
                             &#9474;      &#9474;      &#9474;
                             &#61613;10n   &#61613;10n   &#61613;10n
                             &#9474;      &#9474;      &#9474;
                             &#61464;      &#61464;      &#61464;
    
    

    The output will be both a small 8 or 16ohm speaker and also some other circuitry. I'll use an opamp as Dr_Acula suggested. Although I might opt for a audio specialised opamp instead of something like a 741.
  • Dr_AculaDr_Acula Posts: 5,484
    edited 2012-01-17 02:53
    Ah, I'm not sure putting three low pass filters in a row will help. I suspect it will make things worse!

    What are you trying to do by adding more stages? Do you want a sharper rolloff at the desired frequency? If so, maybe take a look at the schematics for a "third order butterworth filter". There are circuits for filters using inductors, but it is more practical to use the circuits that use op amps. I think a single chip quad op amp will do the job.

    Mind you, the rolloff for a single R and C should be fine for this application.
  • WossnameWossname Posts: 174
    edited 2012-01-17 03:41
    I was hoping that one RC stage would be good enough but I just get a 0.8v (peak-peak) sawtooth, then I added another and that drops down to something like 0.1v, a third made the line flat.

    I took some shots for my own records but they show what I mean...
    6709279653_2b30d4cd46_z_d.jpg
  • Dr_AculaDr_Acula Posts: 5,484
    edited 2012-01-17 05:34
    I wonder if we are talking at cross purposes here?

    When you say you have a 50% duty cycle square wave, what is the frequency of that wave?

    I am assuming it is something much higher than the RC cutoff frequency, say 100khz. Then yes, you should be able to filter it with just one RC filter and get a flat line of 1.5V DC.

    But if that square wave is a much lower frequency, say 1khz, then we might need to go right back to the beginning and talk about some PWM basics.

    What is the time base on that CRO trace? (maybe just post a photo with the knob settings shown as well)
  • WossnameWossname Posts: 174
    edited 2012-01-17 09:45
    The PWM freq is (80_000_000 / 4096) = 19531 Hz (see top post).

    I deliberately made it quite a lot higher than the highest DTMF tone for that very reason you just said :)

    Anyway, the 3 stage RC filter seems to work well, I'm able to output what appears to be a really nice smooth waveform free from nastiness...

    20120117072.jpg


    The signal shown here is the DTMF digit "1".

    (Ignore some of the measurements on that picture, I've still got to play around with some of the multiplications to make the waveform fit nicely in between 0 and 3.3v, but this is in essence exactly what I was looking for.

    Thanks for the input everyone, as always it is much appreciated. This is the best and friendliest forum on the web and long may it remain so :)


    1024 x 768 - 92K
  • Dr_AculaDr_Acula Posts: 5,484
    edited 2012-01-17 14:10
    Great to hear you have a waveform. I'm still not sure though about those three RC filters in a row. I don't really know what sort of filter that is, what its phase response is etc.

    Take a look at this page for how to do multiple filters in series http://en.wikipedia.org/wiki/Roll-off - you need op amp buffers between each stage.

    Also - if you put a 19531 hz into an RC filter with a cutoff frequency of 3386Hz, it doesn't block all frequencies above 3386hz. There is a "rolloff" and for a first order filter it is 6db per octave. So a significant proportion of the 19531 square wave is going to get through, and that is exactly what you are seeing on "waveform at A".

    The fundamental problem here is the sampling frequency (19531) is too close to the filter frequency (3386).

    I wonder if you could try a very simple experiment - try increasing the square wave frequency by 10x to 195310 Hz and measure the waveform at A.
  • LeonLeon Posts: 7,620
    edited 2012-01-17 14:16
    A lot of time and effort can be saved by using simulation techniques with problems like this, instead of messing about with hardware.
  • Dr_AculaDr_Acula Posts: 5,484
    edited 2012-01-17 14:32
    Good point Leon. I found one online simulator here http://www.st-andrews.ac.uk/~jcgl/Scots_Guide/experiment/lowpass/lpf.html and plugged in the values and looked at the waveform. However, it only allows sine wave inputs.

    Does anyone have a link to an online filter simulation where you can plug in square waves as the input? If so, it would be great to replicate the waveforms on that CRO, and as Leon says, save a lot of time playing with hardware.
  • LeonLeon Posts: 7,620
    edited 2012-01-17 14:38
    A SPICE simulator is an option with the PCB software I use, it's actually SIMetrix:

    http://www.simetrix.co.uk/

    I'll simulate that filter and post the results. It'll be interesting to compare it with the actual results shown on the scope.

    A popular free SPICE implementation is LTSpice, available from Linear Technology.
  • Phil Pilgrim (PhiPi)Phil Pilgrim (PhiPi) Posts: 23,514
    edited 2012-01-17 15:28
    A DUTY-mode counter output would be a lot easier to filter than a PWM signal, since the undesired frequencies are so much higher.

    -Phil
  • WossnameWossname Posts: 174
    edited 2012-01-18 03:42
    Leon wrote: »
    A lot of time and effort can be saved by using simulation techniques with problems like this, instead of messing about with hardware.

    I'm an analog noob - LTSpice is waaaaaay over my head - so messing about with hardware is a bit easier even if it is slower. :)
  • WossnameWossname Posts: 174
    edited 2012-01-18 07:28
    Follow up info, from tests using the 3-stage ...

    I worked out how to the DSO to measure FFT spectra - I'm getting a pair of strong signals at around -20db and a few harmonics floating around at about -45db, and a bunch of noise below -60db. Each successive RC stage really suppresses the noise a great deal.

    I think this will be enough to work with for the time being.

    Thanks again for all your help.
  • Dr_AculaDr_Acula Posts: 5,484
    edited 2012-01-18 14:21
    I found an article that talks about the difference between multiple passive RC filters in series vs a more formal two or three pole filter. http://www.proaxis.com/~wagnerj/PWMfil/PWM%20Filters.pdf scroll down to page 28.

    The article itself has a lot of useful points. There is a worked example of a Bell Modem filter with tones of 1200 and 2400 Hz and they chose a PWM frequency of around 64Khz - in other words a frequency a "lot higher".

    I also would like to add a vote in support of PhiPi's comment about Duty Mode being better than pulse width.
  • WossnameWossname Posts: 174
    edited 2012-01-21 11:58
    How does "duty mode" differ from PWM? I can't find much authoritative info on "Duty Mode".
  • Phil Pilgrim (PhiPi)Phil Pilgrim (PhiPi) Posts: 23,514
    edited 2012-01-21 12:07
    PWM uses a fixed frequency with a variable duty cycle. DUTY mode also has a variable duty cycle but makes more frequent (i.e. opportunistic) transitions, resulting in a much higher overall frequency. It emanates from a counter's instantaneous carry when it rolls over. With an 80 MHz clock, for example, and a 50% duty cycle, the DUTY mode output would have a frequency of 40 MHz. As the duty cycle deviates from 50%, the frequency becomes progressively lower.

    DUTY mode output is very simple to obtain from a counter and does not need continuously-running code to produce. After setting things up, you simply set frqx to the analog value you want (as a fraction of 232), and the counter does the rest.

    -Phil
  • WossnameWossname Posts: 174
    edited 2012-01-21 13:51
    Hmmmmm.......

    So I'd use the "DUTY single-ended" mode (%00110) CTRMODE setting? I didn't realise you were referring to the actual Propeller features when you guys mentioned "Duty Mode" - I thought it was some random generic technology I'd never heard of :)

    So you get a 1 cycle-long pulse every time PHSx[31] goes from 1 to 0.

    Am I right in the following cases?...

    - For a steady 50% duty cycle you'd use a FRQx of (2<<31) -- where every other cycle would cause a carry pulse?
    - For a steady 25% duty cycle you'd use a FRQx of (2<<30) -- where every 4th cycle would cause a carry pulse?
    - For a steady 33.333333% duty cycle you'd use a FRQx of 715827883?

    I might be an order of (binary) magnitude out with those calcs but is that the general idea?
  • Phil Pilgrim (PhiPi)Phil Pilgrim (PhiPi) Posts: 23,514
    edited 2012-01-21 13:56
    Yes, you've got the idea! Now, for audio, you want to set a zero level offset of $8000_0000. Then you can add your signed audio waveforms to that.

    -Phil
  • WossnameWossname Posts: 174
    edited 2012-01-23 01:34
    Fantastic! Just tried it and it seems to be easy enough to understand. I notice a fair amount of interference when I bring my FM radio near to my Prop while it's toggling P0 at high frequencies. That's pretty awesome :) although I suspect any application that shows that unfortunate behaviour would be shunned by the industry.
  • Phil Pilgrim (PhiPi)Phil Pilgrim (PhiPi) Posts: 23,514
    edited 2012-01-23 08:58
    The S2 robot uses this method to generate audio. It passed the FCC emissions test and received the CE mark. It all has to do with good PCB layout.

    -Phil
  • mike_mmike_m Posts: 4
    edited 2012-01-23 10:15
    All your trying to do is create an integrator, a Low pass filter to remvoe all the unneeded harmonics of the square wave that make up the tones digitally.

    A simple dual series R/ shunt C, RC filter has always worked for me.

    Coming off of the Propellers output pin you have a series 1K ohm resistor, on the other end of this resistor, the end that is not connected to the processor, you will have a .1uf capacitor to ground.

    from the junction of the 1K ohm and shunt .1 uf cap to ground you have another series resistor of 1K ohm, at the unconnected end of this 2nd series 1 K ohm resistor you have a .01 uf capacitor to ground.

    The filtered sine wave output is at the 2nd 1k and the .01 uf to ground.

    To summarize a series 1K, a shunt .1 uf another series 1K and finally a shunt .01 uf.

    This will create a nice clean sine wave output passing all the required DTMf tones.


    Mike
  • WossnameWossname Posts: 174
    edited 2012-01-26 05:25
    I'll try that tonight, thanks for the tip Mike.

    I decided that the Duty mode method was more fiddly that I was willing to deal with. I could generate sound with it but it didn't sound right and caused some really funky patterns to appear on my scope.

    PWM will be more than enough for me I think.

    Thanks everyone.
Sign In or Register to comment.