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; } |