_____ _____ _____ _____ | __ \| __ \ / ____| / ____| | | | | | | | (___ | (_____ _____ ___ _ __ ___ _ __ | | | | | | |\___ \ \___ \ \ /\ / / _ \/ _ \ '_ \ / _ \ '__| | |__| | |__| |____) | ____) \ V V / __/ __/ |_) | __/ | |_____/|_____/|_____/ |_____/ \_/\_/ \___|\___| .__/ \___|_| | | |_| /***************************************************************************\ * Name : DDS_Sweeper.BAS * * Author : Beric Dunn (K6BEZ) * * Notice : Copyright (c) 2013 CC-BY-SA * * : Creative Commons Attribution-ShareAlike 3.0 Unported License * * Date : 9/26/2013 * * Version : 1.0 * * Notes : Written using For the Arduino Micro * * * * : A0 - Reverse Detector Analog in * * : A1 - Forward Detector Analog in * * * * LCD : Mark Phillips, NI2O 20141202 * \***************************************************************************/ //#include #include #include #include // Define Pins used To control AD9850 DDS #define FQ_UD 10 #define SDAT 11 #define SCLK 9 #define Reset 12 #define pulseHigh(pin) {digitalWrite(pin, High); digitalWrite(pin, LOW); } // Define pins used For the Input control const int buttonEsc = A2; const int buttonUp = A3; const int buttonDown = A4; const int buttonEnter = A5; int lastButtonPushed = 0; int lastButtonEnterState = Low; // the previous reading from the Enter input pin int lastButtonEscState = Low; // the previous reading from the Esc input pin int lastButtonLeftState = Low; // the previous reading from the Left input pin int lastButtonRightState = Low; // the previous reading from the Right input pin long lastEnterDebounceTime = 0; // the last time the output pin was toggled long lastEscDebounceTime = 0; // the last time the output pin was toggled long lastLeftDebounceTime = 0; // the last time the output pin was toggled long lastRightDebounceTime = 0; // the last time the output pin was toggled long debounceDelay = 500; // the debounce time /* //Menu variables MenuBackend menu = MenuBackend(menuUsed,menuChanged); //initialize menuitems MenuItem menu1Item1 = MenuItem("Item1"); MenuItem menuItem1SubItem1 = MenuItem("Item1SubItem1"); MenuItem menuItem1SubItem2 = MenuItem("Item1SubItem2"); MenuItem menu1Item2 = MenuItem("Item2"); MenuItem menuItem2SubItem1 = MenuItem("Item2SubItem1"); MenuItem menuItem2SubItem2 = MenuItem("Item2SubItem2"); MenuItem menuItem3SubItem3 = MenuItem("Item2SubItem3"); MenuItem menu1Item3 = MenuItem("Item3"); */ Double Fstart_MHz = 1; // Start Frequency for sweep Double Fstop_MHz = 10; // Stop Frequency for sweep Double current_freq_MHz; // Temp variable used during sweep long serial_input_number; // Used to build number from serial stream int num_steps = 100; // Number of steps to use in the sweep Char incoming_char; // Character read from serial stream // Define LCD pins LiquidCrystal lcd(7,6,5,4,3,2); // LCD keypad shield from ebay // the setup routine runs once when you press Reset: void setup() { // Configiure DDS control pins For digital Output pinMode(FQ_UD,Output); pinMode(SCLK,Output); pinMode(SDAT,Output); pinMode(Reset,Output); pulseHigh(Reset); pulseHigh(SCLK); pulseHigh(FQ_UD); // this pulse enables serial mode - Datasheet page 12 figure 10 // Configure A2-A4 As digital inputs For use with the buttons pinMode(A2,INPUT_PULLUP); pinMode(A3,INPUT_PULLUP); pinMode(A4,INPUT_PULLUP); pinMode(A5,INPUT_PULLUP); // Configure LED pin For digital Output pinMode(13,Output); // Set up analog inputs On A0 And A1, internal reference voltage, To sense the SWR etc pinMode(A0,Input); pinMode(A1,Input); analogReference(INTERNAL); // initialize serial communication At 57600 baud Serial.begin(57600); // Send some brag stuff To the console Serial.println("K6BEZ Arduino Antenna Analyser"); Serial.println(); // Start the LCD lcd.begin(16,2); lcd.Clear(); lcd.setCursor(0,0); lcd.Print("Testing ..."); // generate 3 frequencies delayed by 1 second each - proves the generator works. Serial.println ("Testing 2.5MHz ..."); SetDDSFreq(2500000); // 2.5MHz delay(1000); Serial.println ("Testing 5MHz ..."); SetDDSFreq(5000000); // 5MHz delay(1000); Serial.println ("Testing 10MHz ..."); SetDDSFreq(10000000);// 10MHz delay(1000); Serial.println ("Reseting the DDS generator ..."); pulseHigh(Reset); // turn the generator off // write some brag stuff To the LCD lcd.Clear(); lcd.setCursor(0,0); lcd.Print(" K6BEZ Antenna"); lcd.setCursor(0,1); lcd.Print(" Analyser V1.1"); delay(3000); Serial.println ("Lets Go!!"); /* //configure menu menu.getRoot().Add(menu1Item1); menu1Item1.addRight(menu1Item2).addRight(menu1Item3); menu1Item1.Add(menuItem1SubItem1).addRight(menuItem1SubItem2); menu1Item2.Add(menuItem2SubItem1).addRight(menuItem2SubItem2).addRight(menuItem3SubItem3); menu.toRoot(); lcd.setCursor(0,0); lcd.Print("www.coagula.org"); */ //} //Initialise the incoming serial number To zero serial_input_number=0; } // the loop routine runs over And over again forever: void loop() { //Check For character If(Serial.available()>0){ incoming_char = Serial.read(); switch(incoming_char){ Case '0': Case '1': Case '2': Case '3': Case '4': Case '5': Case '6': Case '7': Case '8': Case '9': serial_input_number=serial_input_number*10+(incoming_char-'0'); Break; Case 'A': //Turn frequency into FStart Fstart_MHz = ((Double)serial_input_number)/1000000; serial_input_number=0; Break; Case 'B': //Turn frequency into FStart Fstop_MHz = ((Double)serial_input_number)/1000000; serial_input_number=0; Break; Case 'C': //Turn frequency into FStart And Set DDS Output To single frequency Fstart_MHz = ((Double)serial_input_number)/1000000; SetDDSFreq(Fstart_MHz); serial_input_number=0; Break; Case 'N': // Set number of steps in the sweep num_steps = serial_input_number; serial_input_number=0; Break; Case 'R': Asm volatile (" jmp 0"); Break; Case 'S': Case 's': Perform_sweep(); Break; Case '?': // Report current configuration To PC lcd.Clear(); lcd.setCursor(0,0); Serial.Print("Start Freq:"); lcd.Print("Start Freq: "); Serial.println(Fstart_MHz*1000000); lcd.Print(Fstart_MHz); lcd.setCursor(0,1); Serial.Print("Stop Freq:"); lcd.Print("Stop Freq : "); Serial.println(Fstop_MHz*1000000); lcd.Print(Fstop_MHz); Serial.Print("Num Steps:"); Serial.println(num_steps); Break; } Serial.flush(); } } void Perform_sweep(){ lcd.Clear(); lcd.setCursor(4,0); lcd.Print("Sweeping"); Double FWD=0; Double REV=0; Double VSWR; Double Fstep_MHz = (Fstop_MHz-Fstart_MHz)/num_steps; // Start loop For(int i=0;i<=num_steps;i++){ // Calculate current frequency current_freq_MHz = Fstart_MHz + i*Fstep_MHz; // Set DDS To current frequency SetDDSFreq(current_freq_MHz*1000000); // Wait a little For settling delay(10); // Read the forawrd And reverse voltages REV = analogRead(A0); FWD = analogRead(A1); If(REV>=FWD){ // To avoid a divide by zero Or negative VSWR Then Set To max 999 VSWR = 999; }Else{ // Calculate VSWR VSWR = (FWD+REV)/(FWD-REV); } // Send current Line back To PC over serial bus Serial.Print(current_freq_MHz*1000000); Serial.Print(",0,"); Serial.Print(int(VSWR*1000)); Serial.Print(","); Serial.Print(FWD); Serial.Print(","); Serial.println(REV); } // Send "End" To PC To indicate End of sweep And turn off the generator Serial.println("End"); lcd.Clear(); lcd.setCursor(4,0); lcd.Print("Finished"); Serial.flush(); pulseHigh(Reset); } void SetDDSFreq(Double Freq_Hz){ // Calculate the DDS Word - from AD9850 Datasheet int32_t f = Freq_Hz * 4294967295/125000000; // Send one Byte At a time For (int b=0;b<4;b++,f>>=8){ send_byte(f & 0xFF); } // 5th Byte needs To be zeros send_byte(0); // Strobe the Update pin To tell DDS To use values pulseHigh(FQ_UD); } void send_byte(Byte data_to_send){ // Bit bang the Byte over the SPI bus For (int i=0; i<8; i++,data_to_send>>=1){ // Set Data Bit On Output pin digitalWrite(SDAT,data_to_send & 0x01); // Strobe the clock pin pulseHigh(SCLK); } }