Thursday, September 12, 2013

Generating low-distortion audio sine waves using a PIC and DDS techniques

Over the years I have collected a number of service monitors (see the postings about the IFR-1000 and Cushman CE-50A) but the one that I use most often is a rather strange bird, a Wavetek/Schlumberger 4031.

The problem is this:  Many amateur repeaters require subaudible tones for access, so when testing the receiver for things like SINAD, sensitivity, etc. it is necessary to generate both the subaudible tone and a standard 1 kHz tone - something impossible when you have exactly one tone generator, as is the case of my '4031 without this optional extra.
Figure 1:
The completed 1 kHz tone generator.
Click on the image for a larger version.

Fortunately, this "extra" tone generator need not do too much:  Simply generating a low distortion, 1 kHz sine wave will suffice!  After all, many service monitors have, as their "second" tone generator, one that generates only a 1 kHz tone!

The hardware:

I decided to throw a PIC at the problem, specifically the PIC12F683, an 8-pin processor that has quite a few useful features, most notably a hardware PWM generator and an A/D converter. I wanted this device to be quite small and battery-powered as it would be kept with the service monitor at all times.  Throwing a piece of paper on the workbench, I sketched out a circuit that quickly evolved into that depicted below in Figure 2.

The main power switch is Q1, a PNP transistor in series with the Batt+ lead and when SW, a momentary pushbutton switch, is pressed, Q1's base is pulled low through R2 causing it to conduct and provide power to the rest of the circuits.  Once the software in the PIC (U1) has determined that the button has been held down for a long enough time (>1 second) pin 7 is set high which activates Q2 which, in turn keeps Q1 turned on.  Diodes D1 and D2 provide isolation for the pushbutton so that the PIC can detect if the user is pressing the button independently of what Q2 is doing.

The PWM signal is output from pin 5 using the PIC's hardware, the DC is blocked with C8 and then low-pass filtered in two stages, first by R9/C9 and again by R10/C10 to both (mostly) remove the PWM's 20 kHz energy and also to somewhat attenuate higher-level harmonics of the 1 kHz tone itself.  R11 is used to establish an operating point for U2 and is derived from a mid-supply voltage source produced by R5 and R6 and filtered by C2 and ultimately used to bias both halves of U2 to a mid-supply voltage.

Figure 2:
Schematic of tone generator unit.  The only critical components are C10-C12 which should be
temperature-stable (plastic) units rather than ceramic.
NOTE:  There is an error in the schematic:  The anode of D1 should have been shown connecting
to the collector of Q2!  (I'll get around to fixing it some day...)
Click on the image for a larger version.
U2, a TS462, is a "rail-to-rail" op amp, this type being chosen to maximize the output signal level available from the limited supply voltage, particularly when the 9 volt battery is nearing the end of its useful life (approx. 7 volts for this application) and it is capable of driving 600 ohm resistive loads.  U2a is used as a unity-gain follower to buffer the rather high impedance output from the initial R/C PWM filtering (R9-11, C8-C10) and it feeds U2b which is configured as a 2 pole 1 kHz bandpass filter to further clean up the 1 kHz sine wave being generated.  Since U2b has some gain, the values of C10 and R11 were chosen to attenuate the input to U2a enough so that even at a relatively low battery voltage (7.0 volts) it avoids clipping when hitting the power supply rails, providing about 4.5 volts RMS.  C13 is used as a DC block on the output and R15 assures that the op amp's output will always see a resistive load to assure stability.

Preserving the battery:

One problem with portable, battery-powered devices that are used  infrequently is that they often get left on - either because they weren't shut off in the first place, or the power switch got bumped.  To prevent this, a momentary pushbutton switch was used so that a brief "bump" is less likely to leave it in the "on" state.  In addition to this, the pushbutton itself is physically recessed, making it less likely that something being carried along with the unit (e.g. connectors, tools, etc.) will push and hold the button in the "on" position and run the battery down.

Figure 3:
Inside the 1 kHz tone generator.  If you look carefully, you can
see the the blue "power" LED is illuminated.
Click on the image for a larger version.
To eliminate the other likely cause of a dead battery - forgetting to turn it off - the unit is designed to detect if its audio output actually connected to something.  To do this, R8 pulls pin 6, configured as an A/D input, up to the +5 volt rail and it, in turn, is connected via R16 to the audio output.  If the audio output is connected to a device with a resistive load on its input of less than 100k or so (such as the external audio input of the service monitor) the PIC will see the DC voltage on pin 6 as being below a software-predefined threshold (3/4 of the supply voltage) and it will remain powered up.  If the output is disconnected from a load, this voltage will rise above the threshold and if this condition persists for more than 3 seconds the PIC will set pin 7 low, turn off Q2, "un-bias" Q1 and disconnect the battery.

A software timer has also been implemented that will automatically turn off the unit after 30 minutes with an alert tone sounding 20 seconds before power-off so that the timer can be reset by pressing this button momentarily:  This feature was added just in case the unit was left connected to the service monitor and I happen to forget about it!

LED1 (a blue LED) is used used to show when the unit is powered up and since a high-brightness, focused-lens blue LED was used, only a milliamp or two (as set by R4) is needed to provide adequate power for it to be visible - even in bright light.  Finally, D3 and self-resetting 300mA thermal fuse F1 provide protection against accidental reverse voltage when one is fumbling about trying to connect the battery.

In total, the unit consumes about 12 milliamps (approximately 4 milliamps of this is U2) when operating and an undetectable amount of current (well under 100 nanoamps) when it is turned off.  What this means is that when powered down, the battery life will essentially be that of its shelf life - and if you happen to use a lithium 9 volt battery, that could well exceed 10 years!

The mechanical construction:

When I make a "one-off" project I almost never lay out and make a circuit board:  In the time it would take me to do this, I would have already completed the project in the manner shown, having wired it on a piece of prototype board that was selected to be just big enough to accommodate all of the circuitry.

As with all other projects that I build using through-hole techniques on prototype board, this material has an array of holes on 0.1" centers with small, etched copper rings around each hole on the bottom side to make both electrically and mechanically secure connections.  For interconnections I used #30 AWG "Kynar" wire-wrap wire, the advantage of this material is that soldering will "heat strip" the connections:  I've built hundreds of projects over the years using this technique and it has proven to be very reliable once one masters the technique!

In rummaging around my collection of project boxes I didn't find anything that was quite the right size so I determined the minimum footprint required to accommodate the board, the switch and a 9 volt battery and cut some pieces of double-sized glass-epoxy circuit board using a very heavy-duty paper cutter.  Soldering five pieces together (the bottom and four sides) I soon had a very sturdy box that was also well shielded from RF - an important consideration when using equipment at a site with many high-power transmitters!  In retrospect I could have made the box a bit "thinner", but this worked out nicely.

The board itself is mounted using two hexagonal metal standoffs from Radio Shack, each one having been sawed in half and then filed down so that the cut was flat and each was of equal height.  Since these standoffs are nickel-plated brass, they solder quite easily to the circuit board and make an extremely rugged support.

The sixth piece of copper-clad is the lid of the box, sized exactly the same as the bottom piece.  To attach it, two more hexagonal standoffs were cut in half and the four pieces were soldered into the corners as shown in Figure 3.  In the lid, matching holes were drilled to allow the screws included with the standoffs to be used to secure it into place.  Not shown is a small piece of foam that was attached to the bottom side of the lid with RTV ("Silicone") adhesive that keeps the 9 volt battery from rattling around when the cover is in place.

The momentary pushbutton switch was centered over a countersunk hole that I drilled in the side of the box as shown in Figure 1 and was initially tacked into place using a very small amount of cyanoacrylate adhesive ("Super" glue) and I was very careful to avoid getting any of it into the button's works!  Once this adhesive had set I soldered the pins of the switch that would connect to ground directly to the case for more mechanical support and then I used some epoxy around the switch for further reinforcement.  Next to the switch can be seen the blue power indicator LED (in the clear lens) which was epoxied into place at the same time as the switch.

The output cable is a piece of RG-174 coax that I found in my junk box with an already-attached male BNC connector.  At the BNC connector end of the cable I added two overlapping pieces of heat-shrink tubing to mechanically strengthen the crimp connection and, as can be seen in Figure 3, I also added a piece of heat shrink tubing at the point where the RG-174 entered the box through the drilled hole of the box to relieve strain there, too.  At this same point, a small wire tie was attached to the cable on the inside of the box to keep it from being pulled out while a piece of heavy wire was attached to the shield and connected to the case and the center conductor attached to the audio output.

The software:

A DDS (Direct Digital Synthesis) algorithm was chosen to generate the sine waves and with this technique one indexes a table containing a sine wave at a known rate and step size to generate an arbitrary frequency.

An article on the operation of a DDS may be found here:

I programmed the PIC's interrupt and the PWM rates to precisely 20.000 kHz - fairly easy to do with the 20 MHz crystal that I used - and wrote a DDS algorithm using 32 bit integer counters.  In doing the math, the use of a 32 bit "Frequency Control Word" yielded the following:

20 kHz sample rate / 2^32 = 0.0000046566 Hz frequency steps.

Clearly, this amount of resolution was far in excess of the stability and accuracy of the standard CPU-grade crystal that I used as the master timing reference as each "step" would have represented approximately 0.18 Hz at the 20 MHz clock frequency.  If I'd chosen to use 16 bit counters, instead, my frequency step size would have been 1/65536th of this, or 0.305 Hz and I'd have gotten 1000.061 Hz (about 1.2 kHz error at the 20 MHz crystal frequency) which would have been more than good enough, but since my little PIC didn't need to be doing anything else I figured that there was no harm at all in making it crunch 32 bit numbers!

For a Digital-to-Analog converter I used the PIC's built-in PWM generator which is capable of  approximately 10 bits of resolution when used with the hardware timing parameters that I'd chosen to achieve a 20.000 kHz sample rate, but I knew that, in theory, only 8 bits of resolution would be required to achieve an adequately clean sine wave - especially if I followed the output with some sort of audio filter.  What I ended up doing was to use the PWM in 10 bit mode and left-justify the 8 bit sine data and discarding the lowest two bits.

For more info on PWM techniques, read this article:

PWM has the advantage of being very easy to produce in hardware as it is simply a matter of timing the width of the output pulses and in so-doing, the output voltage (after smoothing) is proportional to the duty cycle of those pulses.  The use of PWM does throw in a bit of a complication when it comes to generating complex analog signals using simple hardware:
  • With simple R/C filtering the output voltage's rate-of-change may not exactly be what is expected for all frequencies at all amplitudes and slopes.
  • Simple PWM hardware/software has the problem that only one edge of the stored samples are being used rather than an averaged, "middle" value between two subsequent steps.
The upshot of these factors - particularly the second one - is that any sine wave generated using this method is likely to have some distortion, this being caused by the fact that the samples being generated are slightly offset in time from the actual "center" of the sample and the net result is that there ends up being a residual amount of phase modulation which, in turn, causes a slight amount of harmonic distortion.  The amplitude of these harmonics depends on several factors such as the PWM frequency, the sample rate (the two don't need to be the same, but it's a good idea that they be at least harmonically related to avoid other artifacts), the PWM resolution (and that of the sine table's entries), the actual size of the sine table, and the type of hardware used to filter the PWM output.

In my particular case I measured 0.7% total harmonic distortion + noise on the output of the tone generator - this, on the output of U2b, the 1 kHz bandpass filter.  While perfectly adequate for SINAD measurements out to 30dB or so, I decided that I could do better!

Note:  The bandpass filter reduced the 2nd harmonic's amplitude by approximately 25dB, so the distortion was actually worse than this at the output of U2a, "before" the 1 kHz bandpass filter.

Adding Predistortion:

In theory one could calculate these effects "on the fly" within the DDS algorithm and cancel them out but with the rather limited computational horsepower of the PIC there is only so much one can do - not to mention the amount of time I wanted to spend on this project!  As I was interested in  generating only 1 kHz for this particular project I could simply "pre-distort" the sine table itself, optimizing it for this one frequency.

Many years ago (when GWBASIC was still commonly used) I wrote a simple BASIC program that generated sine wave tables of arbitrary size and span and wrote them to a text file that could be imported into source code so I started with that, adding some extra terms to produce additional harmonics in the manner of the formula below:

   Amplitude = sin(w) + (a * sin(w * 2)) + (b * sin(w * 3))

  • Amplitude is the value of the sine output plus the distortion.  This gets scaled and offset according to the requirements of the sine table.  (e.g. for a table consisting of unsigned 8 bit values it might range from 0 through 255.)
  • w is the input value (in radians) scaled to the size of the table.  (e.g.  a full sine table with 256 entries would scale 0-2π radians to an index range of 0-255.)
  • a is the scaling factor for the 2nd harmonic's amplitude.
  • b is the scaling factor for the 3rd harmonic's amplitude.

One could add additional harmonics, but having only the 2nd and 3rd is enough for our purposes.

In this project I used an 8 bit, 256 entry sine table and using "a" and "b" I could introduce into this table some 2nd and 3rd harmonic distortion and depending on correction needed, "a" and "b" could be either positive or negative.

When adding these extra terms for the 2nd and 3rd harmonics with "a" and "b" I did have to slightly rescale the "span" of the output from 255 to 251 or 252 to keep the resulting values within the range of 0-255 since the harmonics did add a bit of extra amplitude to the overall sine output:  Ultimately I scaled the output to achieve a range of 1 to 254 since the use of 20.0 kHz PWM rate (a divisor of 250) rather than a 19.52 kHz rate (a divisor of 256) implied that my PWM hardware's resolution was actually just a hair under 10 bits.  (I actually tried it both ways and it didn't matter!)

Figure 4:
The "waterfall" display from the Spectrum Lab program showing the 1 kHz fundamental and up through the 9th harmonic after tweaking the sine table.  Not shown is the output of the script that displays the percentage distortion of the harmonics through the 6th and the totals.
Click on the image for a larger version.

Determining scaling factors "a" and "b":

For determining the "cleanliness" of the sine wave I used my desktop computer with an Asus 24 bit sound card running the "Spectrum Lab" software to analyze the harmonics on the output of U2b.  Spectrum Lab has a built in, interpreted scripting language (see "Conditional Actions" in the Spectrum Lab documentation) and with it I wrote a simple program to determine the precise frequency and amplitude of the peak output (nominally 1 kHz) and measure the amplitude of each of the harmonics through the 6th, individually determine their power contribution (and thus,  percentage content) and display those values and their sum to yield an approximate THD (Total Harmonic Distortion) value.  (The measurement taken with Spectrum Lab did not include noise at frequencies other than the fundamental and the harmonics through the 6th so it was not a "THD+Noise" reading.)

Another instrument that I had handy, also connected to U2b's output, was an old HP-332A distortion analyzer.  This device, made in the mid/late 1960's, is still useful today and can measure the distortion+noise of a signal as low as 5 Hz and as high as 600 kHz.  A bit finicky to operate (it takes a gentle touch and some practice) it will reliably measure distortion+noise down to 0.02% or lower.

I determined, through rough calculation of measured harmonics with a "pure" sine table (e.g. no added harmonics) and then through later iterative means that a reasonable value for "a" was +0.085 and "b" was +0.001 - but your mileage may vary!

In using both Spectrum Lab on the computer and with the HP-332A I measured well under 0.035% distortion at the output of U2b, the 1 kHz bandpass filter, with each method:  With a bit of additional tweaking I may have been able to reduce the distortion even more, but I was approaching the point of diminishing returns and I was starting to approach the limit of the HP-332A, anyway!

Figure 5:
The 1 kHz tone generator connected to the input of the
service monitor and operating.
0.6% distortion is about as low as this service monitor will measure
 - at least until I get around to tweaking it's notch filter....
Click on the image for a larger version.

At the output of U2a, prior to the 1 kHz bandpass filter, Spectrum Lab showed that the harmonic distortion at the end of tweaking was on the order of 0.4%, but the bandpass filter reduces the 2nd harmonic by about 25dB and the higher-order harmonics (and noise) by even more.

The results:

The upshot of this is that with this tone generator, the ability to measure the SINAD exceeds that of the service monitor (it reads in excess of 50dB when the generator is connected to the input) and it is, in fact, "cleaner" than the instrument's own built-in tone generator which is on the order of 0.1% THD+noise.


This page stolen from

No comments:

Post a Comment


While I DO appreciate comments, those comments that are just vehicles to other web sites without substantial content in their own right WILL NOT be posted!

If you include a link in your comment that simply points to advertisements or a commercial web page, it WILL be rejected as SPAM!