Arduino Nano HF Antenna Sweeper

by rjkorn in Circuits > Arduino

1736 Views, 6 Favorites, 0 Comments

Arduino Nano HF Antenna Sweeper

IMG_4195.jpg
loop.jpg

I saw this in many forms around the internet and decided to build one myself. I bought a mini vna but it seems so fragile I hate to take it outside.....

I have a large collection of antennas gathered over the years by my father and myself. I figured it was time to trim down the stockpile and see just what I had.

First Prototype

IMG_4189.jpg
IMG_4192.jpg

My first prototype was a single sided PCB made in a laser cutter by painting the board with a $0.99 spray can of flat black paint they lasering off the paint to form the resist pattern. I etched the board in the usual way.

I had seen many people add a buffer amp to their DDS projects and I had already made some little pcb's for these so I decided to incorporate this into the design.

I use PCB Express for these boards but recently tried JLPCB and was pleased with the results

Boards Arrived

IMG_4190.jpg
IMG_4193.jpg
IMG_4194.jpg

The boards arrived and I decided to build one without the DDS amp and one with so I could compare results. To eliminate the amp required two wire jumpers on the board. You do need the amp. Without it you get unpredictable results on antennas with a gamma match or a loading coil that provides 0 ohms dc resistance.

Software

images.png
<p>/***************************************************************************\<br>*  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                            *
*          :   Pins:                                                        *
*          :    A0 - Reverse Detector Analog in                             *
*          :    A1 - Forward Detector Analog in                             *
\***************************************************************************</p><p>/ Define Pins used to control AD9850 DDS
const int FQ_UD=10;
const int SDAT=11;
const int SCLK=9;
const int RESET=12;</p><p>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</p><p>void setup() {
  // Configiure DDS control pins for digital output
  pinMode(FQ_UD,OUTPUT);
  pinMode(SCLK,OUTPUT);
  pinMode(SDAT,OUTPUT);
  pinMode(RESET,OUTPUT);</p><p>  // Configure LED pin for digital output
  pinMode(13,OUTPUT);</p><p>  // Set up analog inputs on A0 and A1, internal reference voltage
  pinMode(A0,INPUT);
  pinMode(A1,INPUT);
  analogReference(INTERNAL);</p><p>  // initialize serial communication at 57600 baud
  Serial.begin(57600);</p><p>  // Reset the DDS
  digitalWrite(RESET,HIGH);
  digitalWrite(RESET,LOW);</p><p>  //Initialise the incoming serial number to zero
  serial_input_number=0;</p><p>}</p><p>// 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 FStop
      Fstop_MHz = ((double)serial_input_number)/1000000;
      serial_input_number=0;
      break;
    case 'C':
      //Turn frequency to 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 'S':
    case 's':
      Perform_sweep();
      break;
    case '?':
      // Report current configuration to PC
      Serial.print("Start Freq:");
      Serial.println(Fstart_MHz*1000000);
      Serial.print("Stop Freq:");
      Serial.println(Fstop_MHz*1000000);
      Serial.print("Num Steps:");
      Serial.println(num_steps);
      break;
    }
    Serial.flush();
  }
}</p><p>void Perform_sweep(){
  double FWD=0;
  double REV=0;
  double VSWR;
  double Fstep_MHz = (Fstop_MHz-Fstart_MHz)/num_steps;</p><p>  // 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);
    }</p><p>    // 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
  Serial.println("End");
  Serial.flush();
}</p><p>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
  digitalWrite(FQ_UD,HIGH);
  digitalWrite(FQ_UD,LOW);
}</p><p>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
    digitalWrite(SCLK,HIGH);
    digitalWrite(SCLK,LOW);
  }
}</p>
<br>

Time to Test Some Antennas...

IMG_4191.jpg
IMG_4187.jpg
IMG_4196.jpg
loop.jpg
mini center load magmount with spring.png
CB Whip.jpg
7.png

The software was written in VB and included the source so I added simple screen shot button. Made it easier to save the plots....

A lot of 10M, 11M and 6M antennas in the pile...

there was a 10M loop but its cap must have dried out as it was up around 30mhz....

Without the amplifier on board that antenna would plot anything.