AD9851 DDS Frequency
Unit
with Arduino
d. bodnar revised 04-16-2015
| The goal of this project is to make a front
end for the AD9850 or AD9851 DDC frequency generator. A rotary encoder is used to change frequency and a 2 line LCD displays the current setting. If the button on the encoder is briefly pressed the digit that the encoder changes is moved to the left (increased x10). If the button is pressed for 200 ms or more the digit is moved to the right (decreased x10)
|
| This image shows the DDS unit set to 5 MHz -
the 100000 shows that turning the rotary encoder will change the
100,000's place up or down. The scope is attached to the small
piece of coax at the bottom.
This view shows the Arduino (rear) and the DDS board (foreground)
The scope shows a bit over 5 MHz.
|
![]() |
Rotary_Encoder_v2_4_button_LCD-Combined-w-DDS-8951-w-reverse-BO ////WORKING = 4-11-2015 -
// revisited 5-15-2015
////HOLD BUTTON ON POWER UP TO Change from 9851 to 9850 & visa versa!
// Need to add "hold button to go back in decimal place"
// from http://www.multiwingspan.co.uk/arduino.php?page=rotary2
#include <Wire.h>
#include <LCD.h>
#include <LiquidCrystal_I2C.h>
#include <EEPROM.h>
#define I2C_ADDR 0x27 // <<----- Add your address here. Find it from I2C Scanner
#define BACKLIGHT_PIN 3
#define En_pin 2
#define Rw_pin 1
#define Rs_pin 0
#define D4_pin 4
#define D5_pin 5
#define D6_pin 6
#define D7_pin 7
int n = 1;
int valLen = 0;
LiquidCrystal_I2C lcd(I2C_ADDR, En_pin, Rw_pin, Rs_pin, D4_pin, D5_pin, D6_pin, D7_pin);
// Setting up the counter
long reading = 5000000;
int lowest = 0;
long highest = 99999999;
long changeamnt = 1;
// Timing for polling the encoder
unsigned long currentTime;
unsigned long lastTime;
unsigned long bpTime; // button press time for single press or hold
int AD9851 = 0; // default is 9850 when = 0, it is AD9851 when = 1
// Pin definitions
const int pinA = 10; //
const int pinB = 11; //
const int buttonPin = 5; // the number of the pushbutton pin
const int ledPin = 13; // the number of the LED pin
// Storing the readings
boolean encA;
boolean encB;
boolean lastA = false;
int buttonState = 0; // variable for reading the pushbutton status
#define W_CLK 6 // Pin 8 - connect to AD9850 module word load clock pin (CLK)
#define FQ_UD 7 // Pin 9 - connect to freq update pin (FQ)
#define DATA 8 // CHANGED Pin 10 - connect to serial data load pin (DATA)
#define RESET 9 // CHANGED 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) {
//Serial.println("at sendFreq");
//fudge to get freq to = input freq
if (AD9851 == 0) { // using AD9850 chip if = 0
// Serial.println("at 9850!!!!");
int32_t freq = frequency * 4294967295 / 125000000 * 1000000 / 1000005; /////25 / 105 * 100 *1004 / 1001*1000000/1000845;
for (int b = 0; b < 4; b++, freq >>= 8) {
tfr_byte(freq & 0xFF);
}
tfr_byte(0x000); // Final control byte, all 0 for 9850 chip
}
else {
int32_t freq = frequency * 25 / 105 * 100 * 1004 / 1001 * 1000000 / 1000845;
for (int b = 0; b < 4; b++, freq >>= 8) {
tfr_byte(freq & 0xFF);
}
tfr_byte(0x001); // Final control byte, all 0 for 9850 chip
}
pulseHigh(FQ_UD); // Done! Should see output
}
void setup() {
Serial.begin(9600);
// 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
AD9851 = EEPROM.read(0);
if (digitalRead(buttonPin) == LOW) { // button pressed
Serial.print(" AD9851=");
Serial.println(AD9851);
if (AD9851 == 0) {
AD9851 = 1;
Serial.println("==1");
EEPROM.write(0, AD9851);
}
else {
AD9851 = 0;
Serial.println("==0");
EEPROM.write(0, AD9851);
}
}
lcd.begin (16, 2); // <<----- My LCD was 16x2
// Switch on the backlight
lcd.setBacklightPin(BACKLIGHT_PIN, POSITIVE);
lcd.setBacklight(HIGH);
lcd.home (); // go home
lcd.print("Ver 2.3- 895");
if (AD9851 == 1) {
lcd.print("1");
}
else {
lcd.print("0");
}
// initialize the LED pin as an output:
pinMode(ledPin, OUTPUT);
// initialize the pushbutton pin as an input:
pinMode(buttonPin, INPUT);
// set the two pins as inputs with internal pullups
pinMode(pinA, INPUT_PULLUP);
pinMode(pinB, INPUT_PULLUP);
// Set up the timing of the polling
currentTime = millis();
lastTime = currentTime;
// Start the serial monitor for debugging
}
int changeamnt10 = 0;
void loop()
{
sendFrequency(reading);
//lcd.blink();
buttonState = digitalRead(buttonPin);
if (buttonState == LOW) { //LOW indicates that the button has been pressed
// turn LED on:
bpTime = millis(); // save time
while (digitalRead(buttonPin) == LOW) { // stay here till button released
}
if (millis() - bpTime <= 200 ) {
Serial.print("Millis<500 = ");
Serial.println(millis() - bpTime );
digitalWrite(ledPin, HIGH);
changeamnt = changeamnt * 10;
changeamnt10 = changeamnt10 + 1;
if (changeamnt == 10000000) {
changeamnt10 = 0;
changeamnt = 1;
}
}
else {
Serial.print("Millis>500 = ");
Serial.println(millis() - bpTime );
digitalWrite(ledPin, HIGH);
changeamnt = changeamnt / 10;
changeamnt10 = changeamnt10 - 1;
if (changeamnt <= 0) {
changeamnt10 = 10000000;
changeamnt = 1;
}
}
Serial.print("change = ");
Serial.println(changeamnt);
lcd.noBlink();
lcd.setCursor(0, 1); // 2nd line
lcd.print(changeamnt, DEC);
lcd.print(" ");
delay(200);
int zz = (changeamnt10);
Serial.print("zz = "); Serial.println(zz);
lcd.setCursor(4 - (zz + 3) + 5 + 8, 0);
lcd.blink();
}
else {
// turn LED off:
digitalWrite(ledPin, LOW);
}
// Read elapsed time
currentTime = millis();
// Check if it's time to read
if (currentTime >= (lastTime + 2)) // was 5
{
// read the two pins
encA = digitalRead(pinA);
encB = digitalRead(pinB);
// check if A has gone from high to low
if ((!encA) && (lastA))
{
// check if B is high
if (encB)
{
// clockwise
if (reading + changeamnt <= highest)
{
reading = reading + changeamnt;
Serial.println("fwd");
}
}
else
{
// anti-clockwise
if (reading - changeamnt >= 0)
{
reading = reading - changeamnt;
Serial.println("bkw");
}
}
// Output reading for debugging
Serial.println(reading);
lcd.setCursor (0, 0); // go to start of 1st line
lcd.print("Freq= ");
decLength();
valLen = 15 - valLen;
lcd.setCursor(valLen, 0);
lcd.print(reading, DEC);
// lcd.print(" ");
int zz = (changeamnt10);
Serial.print("zz = "); Serial.println(zz);
lcd.setCursor(4 - (zz + 3) + 5 + 8, 0);
lcd.blink();
decLength();
// lcd.setCursor(9,1);
// lcd.print(valLen);
}
// store reading of A and millis for next loop
lastA = encA;
lastTime = currentTime;
}
}
void decLength() {
if (reading > 9999999)
valLen = 8;
else if (reading > 999999)
valLen = 7;
else if (reading > 99999)
valLen = 6;
else if (reading > 9999)
valLen = 5;
else if (reading > 999)
valLen = 4;
else if (reading > 99)
valLen = 3;
else if (reading > 9)
valLen = 2;
else
valLen = 1;
}
|