Please help, precision 1kHz sine filter

Status
Not open for further replies.

Mr RB

Well-Known Member
Hi, I'm making a "precision" 1kHz sine wave generator, using a PIC 16F628 and 20MHz xtal.

Goals;
1. Sine freq 1000Hz high freq accuracy, xtal locked
2. Sine amplitude "exactly" 2v p/p set by 5v regulator and trimpot good enough
3. Sine distortion as low as possible using simple external filter parts
4. Low-ish output impedance to connect to audio amp inputs etc
5. Minimum parts as it is an open source project for everyone

The xtal has been trimmed to 20Mhz better than 1PPM, and the 1kHz sine is generated by PIC PWM with 50 entries in a jitter-free sine table at exactly 20uS per entry. The sine table I made in Excel is shown below.

The PWM has a resolution of 100 steps, and sine table runs an amplitude of 73 PWM steps from PWM of 14 to PWM of 86. It is equally distributed +/- from PWM 50 so there is no distortion and each sine sample has been rounded the correct direction so amplitude error in any sine PWM sample is less than about 0.68% of the total amplitude.

The idea is that since the PIC and mathematical sine tabe already produces excellent frequency and good basic sine shape (ie the hard stuff ie done), so that addition of a simple passive filter will be all that is needed.

The PIC sine part is working perfectly and it generates a sine from the 50 samples with an exact freq of 1kHz (around 1000.0000 Hz +/- 0.0005Hz).

The PIC hardware is simplicity itself at this point, just the 0v-5v PWM coming out the PIC pin, and I tacked a trimpot and 0.22uF cap RC filter on that for testing.

The trimpot was adjusted to take out the bulk of the hash without reducing the amplitude or changing the shape of the sine. RC filter as seen in the photos below; 482 ohms, 0.221uF, sine amplitude 3v p/p.

Now the question!
I have lots of parts avaliable including toroid formers and quality caps of different types, cap and inductance meters etc, and a 'scope, but no proper distortion measuring equipment. What would be the best simple passive filter to attach to this PWM output to give the desired "low distortion" result at 1kHz 2v p/p?

My filter design knowlege is poor, limited to googling "Chebychase filter calculator" on some rare occasions... (grin)
 

Attachments

  • sine_gen_1kHz_1.jpg
    66.3 KB · Views: 667
  • sine_gen_1kHz_2.jpg
    27.8 KB · Views: 695
  • sine_50_1kHz.gif
    9.6 KB · Views: 923
Last edited:
Thanks I'll look into that. But even with a filter calculator I'm still likely to enter the wrong values or something.

It will be easy enough for me to filter that output a bit more to make it look perfect on the 'scope but I really would like some input from someone with experience, on a filter that will guarantee a low distortion output given the present state of the circuit.
 
Active filter or passive filter, you need a filter. You need to remove all noise above 1khz with out effecting the 1khz much.
Add a 1khz low pass filter. If you are off in the values and you make a 2khz filter it will work just fine. If you make a 500hz filter the 1k will be down some. So the frequency is not critical but better if you are a little high.
The goal is to pass the 1k and kill the 50khz and its harmonics.
 
Hi there MrRB,


I have found a bandpass filter works pretty well for filtering even a square wave into a nice sine wave, so with your pulsed wave it should work even better.
Maybe an inductor / capacitor filter if you have the parts.

I know you have already done some of the basic digital ground work, but i can offer a few extra hints if you care to reexamine your approach just a little bit.

Point1:
A sine pattern is symmetrical in a few different ways. As i am sure you know, it has the same shape above zero as below zero. It also has the same shape over a 90 degree angle, except in reverse: 0 to 90 is the same as 90 to 180 except the amplitudes are reversed. These two symmetries alone mean that we really only have to store the pattern for the sine from 0 to 90 degrees, changing only the order we look up the values in for the 'reversed' segments. What this means overall is with the same memory space we can get a higher resolution pattern.

Point2:
We dont really have to store the pattern itself, if we want to we can generate the pattern on power up and store the calculated values in 'ram' space. This can make up for differing power supply levels or whatever if needed, or just used to get a good pattern without storing everything beforehand.

Point3:
The levels near the peaks of the sine are more important from a distortion point of view than the levels near the zero points of the sine wave. This means accuracy near the peaks is much more important than near the zero cross areas, and so more attention should be paid for the pattern near the peaks.

Point4:
With point 3 in mind, dithering might help the distortion near the peaks, if you care to get into that of course.

It might be interesting to run a harmonic analysis on your pattern to see what the total harmonic distortion is before and after the proposed filter. Do you have the actual numbers for the pattern available?
 
Last edited:
My very low distortion (0.002%) sine-wave generator circuit starts with a stepped sine-wave made from a CD4018. It uses 3 resistors to make a sine-wave with 10 steps. It is filtered with a switched-capacitor lowpass filter IC plus a high frequency Sallen and Key lowpass filter to remove the clock frequency.

I tried to make it have a voltage-controlled frequency with a CD4046 phase-locked-loop IC but the PLL oscillator has jitter which increases the distortion a lot.
 
Ronsimpson, cool, so if I just make a LC filter with a couple of poles set to 2kHz that should get a good result without causing any shape distortion of the sine wave? It's 3v now and I need 2v p/p final so there is a bit of headroom to play with.

MrAl, thanks for the tips. I did a sine generator before where the table was 1 quadrant and used inversion and doubling to get the full sine wave. The limitation in this case was the 20MHz PIC runs at 5 MIPS so the 50 entry sine table has only 20uS (100 instructions) per sine entry and per PWM cycle. There's no time for any niceties like smoothing with a PIC 16F.

I'm not too worried about the per-entry sine amplitude distortion, even the first crude RC filter has smoothed out the 0.68% max amplitude errors in any one entry, you can see the difference in the Excel sine (with the little amplitude errors) vs the RC filtered sine where those little errors are basically gone due to the overall integration.

Code:
Here are the 50 PWM sine table entries;
50
55
59
63
67
71
75
78
80
83
84
85
86
86
85
84
83
80
78
75
71
67
63
59
55
50
45
41
37
33
29
25
22
20
17
16
15
14
14
15
16
17
20
22
25
29
33
37
41
45

I expect the distortion on these will be a bit high due to the low PWM resolution of 73 PWM steps for the whole sine wave. Again this is mainly a limitation of the PIC 16F, I can go to a 18F series at 10 MIPS and pretty much double PWM resolution and/or sine entries, but I would like to keep this to a 16F628 for now as that will be of use to hobbyists.

Audioguru, thanks for the info. Interesting that you can get an output that low in distortion from a 10 step original wave! I take it that is 5 steps per half wave?
 
Last edited:
Audioguru, thanks for the info. Interesting that you can get an output that low in distortion from a 10 step original wave! I take it that is 5 steps per half wave?
Yes the original wave has 5 steps for each half-cycle. An 8th order switched capacitor butterworth lowpass filter IC removes harmonics very well. You can feed a square-wave to one and get a low distortion sine-wave output (with a small amount of clock frequency that is 100 times the sine-wave frequency).
 


Hi again MrRB,

Ok let me make sure i understand your pulse generation scheme here...

For the first pulse which is 50, you generate a '1' output for 50 instruction cycles, then output a '0' for 50 more instr cycles, then
for the second pulse which is 55 you output a '1' for 55 instr cycles, then output a '0' for 45 more instr cycles, then
for the third pulse which is 59 you output a '1' for 59 instr cycles, then output a '0' for 41 more instr cycles, then
etc., etc.,
until you get to the last and then repeat.
So in general you output a '1' for the table entry and then a '0' for 100 minus the table entry.

Is this correct?

The reason i ask is because i want to make sure i have the right pattern to analyze. We can then compare the harmonic distortion output using various filters and see which one is best.

Also, what is the value of your test resistance and capacitance for the test filter shown in the picture, and what is the amplitude of the sine in the scope picture (scope vertical main grid scale)?

Also, what is the minimum output resistive load you wish to be able to apply without losing too much amplitude? Is 10k ok or do you need more like 1k or 600 ohms?
 
Last edited:
AG, could you...?


Hola AG,

I do not want to derail this thread. Just to ask you: could you post a link to your circuit, if available? Working on a similar circuit right now.

Gracias.
 
Hola AG,

I do not want to derail this thread. Just to ask you: could you post a link to your circuit, if available? Working on a similar circuit right now.

Gracias.
Sorry. I made the circuit many years ago before I got a computer so the schemaric is sketched on paper somewhere. The National Semi switched capacitor filter ICs are not made anymore but today Maxim-IC sell similar ones.
 
Hi Mr RB,

Found this thread this AM, and have been intrigued by the responses so far. So between shopping with my wife and sharing our laptop (on the road in Montana), I have been working on your question. I know you said you wanted a passive filter for your design, but the cost and real estate required might be a burden. So I'll present an alternative for your consideration.

As Eric recommended, FilterPro is a very good resource. Also, as Mr Al recommended, a bandpass filter is a very good solution for resolving THD to the minimum level with a squarewave input as I have also found.

So I ran a sims in LTSpice for both a 1kHz square wave and the PIC output you described using a 6th order BPF with a Butterworth response, a Q of 20, a gain of 1 and a bandpass of 100Hz. The filter with a 1kHz squarewave had a THD of 0.237%. The second harmonic at 3kHz was dominate at ~60db below the fundamental, which was to be expected with the squarewave input. However, with a simulated PIC input to the BPF, as I believe you indicated, the THD dropped to 0.0086% with the 1st harmonic at ~84db below the fundamental and the 2nd harmonic ~91db below.

This option would seem to meet your criteria, but is not a passive solution. Hope this is some help.

P.S. I'll attach the sim of the PIC input. It is not the exact 2V P-P output you cited, but with a spare amp you can set the gain at output for the output level desired.

Cheers!

EDIT: Just thought to sub a LM6144B quad for the AD822 dual (cheaper unit cost), both being rail-rail amps and it came up with a THD of 0.0069%. However, the second harmonic did come up to ~88db below the fundamental vice ~91db with the AD822.
 

Attachments

  • PIC.jpg
    319.7 KB · Views: 546
  • PIC_FFT.jpg
    187 KB · Views: 532
  • PIC_THD.jpg
    304.5 KB · Views: 550
Last edited:
Hi Audioguru, it's great that you got such a good result from quite a flawed original signal using a high tech filter. With this project I'm trying to do the reverse in that the PIC and math sine table can generate a pretty good sinewave at the source, and all the filter really needs to do is remove the 50kHz hash with (hopefully!) a low tech filter. The idea (like most of my web page) is to get good performance from simple and very low end "hobby" hardware.

MrAl, yes you understand the table correctly. The table is basically in PWM % (0-99) and total 100 PWM steps always takes 20uS.

Original RC values in post #1 was; 482 ohms, 0.221uF, sine amplitude 3v p/p. For output impedance I would like the entire device to have an output impedance of about 1k if possible so it's suitable to drive most audio gear, and drives 2v p/p into infinity ohms. Ideally I really wanted to avoid any active filter if possible, from a PIC hobby level that extra complexity is probably the difference between people actually building it or just giving up.

MRCecil, wow I appreciate all the work you did and it's impressive to see those distortion figures! But I think this goes way beyond the "PIC hobby throw something together" level. That's my fault as I did talk about precision sines and very low distortion etc... But even just adding one 8pin opamp to the circuit negates a lot of the value of just connecting a few discretes to a PIC and having a finished result. I would really like to explore the performance possible from just adding the simplest passive filter that any hobbyist can put together.
 
3-stage RC filter test

After checking a filter calc it looked like inductors are well in the mH range, which rules out an easy hand-winding toroids and also rules out most hobby inductors people may have salvaged etc.

I spent a couple hours trying some filter options just using RC components as a baseline for the minimal hobby parts approach. The goal was to remove most of the 50kHz hash with the first stage while keeping the sine shape good, then apply very minimal filtering after that to just clean up the 50kHz remnants but not drop the amplitude or change the sine shape much.

I tried to keep stage 1 low impedance to allow driving the other stages and still keep output impedance lowish. The lowest imedance the PIC could directly drive was about 330 ohms into 0.33uF. Any more load than this caused the sine to distort (thicker) on the bottom due to the PIC pin FET drivers. Obviously the NFET that pulls the voltage down works better than the PFET driver that pulls the voltage up. But at 330 ohms->0.33uF the sine still looks good. With 220 ohms->0.33uF I could just see the sine starting to distort.

Here was the first RC filter that seemed to work ok and the 3 'scope test points;
330 ohms -> 0.33uF (A) 330 ohms -> 0.068uF (B) 820 ohms -> 0.068uF (C) -> 2v p/p output at no load

The waveforms are below, first photo shows A and B together, second photo shows B and C together. C is 2v p/p. The 2 final stages were chosen to JUST remove all the 50kHz with (hopefully) minimal effect on the sine itself.

Output impedance was tested at 951 ohms.
 

Attachments

  • sine_gen_1kHz_3.jpg
    28.1 KB · Views: 487
  • sine_gen_1kHz_4.jpg
    28 KB · Views: 486
Last edited:
Hello again MrRB,

Ok, a harmonic analysis of the pattern and filtered pattern (R=220 ohms, C=0.22 uf) and filtered pattern with those values and 1k load resistance produced the following results:

Without filter:
THD=0.3 (up to 157th harmonic)

With filter but no load:
THD=0.05 percent (with maximums at 49th and 51st harmonics about 0.01 percent each)

With filter and 1k load resistance:
THD=0.06 percent (with maximums at 49th and 51st harmonics about 0.01 percent each)

Contrary to popular misconception, theoretically there is zero 50th harmonic present. This is typical in these kinds of patterns. There are always strong components adjacent to the carrier however, in this case as shown above the 49th and 51st come in at around 50 percent each for the raw pattern, but no 50th harmonic as the symmetrical properties of the pattern cancel out the 50th.

The calculations for the THD were done up to the 157th harmonic. Higher harmonics dont produce any appreciable difference in the filtered pattern THD so that limit was chosen. The slight ramping of the rise and fall times will mean even less contribution from high frequencies anyway.

BTW you are using a single ended output (one PIC pin) right, not two pins for the output as in a bridged arrangement?
If so, i guess you expect people to capacitively couple the output then to get a zero DC output?
I ask because in the tests i've done in the past using frequency generators many times i needed the output DC to be adjusted to zero.
 
Last edited:
Wow THANK YOU very much for running the numbers on that!

I checked out the TI filter program download but it required me to register (Bah!).

I'm quite surpirsed the THD was down to 0.05% even after just that first filter! But that's good.

Yes you are correct it needs an output cap to decouple the DC from the output.

Which program did you use to do the filter analysis? Would you mind putting the 3 stage filter in and get the results from that?

I did a little more testing and added a 2.3mH inductor in the first stage, this took about 60% of the hash out compared to no inductor. I didn't want to use a tiny high value inductor and had limited choiced in decent sized toroids in mH range so that was a "good enough for now" solution.

I photo'd the waveforms and also normalised the amplitudes to better compare the wave shapes. Results are below.

Wave photoss= points A+B, points A+C, points B+C
 

Attachments

  • sine_50_fil2.gif
    8 KB · Views: 912
  • sine_gen_1kHz_5AB.jpg
    9.8 KB · Views: 480
  • sine_gen_1kHz_5BC.jpg
    10 KB · Views: 481
  • sine_gen_1kHz_5AC.jpg
    10.3 KB · Views: 478
Last edited:

Audioguru's starting waveform is a stepped approximation to a sine wave, as in carbonzit's in another thread.

Here you describe Audioguru's starting waveform as "flawed". In carbonzit's thread, you said "Carbonzit the linear resistance from the IC will give voltage steps, which is basically the same type of output as any typical DAC that makes stepped voltage output. That will be slightly better than PWM as it has less ripple and also better as it can be done faster."

Actually, a stepped approximation is much better (less flawed) than a PWM approximation because it can be more easily filtered. The harmonic content is much lower with the stepped version. See the attachment comparing your PWM waveform with a stepped approximation (I used fewer intervals to make it easier to see the PWM waveform).

Also, your filter has two RC stages with essentially the same impedance level for each stage. This is not a good filter. You will get better results if you make the second stage have a 10 times higher impedance level (make the R 10 times larger and the C 10 times smaller in the second stage). This will, of course, increase the output impedance of your filter and make it less able to drive low impedance loads without upsetting the filter performance; this is a good reason to have an opamp output buffer, which could also be used to make a better filter.
 

Attachments

  • ForumTHD_PWM.png
    7.8 KB · Views: 513
Last edited:

I understand that completely. I have been working with ADC and DAC waveform conversion for at least 20 years.

If you misunderstood what I meant by "slightly better" it was not just in reference to the ripple voltage. I stated the ripple voltage would be less with the DAC. But PWM as a precision solution has a major benefit as the timed periods are xtal locked and technically have zero error in the generated average voltage. The DAC (even if it had 1% resistors) will only approach 1% accuracy as the voltage is always affected by more than 1 resistor. I said "slightly better" in reference to both factors. DAC is faster and less ripple, PWM is less parts count and higher precision.


Agreed, it's not a "good filter" by any means. But I did not arrive at those parts values from tossing a coin. It took a couple of hours of substituting many parts values with very specific goals; keeping the overall impedance as low as possible, keeping the output amplitude high (ie 2v p/p) and JUST removing the 50kHz hash with minimal effect on the waveform.

You may note I decreased the 1-2 stage loading by going to a much smaller cap on stage 2 and the 2-3 stage loading by going to a larger resistor on stage 3. The filter works well for accomplishing those filter goals and importantly to the original design goal does not require an opamp.

...
...and make it less able to drive low impedance loads without upsetting the filter performance; this is a good reason to have an opamp output buffer, which could also be used to make a better filter.

Agreed again, you can make really nice filters with opamps.

But MrAl already calculated that the first stage filter had less than THD=0.05 percent, and the first stage has since been improved by changing parts values and adding an inductor. The two smaller stages added mainly to remove the 50kHz hash should have improved that THD figure further... I'm curious what the THD figure ended up at but based on the shape of the waveforms in post #16 I'm thinking it might already be good enough with just this "technically bad" passive filter.
 
Hi MrRB,

I wrote the program myself to calculate all the harmonics up to a certain point like 157 for any entered pattern, although for a pattern this complex i use another small block of code to convert the numbers of the pattern into a form which the base program can understand. The actual run time though is less than a second.
The filter section is analyzed separately into a mathematical form which the base program can deal with more easily. It's just a simple input output analysis really. I could combine this part into the base program but it's not to hard to do this way and i dont have to do this kind of analysis much anymore anyway

I'll stick in the more complex filter and see what numbers we get out of that. Of course with more filtering like that we'll get better numbers on the THD, but with the higher last stage resistance we'll get more loading with the assumed 1k load resistor.

I agree that you can generate a nice sine with a voltage stepped pattern, but that would also take more hardware.

One more little question, what is the series resistance of the inductor alone that you are using (not the 330 ohm resistor, but the internal resistance of the inductor) ?
Is there anywhere on line i can see the spec's for this inductor?
 
Thanks for getting back on that. I assumed you were using a standard circuit simulator etc, that's impressive you wrote code to do it!


It doesn't have to drive a 1k load, the typical audio input might be from 10k to 500k. I wanted around a 1k *output* impedance so it would be ok to drive most workbench applications (signal injecting etc) without needing the complexity and possible distortion of an output amp. A more reasonable test load might be 10k?

... One more little question, what is the series resistance of the inductor alone that you are using (not the 330 ohm resistor, but the internal resistance of the inductor) ?
Is there anywhere on line i can see the spec's for this inductor?

Sorry it's old stock and I don't have datasheet. My box of these inductors has some specs on it from my original testing, they have DC 1.2 ohms so there are two that makes 2.3mH and 2.4 DC ohms. They are toroids about 12mm core with about 250 turns of 0.3mm wire. For the calc you can probably just spec it as a perfect inductance? It dropped the 50kHz hash by about 70% on the 'scope so that roughly matches XL at about 800 ohms as would be expected.

I've also been using a 10uF 25v NP electro as the output decouple cap, that made about zero difference on the scope with the loads I tested, so it's probably not worth including either? I feel bad that you have to manually code these parts in I originally thought it was one of those cut and paste spice simulators etc.
 
Last edited:
Status
Not open for further replies.
Cookies are required to use this site. You must accept them to continue using the site. Learn more…