0-40Mhz, Sine wave generator $25.

0-40Mhz, Sine wave generator $25.

2013-08-18 12.51.35

Recently some very cheap boards ($4-6) have been coming out of china containing a chip known as the AD9850 which is a Direct Digital Synthesis sine wave generator.

ad9850-dds

With only 4 control wires we can control the board via the arduino. This gives us a variable sine wave generator that we can control to give us a very nice sine wave from 0 Megahertz up to around 40 Megahertz at almost a full volt peak to peak.

I decided to use an LCD keypad to give some on screen visual indication of the frequency plus a means of controlling the frequency quickly and easily.

2013-08-12 17.28.16

The code to upload to the Arduino, can be relatively straight forward.

I have been using libraries to simplify the toggling of the control pins to set the frequency on the sub board. Also cause i’m not that smart yet!  The dds.h library is from Anthony Good – K3NG

So simple to use, the command to set the frequency is simply;

ddschip.setfrequency(Frequency);

Could it be any easier?

To get the board up and running, find Anthony’s library here.

Place the DDS directory in your arduino sketches/library folder with all the other libraries. That way when you compile/upload the IDE will find the file automatically.

The board has a clock pin, a load pin, a data pin and a reset pin. The other 4 pins of use are the sin wave ououtput and a square wave output.

2013-08-12 17.27.27

 

2013-08-12 17.27.13

In the setup code you will just need to define what pins you have used for what job between the DDS board and the Arduino.

#define data_pin 12
#define load_pin A5
#define clock_pin A4
#define clock_hz 120000000LL

dds ddschip(DDS9850, data_pin, load_pin, clock_pin, clock_hz);

2013-08-12 17.36.53

This sets my dds up with its 120mhz onboard crystal. I am substituting the pin numbers with words to make it easier to understand. For example the word data_pin would be replaced everywhere it is found at compile time with the number 12. this is what the #define command does

Now the chip pins have been defined, we can just use the ddschip.setfrequency(Frequency); command to set the frequency to any frequency we desire, within the capabilities of the device.  The AD9850 boards i have used are pretty good for about 0-40mhz, beyond that they are a little sketchy.

2013-08-12 17.29.36

2013-08-18 12.52.22

I figured that i would use the up and down buttons to raise or lower the frequency.

I decide to use the left and right buttons to cycle the amount the frequency would increment on raising or lowering. I chose, 1Hz, 10Hz, 100Hz, 1KHz, 10KHz, 100KHz and 1MHz.

I cobbled together some code, some of which i hacked out of a previous LCD keypad project (Morse coder). I have kept the interface reasonably simple, after all we only have 16 characters on two lines.

2013-08-12 17.39.58

2013-08-12 17.40.17

After I had it built up on the bench and had tested it extensively I decide to put it all in a box.  Initially i wanted to put a battery pack inside the box as well, but decided to leave access to the power jack so i could just plug in a battery pack externally if i wanted to.  The result are the photos you see here. The LCD keypad shield is designed to be used in the open and not really designed to go in a case, but i shoehorned it in with lots of cutting. I used a terminal block on the side for the sine wave output and I also decided to break out the square wave output and its associated adjustment pot, the LCD contrast adjustment pot and the DDS board power light.

Here is the code I came up with;

/* T Robb 22.7.13

the way it works , is we read the buttons for up and down, we use that to increment or decrement a number which we later
use to set an increment or decrement amount, ie 10hz, 1khz, 1mhz etc
then if the left or right buttons are pushed we go up or down in frequency byt the incrment amount

*/

 

#include <stdio.h>
#include <dds.h>
#include <LiquidCrystal.h>

#define RESET 13
#define data_pin 12
#define load_pin A5
#define clock_pin A4
#define clock_hz 120000000LL
#define calibrationValue -0.0400000 // this is a value we change to calibrate our particular chip more accurately
#define buttonPin A0

// chip, data_pin, load_pin, clock_pin, clock_hz
dds ddschip(DDS9850, data_pin, load_pin, clock_pin, clock_hz); // set my dds up with 120mhz onboard crystal
LiquidCrystal lcd(8, 9, 4, 5, 6, 7);

// some variables to use in our program
long toFrequency = 14070000;
long currentFrequency;
long maxFrequency = 40000000;
long minFrequency = 0;
int incrementNumber = 6;
int maxprogramnumber = 6; // dont forget to increase the menu numbers here!!
int programnumber = 1;

void setup()

{
Serial.begin(9600);
Serial.println(“Beginning Setup”);
// set up the LCD’s number of columns and rows:
lcd.begin(16, 2);
lcd.clear();
lcd.setCursor(0, 0);
lcd.print(“T.Robb V0.1b “); //Print a little message
lcd.setCursor(0, 1);
lcd.print(” DDS Sine wave “);
delay(2000);
// setup pins
pinMode(RESET, OUTPUT);
pinMode(data_pin, OUTPUT);
pinMode(load_pin, OUTPUT);
pinMode(clock_pin, OUTPUT);
pinMode(buttonPin, INPUT);
digitalWrite(buttonPin, HIGH);

ddschip.calibrate(calibrationValue); // this is a value we change to calibrate our particular chip more accurately
ddschip.setfrequency(toFrequency);
lcd.clear();

}

void loop()
{
if(toFrequency >= maxFrequency){(toFrequency = maxFrequency);}
if(toFrequency <= minFrequency){(toFrequency = minFrequency);}
ddschip.setfrequency(toFrequency);
currentFrequency = toFrequency;

switch(incrementNumber){

case 0:
Serial.println(“increment amount is 1hz”);
lcd.setCursor(0, 0);
lcd.print(“Change By 1hz”);
break;

case 1:
Serial.println(“increment amount is 10hz”);
lcd.setCursor(0, 0);
lcd.print(“Change By 10hz “);
break;

case 2:
Serial.println(“increment amount is 100hz”);
lcd.setCursor(0, 0);
lcd.print(“Change By 100hz “);
break;

case 3:
Serial.println(“increment amount is 1 000hz”);
lcd.setCursor(0, 0);
lcd.print(“Change By 1khz”);
break;

case 4:
Serial.println(“increment amount is 10 000hz”);
lcd.setCursor(0, 0);
lcd.print(“Change By 10khz”);
break;

case 5:
Serial.println(“increment amount is 100 000hz”);
lcd.setCursor(0, 0);
lcd.print(“Change By 100khz”);
break;

case 6:
Serial.println(“increment amount is 1 000 000hz”);
lcd.setCursor(0, 0);
lcd.print(“Change By 1Mhz”);
break;

default:
Serial.println(“increment amount is 100hz”);
lcd.setCursor(0, 0);
lcd.print(“Change By 100hz “);
break;
}

lcd.setCursor(0, 1);
lcd.print(“Freq is “); //Print to lcd
lcd.setCursor(8, 1);
lcd.print(currentFrequency);

Serial.println(incrementNumber); // temporary for debuggin delete me

Serial.print(“Current Frequency is set to :”);
Serial.println(currentFrequency);

while((analogRead(buttonPin))>=1000){} // do nothing while no buttons pressed to chill out
delay(5);
if(analogRead(buttonPin)>=100 && analogRead(buttonPin)<=200){ // we have pushed up
upFrequency();
delay(300);
}

if(analogRead(buttonPin)>=200 && analogRead(buttonPin)<=400){ // we have pushed down
downFrequency();
delay(300);
}

if((analogRead(buttonPin))<=50){ // we have pushed right
incrementNumber++;
delay(300);
}

if(analogRead(buttonPin)>=400 && analogRead(buttonPin)<=600){ // we have pushed left
incrementNumber–;
delay(300);
}

if(incrementNumber > 6){incrementNumber = 0;} // this is where the menu goes around and around
if(incrementNumber < 0){incrementNumber = 6;}

delay(100);
lcd.clear();

}
void upFrequency()
{
Serial.println(“Going UP Frequency”);
switch(incrementNumber){

case 0:
toFrequency = (toFrequency + 1);
break;

case 1:
toFrequency = (toFrequency + 10);
break;

case 2:
toFrequency = (toFrequency + 100);
break;

case 3:
toFrequency = (toFrequency + 1000);
break;

case 4:
toFrequency = (toFrequency + 10000);
break;

case 5:
toFrequency = (toFrequency + 100000);
break;
case 6:
toFrequency = (toFrequency + 1000000);
break;

default:
toFrequency = (toFrequency + 10);
break;
}

}
void downFrequency()
{

Serial.println(“Going DOWN Frequency”);
switch(incrementNumber){

case 0:
toFrequency = (toFrequency – 1);
break;

case 1:
toFrequency = (toFrequency – 10);
break;

case 2:
toFrequency = (toFrequency – 100);
break;

case 3:
toFrequency = (toFrequency – 1000);
break;

case 4:
toFrequency = (toFrequency – 10000);
break;

case 5:
toFrequency = (toFrequency – 100000);
break;

case 6:
toFrequency = (toFrequency – 1000000);
break;

default:
toFrequency = (toFrequency – 10);
break;
}
}

 

 

No Comments Yet.

Leave a comment