I want to build a circuit that can generate sine waves at frequencies controlled by a computer or a microcontroller. I would like to go as low as 0.01 Hz (down to 0.05 Hz would probably be acceptable) and as high as 100 kHz; I need at least 10 frequencies per decade, which is a resolution of roughly 12 mHz at the bottom of the scale (or 60 mHz if the bottom is 0.05 Hz). The output voltage doesn't need to be high - I'm going to run it through some op-amps afterwards anyways.

What is the standard way of doing this? Is DDS the way to go (using either a sine lookup table on a uC or an IC like the AD9850)? Is there a simple analog solution that I'm missing?

I would love to stick to through-hole parts if I can.

  • 2
    \$\begingroup\$ My knee-jerk reaction would be to use a DDS for this. By the way, what's your desired resolution in frequency? \$\endgroup\$ – Nick Alexeev Jan 5 '15 at 19:47
  • \$\begingroup\$ Yeah for the low frequency end you can forget analog. There is always a transient/ turn-on with an analog oscillator. It will last at least a few cycles. For ~$400, Rigol makes a nice sig. gen. that does milli-Hertz to 20 MHz. \$\endgroup\$ – George Herold Jan 5 '15 at 19:53
  • 2
    \$\begingroup\$ TI's AN-263 Sine Wave Generation Techniques has a nice "menu" on p.4 from which you can pick your favorite depending on the freq. range. For yours there are several designs possible. Distortion and stability are also among the factors to consider when picking a solution (but you haven't touched that). \$\endgroup\$ – Fizz Jan 5 '15 at 19:55
  • \$\begingroup\$ @NickAlexeev: I added some information on the resolution. I need at least 10 points per decade, so the second lowest point is ~12 mHz higher than the lowest. \$\endgroup\$ – Greg d'Eon Jan 5 '15 at 19:55
  • \$\begingroup\$ Alas, your requirement to have a 10M:1 sweepable range (this is how I interpret "controlled by computer") kinda excludes most single-chip analog classics like the XR-2206, ICL8038 and so forth (most of which have been obsoleted by their manufacturers, but can still be found as surplus)... unless you can live with multiple adjument pots as shown for example at youtube.com/watch?v=KPtsgFw5Fno You could presumably build the micro-controlled equivalents of those pots, but it's not as easy as sending bits to a DAC. On the other hand, these oldies are available in DIP. \$\endgroup\$ – Fizz Jan 5 '15 at 21:17

You could easily do a highly flexible DDS on an STM32F4 Discovery board for ~$15 using an internal DAC, DMA, a timer and a sine lookup table. People have blogged examples of similar things if you look for them.

In order to get the required frequency (the STM32F4xx DAC's can only do 300ksps at full swing, which equates to ~1V/\$\mu\$s) you will need to constrain the range of the DAC.

For a sinusoid, maximum slew rate (in V/s) is \$2 \pi \times f \times A\$. Inserting the values from the OP's requirements and assuming Vref of the DAC is 3.3V (which if I recall correctly is the case for an STM32F4Disco), a 3.3Vpp sine wave at 100kHz, max slew rate is \$2 \pi \times 10^5 \times 3.3 / 2 = 1036726\$V/s, or \$\approx1.04\$V/\$\mu\$s.

In order to comply with this constraint, the sine wave's amplitude has to be limited, from \$3.3\$V to \$3.3 \times 1 / 1.04 = 3.18\$V.

This now brings in the apparent issue of the 300ksps limit on the STM32F4 DAC. That limit is a furphy. I don't know what the actual physical upper limit is, but I suspect it's the APB1 bus speed. I do know (because I've done it) that you can write at least 2Msps to the DAC and as long as you respect the 1V/us slew rate it will behave predictably. So, you can do 16 samples per cycle for a 100kHz sine wave, a 1.6Msps update rate, as long as you limit the sine wave amplitude to 3.18V instead of 3.3V.

At some point you're probably going to have to deal with digital pots because the reality is that if you want a smooth, continuous output signal, particularly at low speed, then you're going to have to run your DDS through a filter, and that filter is going to have to be adjustable - you can't just put a 100kHz LPF on it and expect it to be useful at sub-1Hz frequencies.

| improve this answer | |
  • \$\begingroup\$ Great information. You're right about the low pass filter - I'll have to experiment and see what works for the sub-1 Hz range. \$\endgroup\$ – Greg d'Eon Jan 5 '15 at 23:27
  • \$\begingroup\$ Hmmm, does Rigol and other inexpensive kit really try and LPF the milli-Hz stuff? At 10 bit what sort of TC do I need for 1 Hz? (~1ms?) And doesn't the filter also make a phase shift? \$\endgroup\$ – George Herold Jan 6 '15 at 0:09
  • \$\begingroup\$ @GeorgeHerold I have no information about how (or if) Rigol deals with filtering. TC? \$\endgroup\$ – markt Jan 6 '15 at 0:16
  • \$\begingroup\$ Oh sorry, of course you don't. Does anyone filter milli-Hz DDS sine waves? TC = time constant. (R*C) (I'll look at the rigol tomorrow.) \$\endgroup\$ – George Herold Jan 6 '15 at 0:21
  • 2
    \$\begingroup\$ Regarding filtering, it may be possible to use a fixed frequency lpf tuned for the high frequencies, and dither the lower frequency case at high frequency. That is, if output value is supposed to be, say, 4.3 lsb, output 4454454445 to dac. This increases resolution as well. \$\endgroup\$ – Nicolas D Jan 6 '15 at 8:36

Here's my (RF's) rough summary of the DDS solution, which was initially suggested by Nick Alexeev. I'm marking this as community wiki, so feel free to improve with details etc.

Using AD's calculator, in order to get the desired balance between the 12mHz frequency resolution (which I'll just round to 10mHz) and a resnoably smooth curve at 100KHz output, you need about 10 to 40Mhz DDS clock, with 20Mhz looking like a good middle ground. At lower than 10Mhz clock, the output of the DDS at 100KHz starts to look quite noisy. At higher than 40Mhz clocks, the resolution gets too coarse; at 40Mhz clock you get a little less than 0.01Hz change for every tuning bit, in the low range of course; the tuning word being a clock divider, it produces a non-linear frequency curve.

As for practical solutions, one can find DDS chips already mounted on Arduino-compatible shields (for around $5 it seems); the catch however is that they may come with a fixed (and possibly unsuitably high) clock, but that can be improved upon with some board rework.

Also worth mentioning is that if one is using a microcontroller (uC) that has a built-in and sufficiently speedy DAC, then adding a DDS (which is basically an ASIC sweeping a sine lookup table and sending that indexed value to a DAC) is rather pointless since the sine lookup can be implemented in the uC software. For more details on this integrated-DAC approach see markt's answer.


I've used a design for a non-digital oscillator that produced decent sines down to below 0.1Hz and to above 100kHz. Theoretically it was an LC parallel tuned circuit in the feedback path of an amplifier. The L and the C were actually precision gyrator circuits (which is why they were able to be tuned to such ridiculously low resonant frequencies). You'd never build one with real inductors and if you did it would be non-tunable.

Both "C" and "L" were kept tracking by using a precision dual-gang pot and, if I remember correctly, a frequency range of over 50:1 could be got from the pot before changing fixed capacitors in the gyrators.

The pots of course would be better served by digipots these days as these can "track" much better than regular pots. I'm sure with care, it could work down to 0.01Hz.

Inductor gyrator: -

enter image description here

There are higher quality gyrators (better frequency response) and here's another link to a document about a different sort of gyrator. The beauty of the single op-amp gyrator in this application is that the CR network (as normally intended to be parasitic) can be used effectively as the tuning section making the L and C in parallel via small series resistors.

| improve this answer | |
  • \$\begingroup\$ I've never heard of gyrators before. This is really cool stuff, but it sounds a lot more difficult to get right than a DDS solution. \$\endgroup\$ – Greg d'Eon Jan 6 '15 at 13:24
  • 1
    \$\begingroup\$ Take a look at the additions and the link. \$\endgroup\$ – Andy aka Jan 6 '15 at 13:38
  • \$\begingroup\$ That link is extremely helpful. I'm still a bit scared of trying to do this in the analog world, but this looks like useful info. \$\endgroup\$ – Greg d'Eon Jan 6 '15 at 13:46
  • \$\begingroup\$ Sure, this is one of the several analog solutions that would work... but this is going to be just as difficult to interface to a computer as a XR-2206 etc., which Kynit rejected off the bat in the comments below his question. Are there DAC-controlled gyrators that would make this easy for his application? \$\endgroup\$ – Fizz Jan 6 '15 at 14:21
  • \$\begingroup\$ @RespawnedFluff digipots would allow control as said in my answer. \$\endgroup\$ – Andy aka Jan 6 '15 at 14:37

One approach would be to clock a 28bit adder/accumulator with a 4 Mhz clock. A uController driving the low order 20bits with a digital word and the top eight bits feed addresses to an eprom for a 256 entry sine look up table. The data bits from the eprom summed into an R2R ladder would capacitively couple to your op amp gain stage. Drive a high value from the micro into the adder and the high order bits cycle faster, for a higher frequency sine wave. A low value takes a lot more clock cycle to step make a count occur in the top eight bits driving the eprom. With a little extra work in the micro software; you can make the eprom table smaller by just storing angles from 0degress through 90. Just read the table forwards for the first 90 degrees (quadrant 1) then backwards for quadrant 2 forward again for quadrant three etc.

| improve this answer | |
  • \$\begingroup\$ I'm guessing the "selling point" of this solution is avoiding to buy/use a DAC IC and instead implementing it as that R/2R ladder? \$\endgroup\$ – Fizz Jan 6 '15 at 1:05
  • \$\begingroup\$ @RespawnedFluff No sales pitch. I just thought of this approach because of the through hole parts comment. \$\endgroup\$ – steverino Jan 6 '15 at 1:15
  • \$\begingroup\$ Well, DACs in DIP package are still available for sale from multiple manufacturers... \$\endgroup\$ – Fizz Jan 6 '15 at 1:38
  • \$\begingroup\$ So I'm using a timer onboard the uC to increment a counter off the uC to figure out which voltage to output? Why not keep it all onboard? And why a ladder instead of a DAC? \$\endgroup\$ – Greg d'Eon Jan 6 '15 at 3:04

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.