/* N6QW / KK6FUT Super Simple DDS This is a super simple DDS sketch to run a single band AD9850-based DDS. Kept super-super simple to make it easy for the non-software folks. Inputs: Rotary encoder Outputs: LCD display, DDS frequency Uses a a (16*2) LCD Display on the I2C Interface for TwRobot. Note: this is "quick and dirty" code to get you up and running, and is not optimized in the slightest, nor has it been extensively debugged. It's here to get you started on writing your own code for this project, and is undoubtedly buggy. Feel free to fix/update/improve and make your version available to the public. 2015 Mar 18 - Incorporated radix bug fixes and display changes from VE2YTQ */ #include #include #include //twrobot const double bandStart = 7000000; // start of 40m const double bandEnd = 7300000; // end of 40m const double bandInit = 7150000; // where to initially set the frequency double freq = bandInit ; // this is a variable (changes) - set it to the beginning of the band double freqDelta = 10000; // how much to change the frequency by, clicking the rotary encoder will change this. // Set pin numbers for ADS9850 const int W_CLK = 2; const int FQ_UD = 3; const int DATAPIN = 4; const int RESET = 5; // Set pins for ROTARY ENCODER - we are NOT using rotary encoder switch, so omit for clarity const int RotEncAPin = 12; const int RotEncBPin = 11; const int RotEncSwPin = A3; // Display library assumes use of A4 for clock, A5 for data. No code needed. // Variables for Rotary Encoder handling boolean OldRotEncA = true; boolean RotEncA = true; boolean RotEncB = true; boolean RotEncSw = true; boolean LastEncSw = HIGH; // Instantiate the LCD display... LiquidCrystal_I2C lcd(0x027, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE); // Set the LCD I2C address TwRobot //LiquidCrystal_I2C lcd(0x27,16,2); // set the LCD address to 0x20 for a 16 chars and 2 line display Use this in case the other doesn't work // the above line void setup() { // Set up LCD lcd.begin(16,2); // initialize the lcd for 16 chars 2 lines, turn on backlight TwRobot //lcd.init(); // Print a message to the LCD. lcd.backlight(); lcd.setCursor(0, 1); lcd.print(" N6QW & KK6FUT"); // Set up ROTARY ENCODER pinMode(RotEncAPin, INPUT); pinMode(RotEncBPin, INPUT); pinMode(RotEncSwPin, INPUT); // set up pull-up resistors on inputs... digitalWrite(RotEncAPin,HIGH); digitalWrite(RotEncBPin,HIGH); digitalWrite(RotEncSwPin,HIGH); // Set up DDS pinMode(FQ_UD, OUTPUT); pinMode(W_CLK, OUTPUT); pinMode(DATAPIN, OUTPUT); pinMode(RESET, OUTPUT); // start up the DDS... pulseHigh(RESET); pulseHigh(W_CLK); pulseHigh(FQ_UD); // start the oscillator... send_frequency(freq); display_frequency(freq); } void loop() { // Read the inputs... RotEncA = digitalRead(RotEncAPin); RotEncB = digitalRead(RotEncBPin); RotEncSw = digitalRead(RotEncSwPin); // check the rotary encoder values if ((RotEncA == HIGH)&&(OldRotEncA == LOW)){ // adjust frequency if (RotEncB == LOW) { freq=constrain(freq+freqDelta,bandStart,bandEnd); } else { freq=constrain(freq-freqDelta,bandStart,bandEnd); } OldRotEncA=RotEncA; // store rotary encoder position for next go around // Now, update the LCD with frequency display_frequency(freq); // push the frequency to LCD display send_frequency(freq); // set the DDS to the new frequency // delay(400); // let the frequency/voltages settle out after changing the frequency } if (RotEncSw==LOW && LastEncSw == HIGH){ LastEncSw = LOW; delay(200); // debounce } else if (LastEncSw == LOW) { LastEncSw = HIGH; delay(200); // debounce // if user clicks rotary encoder, change the size of the increment // use an if then loop, but this could be more elegantly done with some shifting math if (freqDelta == 10000) { freqDelta = 1000; } else if (freqDelta == 1000) { freqDelta = 100; } else if (freqDelta == 100) { freqDelta = 10000; } else { // this is either 100 or we goofed somewhere else, so set it back to the big change freqDelta = 1000; } display_frequency(freq); } OldRotEncA=RotEncA; // End of loop() } // subroutine to display the frequency... void display_frequency(double frequency) { lcd.setCursor(0, 0); //was 17 if (frequency<10000000){ lcd.print(" "); } lcd.print(frequency/1e6,4); lcd.print(" MHz"); if (freqDelta == 10000) { lcd.setCursor(4, 0); } else if (freqDelta == 1000) { lcd.setCursor(5, 0); } else if (freqDelta == 100) { lcd.setCursor(6, 0); } } // Subroutine to generate a positive pulse on 'pin'... void pulseHigh(int pin) { digitalWrite(pin, HIGH); digitalWrite(pin, LOW); } // calculate and send frequency code to DDS Module... void send_frequency(double frequency) { int32_t freq = (frequency) * 4294967295/125000000; for (int b=0; b<4; b++, freq>>=8) { shiftOut(DATAPIN, W_CLK, LSBFIRST, freq & 0xFF); } shiftOut(DATAPIN, W_CLK, LSBFIRST, 0x00); pulseHigh(FQ_UD); }