Remote HF Antenna Tuner

Hello group,
I am new to Arduino, like most I have purchased a couple Arduino's, and some different shields. I have play a little bit with sketches, read lots etc

My project is a remote antenna tuner. If you didn't guess I am a ham. The antenna is a 33' vertical, but in order to make it a multi band HF antenna i need a means to remotely tune the antenna. the RF matching circuit is a going to be a Pi-L network. the components are 1 variable inductor, 1 vacuum variable capacitor, a couple fixed value capacitors, and a couple fixed value inductors.

My plan is to switch in the fixed value components as necessary. And change the value of the variable capacitor and inductor I plan on using a couple bipolar stepper motors. The tuner is attached to the base of the antenna and a control cable is run the house.

So what I need to learn is how to write an arduino sketch that is capable of the following

Control two stepper motors
switch 4 relays
display the value/position of the stepper for for each of the variable componets, the number of each fixed value components switch into the circuit.

ie the LCD display would read something like this

Var L 123 Fix L 1
Var C 123 Fix C 2

this would reflect the position of the variable inductor (L) and tha only 1 fixed inductor was switch in, and the position of the variable capacitor C and the amount if fixed capacitance added in.

One of the LCD shields I have has the 6 buttons the go to the A0 input on the Arduino. if I could make it so two control the Var L and two for the Var C (up and down etc), two to switch in the two fixed inductors and fixed capacitors.

I know that I will have to put limit switchs in both the variable inductor and variable capacitor. to prevent making to many turns.

I was hoping to find out if there was a way for the arduino to recall the steppers last position when powered on and to build into the sketch the max number of steps that the motor could take before reaching the physical limits of the variable components.

the tuner will be manually operated to achieve the best match.

Ok that is a brief over view of my project. I have never written any code or sketches on my own. this is a learning project for me.

Eventually I would like to make this an auto tuner, where it will interface with the radio to get its frequency data, and a VSWR meter to measure the return loss and then building into the sketch the the ability for the tuner to automatically tune it self.

your in put is needed, thank you.

These little stepper motors from ebay are very cheap, and likely have more than enough torque to adjust the tuner elements. They are popular with Arduino fans, so there are plenty of tutorials to get you started.

Servo motors may be easier to use for beginners, depending on your needs (torque...).

I choose the steppers because of the torque. Maybe the servos would be easier?

So here is a thought. to provide a reference for the stepper to prevent from over rotating past the limits of the roller inductor and the vacuum capacitor I could insert on the shaft that couples the stepper to the either of the two components a multi turn pot.

I have a couple high precision 10 turn 100K pots. I could use some 32P gears to couple them to the shaft of the stepper. The Inductor is 26 turns to move the contact from one end to the other of the coil. That equates out to a 2.5:1 ratio. So if I use a 32 tooth and a 80 tooth gear they should give me the correct ratio that when the roller makes 25 turns the pot will have swept 10 turns.

Feed the wiper into one of the analog inputs on the Arduino as a reference.

How would I in the sketch write so that the stepper would not continue to rotate past a certain point once the pot has reached its limit either 0 ohms or 100K ohms?

Again I am addressing what would happen if the power was cycled and the stepper motors turning past the limits of the components.

How would I in the sketch write so that the stepper would not continue to rotate past a certain point once the pot has reached its limit either 0 ohms or 100K ohms?

You probably need to use a stepper motor strong enough to turn the pot, but not strong enough t break the pot hard stops.

Or a pot with no stops.

OK so I though about this some more.
What if I use a pot on to a analog input to move the stepper?

The motors I have are 1.8 degree, so 200 steps/rev and I want to make no more that 25 revolutions so a max of 5000 steps?

Would this work for when the unit is powered on and off? Say it was 1/2 in total travel when I powered the controller off. next time when I powered the unit back of and turned the pot to 75k the motor should advance to 75% travel right?

I think I would want a pot that wasn't continuous turn so I knew when I reached the limit. Also I want to display this value on the LCD.

W7OWC:
OK so I though about this some more.
What if I use a pot on to a analog input to move the stepper?

The motors I have are 1.8 degree, so 200 steps/rev and I want to make no more that 25 revolutions so a max of 5000 steps?

Would this work for when the unit is powered on and off? Say it was 1/2 in total travel when I powered the controller off. next time when I powered the unit back of and turned the pot to 75k the motor should advance to 75% travel right?

I think I would want a pot that wasn't continuous turn so I knew when I reached the limit. Also I want to display this value on the LCD.

I would put limit switches on the rotating elements and do a 'calibration' on power up.

During the powerup, you could record the current position and count off until the stop is reached. Then either return to the current position or a default. With the A/D converter of an Arduino 1024 values are possible, but not probable. So, realistically maybe 512 or less values. How accurate do you want the read back?

I would limit and count steps unless wear on the inductor or capacitor is a consideration.

An optical mask that reports absolute position would produce a more repeatable position. The multiturn pot would need minimal backlash continuous linear values.(^$)

Now as long as the stepper doesn't miss-step the delta count method works. If the motor Stalls you need a hardware limit switch.

If the limit stop is physical you could jam into it for a max count then back off. If you have a logical limit you would have to honor it in software.

Chuck

Limit switch are possible on the inductor. (moving parts to push things) but with te vacuum Cap there is and thing the moves other that the shaft.

Here is a copy of the Sketch so far.

I have put in the LCD display stuff yet. Figured I would tackel one thing at a time. THis is the first one I have ever attempted so please give me some input.

#include <AFMotor.h>

/ HF_Vert_Tuner
//
//
//
//
//
//

// two stepper motors one on each port
AF_Stepper Stepper1(200, 1); // A 200-step-per-revolution motor on channels 1 & 2
AF_Stepper Stepper2(200, 2); // A 200-step-per-revolution motor on channels 3 & 4
int sensorPin1 = A1; // select the input pin for the potentiometer for Stepper 1
int sensorPin2 = A2; // select the input pin for the potentiometer for Stepper 2
}
void setup() {
Serial.begin(9600); //
Stepper1.setSpeed(10); // Stepper1 10 RPM
Stepper2.setSpeed(10); // Stepper2 10 RPM
Stepper1.step(5000); //Reset Position(5000 steps counter-clockwise).
Stepper2.step(5000); //Reset Position(5000 steps counter-clockwise).
}

void loop() {
int val = analogRead(sensorPin1); //get the potentiometer value (range 0-100000 ohms)
val= map(val,0,100000,0,5000); // map pot range in the stepper range.

if(abs(val - pos)> 1){ //if diference is greater than 1 steps.
if((val - pos)> 0){
Stepper1.step(-1); // move one step to the left.
pos++;
}
if((val - pos)< 0){
Stepper1.step(1); // move one step to the right.
pos--;
int val = analogRead(sensorPin2); //get the potentiometer value (range 0-100000)
val= map(val,0,100000,0,5000); // map pot range in the stepper range.

if(abs(val - pos)> 1){ //if diference is greater than 1 steps.
if((val - pos)> 0){
Stepper2.step(-1); // move one step to the left.
pos++;
}
if((val - pos)< 0){
Stepper2.step(1); // move one step to the right.
pos--;
}
}
// Serial.println(pos); //for debuging...
// Serial.println(val);
// delay(100);
}

Hi, please edit that post and put in code tags!

analogRead() does not return a number of ohms. It returns a number in the range 0 to 1023, so you need to adjust your use of map().

Paul

You probably need to determine the mechanical rotation range of the various mechanical parts. Addition of limit switches add another mechanical part that requires setup and calibration.

Here is the sketch, still a work in progress. Ignore the RELAY stuff I am in the process of writing that now..... I am trying to figure out how to use 2 analog inputs as pull ups, one for relay 1 and 2 the other for relay 3 and 4.

I made the change to the analog read to 1023.

In the loop I put the int pos=0 does this mean that when the power is cycled the stepper will reference the current pot position as 0? if the pot is turned 1/2 way and the power is cycled does this mess up the total rotations?

I am really trying to avoid having to put limits switches on the inductor and capacitor. the inducted could be done with some work, the capacitor no so much, no linear movement. Also this network will se 1.5Kw, So I have to be very mindfull of RF

HF_Tuner.ino (2.66 KB)

Hi,

2 analog inputs as pull ups, one for relay 1 and 2 the other for relay 3 and 4.

? ? ? ? ? ?
Can you please post a copy of your circuit, in CAD or a picture of a hand drawn circuit in jpg, png?

Can you please post a copy of your sketch, using code tags?
They are made with the </> icon in the reply Menu.
See section 7 http://forum.arduino.cc/index.php/topic,148850.0.html

Tom..... :slight_smile:

#include <Wire.h>
#include <AFMotor.h>

// HF_Vert_Tuner Pi-L network
//Stepper1=Variable Inductor (10 turns)
//Stepper2= Variable Capacitor(10 turns)
//
//
//
//Fixed value inductors and capacitors via relays digital pins 2,9,10,13
// two stepper motors one on each port
AF_Stepper Stepper1 (200, 1);  // A 200-step-per-revolution motor on channels 1 & 2
AF_Stepper Stepper2 (200, 2);  // A 200-step-per-revolution motor on channels 3 & 4
int sensorPin1 = A1;    // select the input pin for the potentiometer for Stepper 1
int sensorPin2 = A2;    // select the input pin for the potentiometer for Stepper 2
 #define RELAY1 2  // Fixed Inductor1
 #define RELAY2 9  // Fixed Inductor2
 #define RELAY3 10  // Fixed Capacitor1
 #define RELAY4 13  // Fixed Capacitor2

void setup() {
 Serial.begin(9600);         // Begin monitoring 
 Stepper1.setSpeed(10);     // Stepper1 10 RPM
 Stepper2.setSpeed(10);     // Stepper2 10 RPM
 Stepper1.step(5000,MICROSTEP);       //Reset Position(5000 Micorsteps).
 Stepper2.step(5000,MICROSTEP);       //Reset Position(5000 Micorsteps).

;pinMode(RELAY1, OUTPUT)
;pinMode(RELAY2, OUTPUT)
;pinMode(RELAY3, OUTPUT)
;pinMode(RELAY4, OUTPUT);

}
void loop() {
 int val = analogRead(sensorPin1);   //get the potentiometer value
  val= map(val,0,1023,0,5000);    // map pot range in the stepper range.
 int pos= 0
  ;if(abs(val - pos)> 1){         //if diference is greater than 1 steps.
      ;if((val - pos)> 0){
          Stepper1.step(1,BACKWARD,MICROSTEP);      // move one step to the left.
          pos++;
          }
      ;if((val - pos)< 0){
          Stepper1.step(1,FORWARD,MICROSTEP);       // move one step to the right.
          pos--;
      }
 int val = analogRead(sensorPin2);   //get the potentiometer value 
  val= map(val,0,1023,0,5000);    // map pot range in the stepper range.
int pos=0
  ;if(abs(val - pos)> 1){         //if diference is greater than 1 steps.
      ;if((val - pos)> 0){
          Stepper2.step(1,BACKWARD,MICROSTEP);      // move one step to the left.
          pos++;
          }
      ;if((val - pos)< 0){
          Stepper2.step(1,FORWARD,MICROSTEP);       // move one step to the right.
          pos--;
          }
        {  
          ;if ()                  // Analog input
      digitalWrite(RELAY1, HIGH);
    ;else
      digitalWrite(RELAY1, LOW);
      ;if ()                      // Analog input
      digitalWrite(RELAY2, HIGH);
    ;else
      digitalWrite(RELAY2, LOW);
      ;if ()                      // Analog input
      digitalWrite(RELAY3, HIGH);
    ;else
      digitalWrite(RELAY3, LOW);
      ;if ()                      // Analog input
      digitalWrite(RELAY4, HIGH);
    ;else
      digitalWrite(RELAY4, LOW);
  }}}}

That is one of the strangest coding styles I have seen in a while! Why are you putting the semi-colons on the left like that? Not that the compiler cares...

I've tried to tidy it up a bit. At least it compiles now.

#include <Wire.h>
#include <AFMotor.h>

// HF_Vert_Tuner Pi-L network
//Stepper1=Variable Inductor (10 turns)
//Stepper2= Variable Capacitor(10 turns)
//
//
//
//Fixed value inductors and capacitors via relays digital pins 2,9,10,13
// two stepper motors one on each port

AF_Stepper Stepper1 (200, 1);  // A 200-step-per-revolution motor on channels 1 & 2
AF_Stepper Stepper2 (200, 2);  // A 200-step-per-revolution motor on channels 3 & 4
int sensorPin1 = A1;    // select the input pin for the potentiometer for Stepper 1
int sensorPin2 = A2;    // select the input pin for the potentiometer for Stepper 2
int pos1 = 0;
int pos2 = 0;
#define RELAY1 2  // Fixed Inductor1
#define RELAY2 9  // Fixed Inductor2
#define RELAY3 10  // Fixed Capacitor1
#define RELAY4 13  // Fixed Capacitor2

void setup() {
  Serial.begin(9600);         // Begin monitoring
  Stepper1.setSpeed(10);     // Stepper1 10 RPM
  Stepper2.setSpeed(10);     // Stepper2 10 RPM
  Stepper1.step(5000, MICROSTEP);      //Reset Position(5000 Micorsteps).
  Stepper2.step(5000, MICROSTEP);      //Reset Position(5000 Micorsteps).

  pinMode(RELAY1, OUTPUT);
  pinMode(RELAY2, OUTPUT);
  pinMode(RELAY3, OUTPUT);
  pinMode(RELAY4, OUTPUT);

}

void adjustStepper(int sensorPin, AF_Stepper &stepper, int &pos) {
  
  int val = map(analogRead(sensorPin), 0, 1023, 0, 5000);   //get the potentiometer value
  if ((val - pos) > 1) {
    stepper.step(1, BACKWARD, MICROSTEP);    // move one step to the left.
    pos++;
  }
  else if ((val - pos) < -1) {
    stepper.step(1, FORWARD, MICROSTEP);     // move one step to the right.
    pos--;
  }
}


void loop() {

  adjustStepper(sensorPin1, Stepper1, pos1);
  adjustStepper(sensorPin2, Stepper2, pos2);
      
  if (true)                 // Analog input
     digitalWrite(RELAY1, HIGH);
  else
     digitalWrite(RELAY1, LOW);
  if (true)                     // Analog input
     digitalWrite(RELAY2, HIGH);
  else
     digitalWrite(RELAY2, LOW);
  if (true)                     // Analog input
     digitalWrite(RELAY3, HIGH);
  else
     digitalWrite(RELAY3, LOW);
  if (true)                     // Analog input
     digitalWrite(RELAY4, HIGH);
  else
     digitalWrite(RELAY4, LOW);
}

Don't forget, you also need to power the Arduino and all the motors at the base of the antenna.

Paul, KD7HB

paulRB. TNX for cleaning up the sketch. This is the first one I have ever written. Basically I work on a section of the sketch until I think I have it then verify it and make the changes based on what the compiler suggests. I am leaving everything as I go. Please suggest anything that you think will help me out. I will makes those changes in the current sketch. Right now I and hung up on the Serial LCD part. I will post it next time I have it up on the computer.

KD7HB
The only thing that will be at the base of the antenna will be the matching network being driven by the steppers. I may incorporate some geared pots to reference limits if necessary. I plan on running so multi conductor 18 awe cable to run everything. It should only be a couple amps of draw at most. The arduino led and controls will be in the shack. The element will be a 33' vertical. With lots of radials. I am having to get creative with antennas as I live in a HOA. I am able to place the antenna where it will be canon laughed by trees. This is the first time I have evened lived in a HOA so it is a compromise antenna at 5,3.5 and 1.8 MHz. For 7 MHz it will be 1/4 wave the higher frees it will be 1/2,3/8, 5/8 3/4 and full wave depending on loading. That is why the adjustable loading network. I primarily use 7 MHz data 18 MHz voice and 3.5 MHz voice. I have a AIM 41,70 to tune the antenna with to determine phase and impedance and r/l/c. Lots of work going into this. But I didn't want to put up a trap vertical and loses everything in the traps at the lower frees

Tnx guys

Here is the current sketch.

It might help if I list the hardware I am using

Arduino Uno or 2560
1602 LCD with serial
L293D 2 motor shield setup to drive 2 stepper motors
4 channel relay board // used to drive the vacuum relays in the tuner enclosure
2 NEMA 17 Bipolar motors
2 100k 10 turn precision pots
2 on-off-on switch and resistors to switch relays // see pins A2 and A3 in sketch maybe it will mak more sense.

here is the sketch it has not been verified. just made the recommended changes and I have finished the LCD stuff. I need to know how to in the loop write so that the charators after the VarL and VarC are a percentage value of the 2 pots. that way I can recall the position to retune the antenna.

// HF_Vert_Tuner Pi-L network
//Stepper1=Variable Inductor (10 turns)
//Stepper2= Variable Capacitor(10 turns)
//
//
//
//Fixed value inductors and capacitors via relays digital pins 2,9,10,13
// two stepper motors one on each port


#include <LiquidCrystal_I2C.h>
#include <Wire.h>
#include <AFMotor.h>
AF_Stepper Stepper1 (200, 1);  // A 200-step-per-revolution motor on channels 1 & 2
AF_Stepper Stepper2 (200, 2);  // A 200-step-per-revolution motor on channels 3 & 4
int sensorPin1 = A0;    // select the input pin for the potentiometer for Stepper 1
int sensorPin2 = A1;    // select the input pin for the potentiometer for Stepper 2
int pos1 = 0;
int pos2 = 0;
int sensorPin3 = A2;    // Input pin for switching RELAY1 and RELAY2
int sensorPin4 = A3;    // Input Pin for switching RELAY3 and RELAY4
#define RELAY1 2  // Fixed Inductor1
#define RELAY2 9  // Fixed Inductor2
#define RELAY3 10  // Fixed Capacitor1
#define RELAY4 13  // Fixed Capacitor2
// set the LCD address to 0x27 for a 20 chars 4 line display
// Set the pins on the I2C chip used for LCD connections:
//                    addr, en,rw,rs,d4,d5,d6,d7,bl,blpol
LiquidCrystal_I2C lcd (0x27, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE);  // Set the LCD I2C address

void setup() {
adjustStepper(int sensorPin, AF_Stepper &stepper, int &pos) {
  
  int val = map(analogRead(sensorPin), 0, 1023, 0, 5000);   //get the potentiometer value
  if ((val - pos) > 1) {
    stepper.step(1, BACKWARD, MICROSTEP);    // move one step to the left.
    pos++;
  }
  else if ((val - pos) < -1) {
    stepper.step(1, FORWARD, MICROSTEP);     // move one step to the right.
    pos--;
  }
  {
  lcd.begin(16,2);   // initialize the lcd for 16 chars 2 lines, turn on backlight
  for(int i = 0; i< 3; i++)      // ------- Quick 3 blinks of backlight  -------------
  {
    lcd.backlight();
    delay(250);
    lcd.noBacklight();
    delay(250);
  }
  lcd.backlight();       // finish with backlight on  

  lcd.setCursor(0,0); //Start at character 4 on line 0
  lcd.print("VerticalAntenna");
  delay(2000);
  lcd.setCursor(0,1);
  lcd.print("W7OWC Tuner");
  delay(2000);  
                        // Wait and then tell user they can start the Serial Monitor and type in characters to
                        // Display. (Set Serial Monitor option to "No Line Ending")
  lcd.clear();
  lcd.setCursor(0,0);   //Start at character 0 on line 0
  lcd.print("Var L");
  lcd.setCursor(0,1);   //Start at character 0 on line 1
  lcd.print("Var C");
  lcd.setCursor(10,0);   //Start at character 10 on line 0
  lcd.print("Fix L");
  lcd.setCursor(10,1);   //Start at character 10 on line 1
  lcd.print("Fix C");    
}
}
;pinMode(RELAY1, OUTPUT)
;pinMode(RELAY2, OUTPUT)
;pinMode(RELAY3, OUTPUT)
;pinMode(RELAY4, OUTPUT);

}
  lcd.begin(16,2);        // initialize the lcd for 16 chars 2 lines, turn on backlight
  lcd.backlight();       // backlight on  

  lcd.setCursor(0,0); //Start at character 4 on line 0
  lcd.print("VerticalAntenna");
  delay(2000);
  lcd.setCursor(0,1);
  lcd.print("W7OWC Tuner");
  delay(2000);  
                        // Wait and then tell user they can start the Serial Monitor and type in characters to
                        // Display. (Set Serial Monitor option to "No Line Ending")
  lcd.clear();
  lcd.setCursor(0,0);   //Start at character 0 on line 0
  lcd.print("Var L");
  lcd.setCursor(0,1);   //Start at character 0 on line 1
  lcd.print("Var C");
  lcd.setCursor(10,0);   //Start at character 10 on line 0
  lcd.print("Fix L");
  lcd.setCursor(10,1);   //Start at character 10 on line 1
  lcd.print("Fix C");    
}
}
void loop() {
 adjustStepper(sensorPin1, Stepper1, pos1);
  adjustStepper(sensorPin2, Stepper2, pos2);
      
  if (true)                 // Analog input
     digitalWrite(RELAY1, HIGH);
  else
     digitalWrite(RELAY1, LOW);
  if (true)                     // Analog input
     digitalWrite(RELAY2, HIGH);
  else
     digitalWrite(RELAY2, LOW);
  if (true)                     // Analog input
     digitalWrite(RELAY3, HIGH);
  else
     digitalWrite(RELAY3, LOW);
  if (true)                     // Analog input
     digitalWrite(RELAY4, HIGH);
  else
     digitalWrite(RELAY4, LOW);
}

Now its a mess again.

Go back to the version I tidied up for you and add your changes a few lines at a time and check it still compiles after every change. Keep your indentation correct (if in doubt use Autoformat from Tools menu) and quit that wierd habbit of putting semicolons on the left, they are supposed to be statement terminators.

Sorry for moaning. A least you are giving it a go.

OK doing like you said. a few lines at a time. here is the problem I am running into with the LCD. when I verify I get the following error "lcd does not name a type"

  lcd.begin(16,2);   // initialize the lcd for 16 chars 2 lines, turn on backlight
  for(int i = 0; i< 3; i++)      // ------- Quick 3 blinks of backlight  -------------
  {
    lcd.backlight();
    delay(250);
    lcd.noBacklight();
    delay(250);
  }
  lcd.backlight();       // finish with backlight on  

  lcd.setCursor(0,0); //Start at character 4 on line 0
  lcd.print("VerticalAntenna");
  delay(2000);
  lcd.setCursor(0,1);
  lcd.print("Tuner");
  delay(2000);  
                        // Wait and then tell user they can start the Serial Monitor and type in characters to
                        // Display. (Set Serial Monitor option to "No Line Ending")
  lcd.clear();
  lcd.setCursor(0,0);   //Start at character 0 on line 0
  lcd.print("Var L");
  lcd.setCursor(0,1);   //Start at character 0 on line 1
  lcd.print("Var C");
  lcd.setCursor(10,0);   //Start at character 10 on line 0
  lcd.print("Fix L");
  lcd.setCursor(10,1);   //Start at character 10 on line 1
  lcd.print("Fix C");

Post the full code. Don't think the problem is actually in that bit you posted. Its just that the compiler didn't realize there was a problem until it got to that bit.

Could it be that you didn't add these bits:

#include <LiquidCrystal_I2C.h>
...
LiquidCrystal_I2C lcd (0x27, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE);  // Set the LCD I2C address
...
  lcd.begin(16,2);   // initialize the lcd for 16 chars 2 lines, turn on backlight

Also expected to see a "wire.begin();" somewhere...

If so, when I said "a few lines at a time", you have to know which ones belong together and are dependent on each other (I realize that may not be obvious to a beginner).

What I usually to is not only add code in small chunks at a time, but also test each change you make, as far as you can.