DDS Musings: AD9850 and AD9851

The general idea is to build a specialized sine-wave source as part of a test fixture to measure quartz crystal / tuning fork resonators in the 10 kHz to 100 kHz band. AD9850 / AD9851 DDS modules are cheap & readily available, albeit with crappy two-layer PCB layouts and no attention to signal integrity:

AD8950 DDS module
AD8950 DDS module

Documentation seems scanty, at best. The Elecfreaks page may be as good as it gets, with a summary:

Serial mode just need connect GND,D7 WCLK, FQUP, REST, VCC, I-R

More doodling will be required.

Because the AD9850 has an upper clock limit of 125 MHz, of course those boards sport a 125 MHz oscillator-in-a-can. The AD9851 has a 180 MHz limit and an internal 6× multiplier, so it gets a more reasonable 30 MHz oscillator and can run at either 30 MHz or 180 MHz.

The included 70 MHz (?) reconstruction filter won’t do much to improve a 60 kHz signal. A much much lower outboard lowpass filter will be in order.

As far as the AD9850 goes, the output frequency comes from a 32 bit value determining the phase increment:

f = Δφ · osc / 232

Where

  • f = output frequency
  • Δφ = phase increment
  • osc = oscillator frequency (30, 125, or 180 MHz)
  • 232 = DDS phase counter width

The smallest frequency difference between successive phase increments is thus osc/232, which is 0.029 103 83 Hz at 125 MHz. Obviously, you can’t get nice round frequencies like 60.000 kHz, except by accident, but you can get close.

Alas, the resolution conflicts with tuning fork characterization, where you (well, I) want to step the frequency in nice round 0.1 Hz units across a 2 Hz range around 60.000 kHz. Because the crystal characterization requires closely spaced frequencies, where the difference between the test frequencies matters, you shouldn’t work from the nicely rounded frequencies on a display.

For example, successive values of Δφ produce these frequencies near 60 kHz:

  • 2 061 580 → 59.999 874 793
  • 2 061 581 → 59.999 903 897
  • 2 061 582 → 59.999 933 006
  • 2 061 583 → 59.999 962 104
  • 2 061 584 → 59.999 991 208
  • 2 061 585 → 60.000 020 312
  • 2 061 586 → 60.000 049 416
  • 2 061 587 → 60.000 078 520

In an ideal world, you could pick an oscillator frequency to produce nice increments. For, oh, say, 0.025 Hz increments, all you need is osc = 0.025 × 232 = 107.374 182 MHz. Riiiight.

The computations require more numeric resolution than built-in Arduino data types and math operations can provide. Floating point numbers have 6-ish significant digits (double is the same as float), which cannot represent the Δφ values or frequencies. Unsigned integers top out at 32 bits (unsigned long long int is not a thing), enough for 9 significant digits that can hold the Δφ values, but integer multiplication and division do not produce 64 bit results and overflow / underflow without warning.

Other than that, an Arduino would be just about ideal: the generator needs a small display, a knob, and a few buttons.

Perhaps storing precomputed Δφ values for specific frequencies in a table, then computing nearby frequencies as offsets from that value would suffice. This will require doodling some absurd significant figures.

11 thoughts on “DDS Musings: AD9850 and AD9851

  1. Hmm interesting problem one thought that crosses my mind is to use one AD9851 to supply the 107.374 182 MHz to a second one, this would give you the step resolution you want, but I guess things like jitter may suffer in the process.

  2. Or have the first DDS drive a PLL that runs at 107.374182 MHz…

  3. I haven’t played with them myself, but I know there are some “big number” libraries around with Arduino support. They basically deal with numbers like strings, so the sky is the limit (which is a few kilobytes on an Arduino of course). Depending on the implementation, they may also avoid some of the base-10 vs base-2 conversion errors you would get with floats, which is important if you want to iteratively add 0.1 and and get to 1.00.

  4. What a nice, juicy problem. Lots of ways to tackle it. Here is Yet Another Alternative Approach – YAAA(tm).

    Suppose you ditch the DDS. If you had a way to generate a signal that ran from 2.399960 MHz to 2.300040 MHz in 1 Hz steps, you could divide that signal by 40 and get your desired sweep (0.025 Hz steps in a 2 Hz range centered on 60 KHz).

    This sounds like a job for a 74HC4046 PLL, running at 2.4 MHz with a divisor that steps in one count increments around a nominal value of 2400000 to get a 1 Hz input to the phase detector. You would need a good 1 Hz reference (GPS, anyone?). The loop time constant would have to be pretty long, of course, at such a low phase comparison rate, so this would not be a good approach for rapid sweeping. But it should work for manual data point measurements.

    There are some clever ways to do division when the input signal is <10MHz using 8-pin PIC processors that execute synchronous code to perform the division. So the chip count would be manageable, even with 22-bit of nominal division. The PIC could handle 13 of those bits as a prescaler.

    Maybe a 6-8 chip solution, all told?

    Oh BTW, there is a typo in the original post. Where it says osc = 0.25 × 2^32, it should read osc = 0.025 × 2^32. And don’t forget the fractional part of the oscillator calculation — the pesky 0.4Hz that makes it hard to find a clean way to synthesize that desired frequency :-(

    1. I like it!

      There’s a column deadline comin’ on strong, with a discussion of DDS divisors & suchlike on the spike, so I’ll explore that path to see where it goes. Figuring prime factors of the oscillators & output frequencies ought to come in there, too; it’s a shame simple integers can’t divide (*) 10 MHz down to 60 kHz!

      (*) Multiplication is so messy!

  5. Documentation scanty? You have to be kidding, right? Hundreds of projects scattered across the Interweb, adequate datasheets and app notes from the chip supplier. What more do you need? OK, the parallel interface has fewer exemplars, but, sheesh! And feel free to whip off the 125MHz clock in favour of something both more appropriate to your needs, and reduce the gutwrenching current drain of that board at the same time.

    1. I always feel a childlike glee when I find a datasheet for the exact hardware in hand, which is certainly unavailable from the usual low-end eBay sellers. Some poking around revealed a bunch of doc for slightly different versions from here-and-there; surely close enough for what I need.

      I wonder where all the Analog Devices DDS chips now selling for essentially zero dollars (if the board price means anything) came from? Perhaps counterfeit DDS chips are a thing, along with FTDI chips and assorted microcontrollers.

  6. You have one typo of AD8951, which you may wish to correct before this gets widely spidered …

  7. … and “or example” where I think you meant “For example.”

Comments are closed.