Testing an eBay AD9850 DDS module with Arduino Uno

Like a lot of Hams, while browsing for electronics on eBay I came across some of these super inexpensive DDS modules being sold and shipped from China (less than $6 as of August 2012).  That’s cheaper than you can buy the 9850 chip by itself here in the States!  Without any research whatsoever I went ahead and added 2 to a recent order of some other components I needed.

About 2 weeks later my package arrived and here’s the board I ended up with.Anyway, I had visions of dragging out the breadboard, hooking up some jumpers, maybe throwing a couple of capacitors in there…   As anyone can tell you that’s bought one of these on impulse – it’s a little more complicated than that.  There is actually some math involved, bits, bytes, hexadecimal, longwords even.  Stuff I hadn’t seen since college (what I remember of college anyway).  So, I finally sat down the other day and dug in to what it would take to get this thing going.

Long story short, to get any output from one of these you need to send 40 bits of data to the chip, either via it’s serial or parallel interface.  It’s all explained in the official Analog Device datasheet here – http://www.analog.com/static/imported-files/data_sheets/AD9850.pdf

I read it the other night to help me fall asleep.

Ahh, just kidding.  It’s actually pretty cool stuff.  You can interface to the board via your computers serial or parallel port, but as a recent Arduino convert, I decided to go that route.  I ended up modifying slightly an Arduino sketch that was written for the 9851, putting the AD9850 on a UNO prototype shield, and testing it in single frequency mode.  I can envision using these as a crystal eliminator for some older tube type transmitting gear I have here, maybe controlled with an Atmel 90S2313 or PIC.  It’s about comparable in cost to buying an actual crystal for the older gear, and you’re not stuck to one frequency.

Ok, so here are the two board versions, with pinouts labeled that I’ve seen on eBay.

I used a prototype shield with breadboard, although it’s not necessary.  You could just jumper to the main Arduino board.

Using digital pins 8 through 11, proto shield installed on the UNO.  Pin 8 to CLK, 9 to FQ, 10 to DATA, and 11 to RST.

Here is the modified sketch for the 9850.  Just cut and paste, and upload to your Arduino board.  At the very end of the program you can choose which frequency you would like.

/*
 * A simple single freq AD9850 Arduino test script
 * Original AD9851 DDS sketch by Andrew Smallbone at www.rocketnumbernine.com
 * Modified for testing the inexpensive AD9850 ebay DDS modules
 * Pictures and pinouts at nr8o.dhlpilotcentral.com
 * 9850 datasheet at http://www.analog.com/static/imported-files/data_sheets/AD9850.pdf
 * Use freely
 */

 #define W_CLK 8       // Pin 8 - connect to AD9850 module word load clock pin (CLK)
 #define FQ_UD 9       // Pin 9 - connect to freq update pin (FQ)
 #define DATA 10       // Pin 10 - connect to serial data load pin (DATA)
 #define RESET 11      // Pin 11 - connect to reset pin (RST).

 #define pulseHigh(pin) {digitalWrite(pin, HIGH); digitalWrite(pin, LOW); }

 // transfers a byte, a bit at a time, LSB first to the 9850 via serial DATA line
void tfr_byte(byte data)
{
  for (int i=0; i<8; i++, data>>=1) {
    digitalWrite(DATA, data & 0x01);
    pulseHigh(W_CLK);   //after each bit sent, CLK is pulsed high
  }
}

 // frequency calc from datasheet page 8 = <sys clock> * <frequency tuning word>/2^32
void sendFrequency(double frequency) {
  int32_t freq = frequency * 4294967295/125000000;  // note 125 MHz clock on 9850
  for (int b=0; b<4; b++, freq>>=8) {
    tfr_byte(freq & 0xFF);
  }
  tfr_byte(0x000);   // Final control byte, all 0 for 9850 chip
  pulseHigh(FQ_UD);  // Done!  Should see output
}

void setup() {
 // configure arduino data pins for output
  pinMode(FQ_UD, OUTPUT);
  pinMode(W_CLK, OUTPUT);
  pinMode(DATA, OUTPUT);
  pinMode(RESET, OUTPUT);

  pulseHigh(RESET);
  pulseHigh(W_CLK);
  pulseHigh(FQ_UD);  // this pulse enables serial mode - Datasheet page 12 figure 10
}

void loop() {
  sendFrequency(10.e6);  // freq
  while(1);
}

Right click this Download Link and choose “save as” to download.

And here’s the result.

This is a look at a 10 MHz sinewave from pin 10 on my board.  The HP 5334A frequency counter uses a GPS phase corrected ovenized crystal oscillator as it’s reference source, so it’s extremely accurate.  A little tweeking of the <sys clock> variable in the Arduino sketch and this thing would be balls on, or close to it.

Pretty impressive little board.

35 thoughts on “Testing an eBay AD9850 DDS module with Arduino Uno

  1. Hi, nice work.
    but the code can’t be verified by arduino 1.0.1
    Error-messages:
    sketch_sep08a:20: error: stray ‘\’ in program
    sketch_sep08a:31: error: stray ‘\’ in program
    sketch_sep08a.cpp: In function ‘void tfr_byte(byte)’:
    sketch_sep08a:20: error: expected `)’ before ‘u00d701′
    sketch_sep08a.cpp: In function ‘void sendFrequency(double)’:
    sketch_sep08a:31: error: expected `)’ before ‘u00d7000′

    would be great, if you fix that
    or do I have to use a different Arduino-Shell ?
    Greatings from Germany
    Kurti

  2. Kurti, thanks for the heads up! I didn’t realize WordPress changed the formatting of the code. I had to install a plug-in so it would display correctly. You should now be able to copy and past the code and it will compile correctly. Let me know how it works out.

  3. Hi,
    afer deleteing the ”
    I got the following message:
    sketch_sep10a.cpp: In function ‘void tfr_byte(byte)’:
    sketch_sep10a:19: error: expected `;’ before ‘)’ token
    sketch_sep10a.cpp: In function ‘void sendFrequency(double)’:
    sketch_sep10a:28: error: expected `;’ before ‘)’ token

    I think a download of the sketch would solve the problem.
    Thanks again for your work
    an Greatings from Germany
    Kurti

  4. Ok, that’s strange, I was getting the same errors you are. I just re-posted the code and I can cut and paste, and it compiles fine in the IDE. I am going to add a link for direct download of the sketch.

  5. I’m K4WDE, though very inactive. I’ve been searching for a sketch to test the DDS module I purchased. Looks like yours will be the simplest. Thanks a ton for taking the time.

    Walt

    • Hey Walt, thanks for commenting. Good luck with the DDS module. I think I’m going to be using mine with a buffer amp as a crystal replacement for an old 2&6 meter tube rig I’m restoring (Ameco TX62). I think it would be neat to use the 9850 with a LCD keypad shield and be able to just cursor over to the digit you want to change, hit up or down, and then select. Should be easy to do, and who knows it’s probably already been done, just need to find it.
      73, Ron

  6. Hi Walt,
    thanks for your listing to test an AD9850 you buying via eBay.
    I have exact the same one here.
    Your code is compiling and working great.
    I have only one problem. The smallest step-rate I can use is 1 Hz.
    Following the datasheet and other publications it must-be possible to use smaller step-rates. What I need it a steprate from abt. 1.46 Hz.
    I hope you can help me with this.

    Regards and vy73 de Erwin DU1MGA (W3WAZ)

  7. Thanks for posting your frequency programming sketch. I am still waiting for my boards from Hong Kong (they must really be on the “slow boat”).

    Do you know what function R13, the little trimpot, performs?

    73

  8. Pingback: Procrastination Paid Off | Used Radio Mall

  9. Pingback: DDS Update | Used Radio Mall

  10. Thanks for the video explanation. I wouldn’t have guessed that it was a square wave duty cycle adjust.

    Since my last comment, I have received my AD9850 boards and had it running on the bench in about 5 minutes!

    Thanks for posting your experience and your code.

  11. Question about AD9850_nr80.ino source
    Thanks for the code! Now a question: Your line:
    int32_t freq = frequency * 4294967295/125000000;
    Obviously 4294967295 = 2^32 and 125000000 = RefClk
    But it does not jive with the datasheet page 8 that says:
    Fout = (delta Phase x CLKIN) / 2^32
    Your multiplication then division are not the same as the datasheet formula.
    What am I not understanding?
    Also:
    When I use the Interactive Design Tool at Analog.com
    http://designtools.analog.com/dt/dds/ad9850.html
    It does not give the same results as your formula.
    It must be something obvious, but what?
    73, Doug WD0UG

    • Hi Doug,

      Perhaps you’ve been misled by the variable name ‘freq’ and you think this is the same as ‘Fout’ in the datasheet. What the program is calculating (and calls ‘freq’) is actually the frequency tuning word or the the thing called ‘delta Phase’ in the datasheet. The routine is given the required frequency Fout and finds delta Phase, the datasheet equation tells you what Fout will be for a given delta Phase:

      Fout = (delta Phase * Refclk) / 2^32

      so the program computes:

      delta Phase = Fout * 2^32 / Refclk

      There may be a small difference between the tuning word calculated by this program and the tool you mentioned, but it will only be in the least significant bits and is simply due to differences in the way rounding to the nearest integer is done.

      Hope that helps,

      David

  12. Hi Ron,
    Thanks for the sketch, I have had my arduino ages, but lack the gumption to get stuck in to it. I bought one of these dds boards for £3.70 delivered from Hong Kong after hearing about it in Radcom. I had it wired and running within a matter of minutes. The big rig had it within about 10hz, that’s pretty amazing in my book.
    Thanks for putting this on your blog. I’d like to take it further, maybe add an encoder and have it as a dds vfo for some future qrp rig, maybe for the new 60 metre segments we have here now.

    73,
    Ian MM0GYX

  13. Thanks, I was able to have your sketch up and running with Energia on a Stellaris Launchpad within seconds. The module gets its power from the Launchpad as well.

  14. How tight is the output sine at low (e.g. audio) freq’s?
    At the moment, I’m using a PIC12F1822 and it’s 5 bit DAC. Ugly at best, even after a decent filter…

  15. Thank you very much, I also managed to have the DDS up and running in 5 minutes, an essential starting point. Great work!
    Marco

  16. Thanks for posting this guide; it really helps speed up the learning curve (reducing it to almost zero). I was able to get my AD9850 board working in only about 30 minutes (taking my time) using this info.

    PS:
    2^32 is 4294967296, but your code shows … 295 (=2^32 – 1).
    Arduino main loop doesn’t require the while(1) statement.

  17. Hallo, Bill
    Thanks for info for “while(1)”. I
    I copied code from the two oringins and adapted. You can see following links in the code comments area. This is my first Arduino ide code (excepting pin 13 led blinking). I used my limited Turbo C knowledge (last time I used was 20 years ago) to make it work.
    If you put …296, arduino ide can´t compile:
    “error: integer constant is too large for ‘long’ type”

    Best 73 from Niceto

    • “…296 can’t compile…”

      Of course! Good one.

      My next iteration will move the constant calculation outside the main loop. No need to repeatedly recalculate it, but I’ll need to think carefully about where the truncation of significant digits or bits occurs. We don’t want to lose resolution of frequency steps.

      Thank you.

  18. Thanks for the info. I ordered 4 of them – probably won’t get them until after Dayton. Presently using a PICAXE to control an AD9851, but the freq>word conversion is considerably more difficult with a PICAXE.

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>