Reviewing and improving the semi-automatic antenna tuner

Foreword

When I built the semi automatic tuner two years ago I did not take into account some possible shortcomings the device could suffer from. The first of these I noticed when I exceeded power levels of about more or less than 50 watts. In some cases there was rf incoupling leading the microcontroller to fail so that the relay setting was invalid for the given combination of frequency and antenna. The next point was that the algorithm to set the capacitor was far from being optimized. And, as I found out, the maximum inductance I had inlcuded was far too high. On the other hand the lowest indcutance was to big to ensure very fine tuning. So this was revised, too by stepping the inductors more carefully.

The consequence then was a complete reconstruction of the tuner trying to avoid the problems from rf stray energy being coupled into the microcontroller and improving the software and hardware.

Abstract

Thsi article describes a microcontroller driven semi-automatic antenna tuner capable of handling power levels up to 150 watts. The device is a low pass filter tuner manually tuned by setting the optimized L/C combination by hand and then storing the values into the EEPROM of the mictrocontroller to recall them later (seperately for each band from 80 to 10 meters including WARC bands). The tuner ist designed to couple long wire antennas (i. e. longer than half a wavelength) in the frequency range from about 3 MHz to 30 MHz. The antennas can be balanced or non-balanced.

The device uses 7 coils wound on iron powder toroids and a variable capacitor controlled by a motor with a reduction drive and a a device that detects the current turning angle of the rotator.

Also integrated you will find a measurement section to give the current standing wave ratio and put out this on the display.

General layout

The tuner consists of two main parts:

  • The microcontroller unit
  • The RF unit containing the tuning coils and the variable capacitor.

Let’s see the schematic first:

DK7IH semi automatic antenna tuner V2 (schematic)
DK7IH semi automatic antenna tuner V2 (Schematic FULL SIZE)

Circuit description

Starting on the left side, you see the microcontroller unit equipped with an 8-bit AVR microcontroller (ATMega16 or similar). The user interface is very simple and made of 6 push buttons. These are connected to GND via switchable individual resistors leading to the ADC3 input of the cntroller. The pull up resistor for ADC3 is activated thus forming a voltage divider and thus an individual ADC value for each push button to be recognized by the software. This is done because it saves control lines and controller ports to a wide extent.

The LCD is a two line 16 characters LCD.

Output ports are connected to ULN2003 driver ICs. These ICs contain a driver capable to handle up to 30V DC including a clamp diode so this IC can drive mtors and relays directly. There are capacitors of 0.1uF connected to the port lines to minimize rf coupling effects.

The RF board is made of 7 coils wound on T68-2 toroids with the inductances given in the schematic:

  • L1: 0.1uH: 4 turns,
  • L2: 0.25uH: 7 turns,
  • L3: 0.5uH: 9 turns,
  • L4: 1uH: 13 turns,
  • L5: 2uH: 19 turns,
  • L6: 4uH: 26 turns,
  • L7: 8uH: 37 turns.

Wire gauge is 0.4mm. The inductors are shortened by a 12V relay each if neccessary. So you can (by binary calculation) set any value from 0.1 uH to close to 16uH.

An output transformer is used to give a balanced out for e. g. doublet antenns. It is 10 turns bifilar on a 2.5 cm toroid ferrite core of No. 43 material. If you use a non-balanced antenna you can leave out this transformer.

The capacitor in my construction is a 200pF max. butterfly capacitor with air as dielectric.  The advantage of a butterfly type is that it needs only 90° angle to turn it from minimum to maximum capacity. The motor (a 5V dc version) is connected via a 240:1 gear drive by TAMIYA. The motor is pulse driven so it can be directly connected to 12 Volts with running danger to damage it.

The drive has two outlets providing one axle at each side of the drive. To one of the axles I connected the capacitor, the other one connects to a potentiometer to report the current swing angle to the microcontroller. This allows precise feedback of the capacitor’s current position which is essential for setting it to the desired value. The value of this variable resistor does not really matter since it is only a simple voltage divider. Anything between 1k and 10k should fit. Make sure that you use a piece that is easy to turn to minimize friction. To connect the axles I used PVC tubing with an inside diameter of 3 mm.

Also included is a measurement section to give the user a current reading of VSWR. The coupler can be anything you should regard as proper. I used a strip power coupler from an old CB radio. But other systems should also work.

To compensate losses when tuning low frequencies I added a DC amplifier based on an operational dual system amplifier (LM358). There is no means to reduce sensitivity. This is done by regulating the input power of the driving transmitter. The software will give you a readout for FWD and REF power in the range from 0 to 999. Tune to maxmimun FWD and minimum REF energy and everything will be alright! 😉

Practical aspects

To minimize RF couping into the microcontroller I seperated the control board from the RF board by putting it on a seperate veroboard with an aluminium shielding underneath:

DK7IH semi automatic antenna tuner V2 (inside view)
DK7IH semi automatic antenna tuner V2 (inside view)

The RF board is mounted to the bottom of the case, here with dismantled controller board. The controller board is sited on top of the package.

DK7IH semi automatic antenna tuner V2 (inside view)
DK7IH semi automatic antenna tuner V2 (inside view)

On the right side there is the variable butterfly capacitor, on the board, centered you can see the motor plus the reduction drive. On the left side of this there is a small potentiometer that forms the turning angele detector. To connect this to the ADC of the controller it is highly recommended to use shielded cable!

To come to an end, here is the deveice positioned under the roof window of my shack directly connected to the ladder line:

DK7IH semi automatic antenna tuner V
DK7IH semi automatic antenna tuner V”

Thanks for reading and enjoy your radio! 73 de Peter (DK7IH)

The software

(Apology for having some comments in German. I have been using this code for centuries! 😉

/*****************************************************************/
/*              Antennatuner with ATMega 16 V2                   */
/*  ************************************************************ */
/*  Microcontroller:  ATMEL AVR ATmega16, 8 MHz                  */
/*                                                               */
/*  Compiler:         GCC (GNU AVR C-Compiler)                   */
/*  Author:           Peter Rachow DK7IH                         */
/*  Last cahnge:      2018-07-27                                 */
/*****************************************************************/

/*    PORTS */
// O U T P U T 
// LCD 
// RS      = PD2
// E       = PD3
// D4...D7 = PD4..PD7

//Coil relays: PC0...PC6
//Motor drive on/off: PD1
//Motor direction relay: PD0
//Extra capacitor 200pF: PC7 (not yet!)

//I N P U T
//ADC0: SWR-Meter 0
//ADC1: SWR-Meter 1
//ADC2:
//ADC3: Keys
//ADC4: Potentiometer for Capacitor position

#include <inttypes.h>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>

#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/sleep.h>
#include <avr/eeprom.h>
#include <util/delay.h>

int main(void);

#define LCD_INST 0x00
#define LCD_DATA 0x01

#define MAXCAP 220
#define CAPDELAY 10
#define MAXBANDS 7

void lcd_write(char, unsigned char);
void set_rs(char);
void set_e(char);
void lcd_init(void);
void lcd_cls(void);
void lcd_line_cls(int);
void lcd_putchar(int, int, unsigned char);
void lcd_putstring(int, int, char*);
int lcd_putnumber(int, int, long, int);
void lcd_display_test(void);

//BAND DISPLAY & MISC
void show_band(int);
void show_meter(int, int, int);
void define_chars(void);

//Coils & Cpas
void set_coils(int);
void set_cap(int);
void rotate_cap(int);
int get_cap(void);

//ADC
int get_adc(int);
int get_keys(void);

//Delay
void wait_ms(int);

//String
int int2str(long, int, char *, int);
int stringlen(char *);


long runsecs = 0;

/**************************************/
/* Funktionen und Prozeduren fuer LCD */
/**************************************/
// LCD 
// RS      = PD2
// E       = PD3
// D4...D7 = PD4..PD7

/* Ein Byte (Befehl bzw. Zeichen) zum Display senden */
void lcd_write(char lcdmode, unsigned char value)
{
    int x = 16, t1;
	
    set_e(0); 

    if(!lcdmode)
	{
        set_rs(0);    //RS=0 => INST
	}	
    else
	{
        set_rs(1);    // RS=1 => DATA
	}	

    wait_ms(4);
	
    //Hi nibble
    set_e(1);
	for(t1 = 0; t1 < 4; t1++)
	{
	    if(value & x)
	    {
	       PORTD |= x;
	    }
        else	
	    {
           PORTD &= ~(x);
	    }  
		
		x <<= 1;
	}	
	set_e(0);
	
	x = 16;

	// Lo nibble
	set_e(1);
	for(t1 = 0; t1 < 4; t1++)
	{
	    if((value & 0x0F) * 16 & x)
	    {
	       PORTD |= x;
	    }
        else	
	    {
           PORTD &= ~(x);
	    }  
		
		x <<= 1;
	}
    set_e(0);

}

//RS
void set_rs(char status) //PD2  
{
    if(status)
	{
        PORTD |= 4;
	}	
    else
	{
	    PORTD &= ~(4);
	}	
}

//E
void set_e(char status)  //PD3
{
    if(status)
	{
        PORTD |= 8;
	}	
    else
	{
	    PORTD &= ~(8);
	}	
}

/* Ein Zeichen (Char) zum Display senden, dieses in */
/* Zeile row und Spalte col positionieren           */
void lcd_putchar(int row, int col, unsigned char ch)
{
    lcd_write(LCD_INST, col + 128 + row * 0x40);
    lcd_write(LCD_DATA, ch);
}


/* Eine Zeichenkette direkt in das LCD schreiben */
/* Parameter: Startposition, Zeile und Pointer   */
void lcd_putstring(int row, int col, char *s)
{
    unsigned char t1;

    for(t1 = col; *(s); t1++)
	{
        lcd_putchar(row, t1, *(s++));
	}	
}


/* Display loeschen */
void lcd_cls(void)
{
    lcd_write(LCD_INST, 1);
}


/* LCD-Display initialisieren */
void lcd_init(void)
{
    /* Grundeinstellungen: 2 Zeilen, 5x7 Matrix, 4 Bit */
    lcd_write(LCD_INST, 40);
    lcd_write(LCD_INST, 40);
    lcd_write(LCD_INST, 40);

    //MAtrix 5*7
    lcd_write(LCD_INST, 8);

    /* Display on, Cursor off, Blink off */
    lcd_write(LCD_INST, 12);

    /* Entrymode !cursoincrease + !displayshifted */
    lcd_write(LCD_INST, 4);
	
	//4-Bit-Mode
    lcd_write(LCD_INST, 2);	
	
	lcd_cls();
}


//Write number with given amount on digits to LCD
int lcd_putnumber(int col, int row, long num, int dec)
{
    char *numstr = malloc(32);
    int l = 0;
    if(numstr != NULL)
    {
        int2str(num, dec, numstr, 16);
        lcd_putstring(col, row, numstr);
        l = stringlen(numstr);
        free(numstr);
        return l;
      
    } 
    return 0;
}


void lcd_line_cls(int ln)
{
    int t1;
	
	for(t1 = 0; t1 < 15; t1++)
	{
	    lcd_putchar(ln, t1, 32);
	}
}	
/*****************************************/
//           STRING FUNCTIONS
/*****************************************/
//INT 2 ASC
int int2str(long num, int dec, char *buf, int buflen)
{
    int i, c, xp = 0, neg = 0;
    long n, dd = 1E09;

    if(!num)
	{
	    *buf++ = '0';
		*buf = 0;
		return 1;
	}	
		
    if(num < 0)
    {
     	neg = 1;
	    n = num * -1;
    }
    else
    {
	    n = num;
    }

    //Fill buffer with \0
    for(i = 0; i < 12; i++)
    {
	    *(buf + i) = 0;
    }

    c = 9; //Max. number of displayable digits
    while(dd)
    {
	    i = n / dd;
	    n = n - i * dd;
	
	    *(buf + 9 - c + xp) = i + 48;
	    dd /= 10;
	    if(c == dec && dec)
	    {
	        *(buf + 9 - c + ++xp) = '.';
	    }
	    c--;
    }

    //Search for 1st char different from '0'
    i = 0;
    while(*(buf + i) == 48)
    {
	    *(buf + i++) = 32;
    }

    //Add minus-sign if neccessary
    if(neg)
    {
	    *(buf + --i) = '-';
    }

    //Eleminate leading spaces
    c = 0;
    while(*(buf + i))
    {
	    *(buf + c++) = *(buf + i++);
    }
    *(buf + c) = 0;
	
	return c;
}

//STRLEN
int stringlen(char *s)
{
   int t1 = 0;

   while(*(s + t1++));

   return (t1 - 1);
}


//BAND DISPLAY
void show_band(int b)
{

    char *band_str[] = {"80m", "40m", "30m", "20m", "17m", "15m", "12m", "10m"};
    lcd_putstring(0, 13, band_str[b]);
}

//Meter (max. value = 25)
void show_meter(int value, int value_old, int pos)
{
	#define MAXBLOCKS 4
    int v1, v2, v3, i1;
	
    //Clear meter (5 chars) if new value > old value
    if(value < value_old)
    {
        for(i1 = 0; i1 < MAXBLOCKS; i1++)
        {
	        lcd_putchar(1, i1 + pos * 6, 32);
        }
	}
			
	v1 = (int) value / MAXBLOCKS; //Full blocks, 5 cols each
    v2 = value - v1 * MAXBLOCKS;  //Rest
	if(v1 > MAXBLOCKS)
	{
		v1 = MAXBLOCKS;
	}
	
	if(value >= value_old)
	{
	    v3 = (int) value_old / MAXBLOCKS; //Full blocks, 5 cols each, already drawn
	}
	else
	{  
		v3 = 0;
	}	    
	
	//Full blocks	
	for(i1 = v3; i1 < v1; i1++)
	{
	    lcd_putchar(1, i1 + pos * 6, 4); 
	}
	
	//Rest
	if(i1 < MAXBLOCKS)
	{
		if(v2)
	    {
	        lcd_putchar(1, i1 + pos * 6, v2 - 1);
	    }
        else
        {
            lcd_putchar(1, i1 + pos * 6, ' ');
        }
	}
}

//PROGRAM CUNSTOM CHARS FOR S-SMETER
void define_chars(void)
{
    int i1;
	unsigned char adr = 64;
						  
	unsigned char b1[] = {0x00, 0x00, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00, //S-Meter blocks 
	                      0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00,
						  0x00, 0x00, 0x1C, 0x1C, 0x1C, 0x1C, 0x00, 0x00,
						  0x00, 0x00, 0x1E, 0x1E, 0x1E, 0x1E, 0x00, 0x00,
						  0x00, 0x00, 0x1F, 0x1F, 0x1F, 0x1F, 0x00, 0x00,
						  	0x0,0x0,0x4,0xe,0x4,0x0,0x0, 0, //+
						  	0x4,0xe,0x4,0x0,0x4,0xe,0x4,0, //++
						  0x00, 0x01, 0x02, 0x12, 0x0A, 0x04, 0x00, 0x00  //Tick
						  
						  };					  
	//Dummy operation!
	lcd_write(LCD_INST, 0);
	lcd_write(LCD_DATA, 0);

    //Load data into CGRAM
	for(i1 = 0; i1 < 64; i1++)  
	{
	    lcd_write(LCD_INST, adr++);
		lcd_write(LCD_DATA, b1[i1]);
	}
}		


/////////////////////////////////////
//
// C O I L S & C A P S
//
/////////////////////////////////////
void set_coils(int pattern)
{
    int unsigned t1, x = 1, p = pattern;
    
    //Inductance in uH  * 100
    int i0[] = {10, 25, 50, 100, 200, 400, 800}, i1 = 0;
    
    //lcd_putstring(0, 10, "    ");
    //lcd_putnumber(0, 10, p, -1, -1, 'l', 0);
    
    for(t1 = 0; t1 < 7; t1++)
    {
		if(p & x)
        {
            PORTC &= ~(x);      
            i1 += i0[t1];
        }
        else
        {    
            PORTC |= x;
        }
        x <<= 1;
     }       
     lcd_putstring(0, 0, "       ");
     lcd_putstring(0, lcd_putnumber(0, 0, i1, 2), "uH");
}

void set_cap(int cap)
{
               
    if(cap < 0 ||cap > MAXCAP)
    {
		return;
	}
	
	lcd_putstring(0, lcd_putnumber(0, 7, cap, -1) + 7, "pF");
	wait_ms(500);
	/*	
    lcd_putnumber(0, 0, get_adc(4), -1, -1, 'l', 0);
    lcd_putnumber(0, 8, cap, -1, -1, 'l', 0);
    lcd_putnumber(1, 0, (int) adc0, -1, -1, 'l', 0);	
    */       
    
    while(get_cap() > cap)
    {
		rotate_cap(0);
		lcd_putstring(0, 7, "      ");
        lcd_putstring(0, lcd_putnumber(0, 7, get_cap(), -1) + 7, "pF");
        if(get_keys() == 5 || get_keys() == 6) //Quit if band QSY key is pressed
        {
			return;
		}	
    }
    
    while(get_cap() < cap)
    {
		rotate_cap(1);
		lcd_putstring(0, 7, "      ");
        lcd_putstring(0, lcd_putnumber(0, 7, get_cap(), -1) + 7, "pF");
        if(get_keys() == 5 || get_keys() == 6) //Quit if band QSY key is pressed
        {
			return;
		}	
    }
        
    

}

//Measure real cap val from sensor
int get_cap(void)
{
	double val = (double) (get_adc(4) - 384) * MAXCAP / 256;
	
	return (int) val;
}
	
void rotate_cap(int direction)
{
	if(direction)
	{
		PORTD &= ~(1); //RelayOFF      
	}
	else
	{
	    PORTD |= 1;   //Relay ON	
	}	
	
	PORTD |= 2;   //Motor ON
	wait_ms(CAPDELAY);
	PORTD &= ~(2);  //Motor OFF      
	wait_ms(CAPDELAY);
}	


ISR(TIMER1_OVF_vect)   	   // Timer1 Überlauf
{ 
    runsecs++;
    TCNT1 = 57724;	  
} 

//***************************************************
//                      ADC
//***************************************************

int get_adc(int adcmode)
{
    int adc_val = 0;
	
	
	ADMUX = (ADMUX &~(0x1F)) | (adcmode & 0x1F);     // Kanal adcmode aktivieren PA0=TUNE
    wait_ms(3);
	
    ADCSRA |= (1<<ADSC);
	wait_ms(3);
	
	adc_val = ADCL;
    adc_val += ADCH * 256;   
	
	while(ADCSRA & (1<<ADSC));
	
	return adc_val;
}	

//Read keys via ADC0
int get_keys(void)
{

    int key_value[] = {18, 22, 29, 43, 74, 132};  
       	
    int t1;
    int adcval = get_adc(3);
        
    //TEST display of ADC value 
    /*
    lcd_cls();
    lcd_putnumber(0, 0, get_adc(3), -1, -1, 'l', 0);
    return 0;    	
    */
    
    for(t1 = 0; t1 < 6; t1++)
    {
        if(adcval > key_value[t1] - 2 && adcval < key_value[t1] + 2)
        {
			 return t1 + 1;     
        }
    }
    
    return 0;
}

/***************************************************/
/* Wartezeit in Millisekunden bei fck = 8.000 MHz  */
/***************************************************/
void wait_ms(int ms)
{
  int t1, t2;

  for(t1 = 0; t1 < ms; t1++)
    for(t2 = 0; t2 < 137 * 8; t2++)
      asm volatile ("nop" ::);
}

int main()
{
	int t1;
	int key;     //Keystroke
	int adc_val; //Value of ADC
    int i = 65;  //L
    int band = 0;
    int l1 = 0, c1 = 0;
    
    //Standard values for DK7IH antenna
    //L=      - (128), 8uH(64), 4uH(32), 2uH(16), 1uH(8), 0.5uH(4), 0.25uH(2), 0.125uH(1)
    int std_l [] = {65, 33, 12, 8, 6, 4, 3, 2, 1};
    int std_c [] = {172, 41, 75, 110, 88, 55, 33, 17};
    
    //Meter data
    int s0, s1;
    int s0_old = -1, s1_old = -1;
    int s0off, s1off;
    int loopcnt0 = 0;;
        
    int ok = 0;
    long runsecs2 = 0;
	
	/* Set ports */
    /* OUTPUT */
    DDRB = 0x1F; //Relays 1.55 of cap switching
    DDRC = 0x7F; //Relays for coils             
    DDRD = 0xFF; //LCD data on PD4...PD7
                 //LCD RS:PD2, E:PD3
                 //PD0, PD1: Relay 6 and 7 of cap switches
    
    PORTA = 0x08; //Pullup resistor for keys' input   
    
    //Display
    lcd_init();
	wait_ms(500);
	lcd_cls();
	lcd_putstring(0, 0, " DK7IH Antenna");				
	lcd_putstring(1, 0, " Tuner Ver. 2.0");				
	wait_ms(500);
	lcd_cls();
			
	//Watchdog abschalten
	WDTCR = 0;
	WDTCR = 0;
    	
	//ADC initialisieren
    ADMUX = (1<<REFS0);     // Referenz = AVCC
    ADCSRA = (1<<ADPS2) | (1<<ADPS1) | (1<<ADEN); //Frequenzvorteiler 64 u. //ADC einschalten
	ADCSRA |= (1<<ADSC); //Eine Wandlung vornehmen
	while (ADCSRA & (1<<ADSC)); //Eine Wandlung abwarten
    adc_val = ADCL;
    adc_val += ADCH * 256;   //Wert auslesen
	adc_val = 0;
	
	//Timer 1
	TCCR1A = 0;                      // normal mode, keine PWM Ausgänge
    TCCR1B = (1<<CS12) + (1<<CS10) ;   // start Timer mit Systemtakt, Prescaler = /1024
	                                    //Auslösung des Overflow alle Sekunde sec.
    TIMSK = (1<<TOIE1);   // overflow aktivieren.
	TCNT1 = 57724;        //Startwert für Sekundentakt

    //Define custom chars for meter
    //define_chars();

    //Load standard data if eeprom cell empty
    for(t1 = 0; t1 < 8; t1++)
    {
		if(eeprom_read_byte((uint8_t*)(t1 * 2)) == 255)
		{ 
			eeprom_write_byte((uint8_t*)(t1 * 2), std_l[t1]);
			eeprom_write_byte((uint8_t*)(t1 * 2 + 1), std_c[t1]);
		}
	}		
				
		
    //Get recent data           		
   	band = eeprom_read_byte((uint8_t*)32);
   	if(band < 0 || band > MAXBANDS)
	{
	    band = 3;
	}
	show_band(band);
	
	l1 = eeprom_read_byte((uint8_t*)(band * 2));
	if(l1 >= 0 && l1 < 128)
	{
		set_coils(l1);
	}
	else
	{
		set_coils(65);
		lcd_line_cls(1);
		lcd_putstring(0, 0, " -x-uH");
		wait_ms(1000);
	}
	c1 = eeprom_read_byte((uint8_t*)(band * 2) + 1);	
	if(c1 >= 0 && c1 < MAXCAP)
	{
		set_cap(c1);
	}
	else
	{
		set_cap(110);
		lcd_line_cls(1);
		lcd_putstring(0, 0, " -x-pF");
		wait_ms(1000);
	}	
    sei();

    show_band(band);
    
    //Calculate 0-offset of swr meter
    s0off = get_adc(0);
    s1off = get_adc(1);
    
    for(;;) 
	{
		key = get_keys();
		if(i > 0 && key == 2)
		{
			i--;
		    set_coils(i);
		    wait_ms(50);
		}    
		
		if(i < 127 && key == 1)
		{
			i++;
		    set_coils(i);
		    wait_ms(50);
		}    
				
		while(get_cap() > 0 && key == 4) //C(-)
		{
			rotate_cap(0);
		    lcd_putstring(0, 7, "      ");
            lcd_putstring(0, lcd_putnumber(0, 7, get_cap(), -1) + 7, "pF");     
            wait_ms(100);
            key = get_keys();
		}    
		
		while(get_cap() < MAXCAP && key == 3) //C(+)
		{
			rotate_cap(1);
		    lcd_putstring(0, 7, "      ");
            lcd_putstring(0, lcd_putnumber(0, 7, get_cap(), -1) + 7, "pF");     
            wait_ms(100);
            key = get_keys();
		}    

        if(band > 0 && key == 6)         //Band (-)
        {
			band--;
		
			while(!eeprom_is_ready());
		    eeprom_write_byte((uint8_t*)32, band);
										
			lcd_putstring(1, 0, "Recalling.");
				
			l1 = eeprom_read_byte((uint8_t*)(band * 2));
			c1 = eeprom_read_byte((uint8_t*)(band * 2 + 1));

	        if(l1 >= 0 && l1 < 128)
	        {
		        set_coils(l1);
		        i = l1;
	        }
	        else
	        {
		        set_coils(65);
		        lcd_putstring(0, 0, " -x-uH");
		    }    
									
														
			if(c1 >= 0 && c1 <= MAXCAP)
			{
			    set_cap(c1);
			}	
			else
			{
				lcd_putstring(0, 7, "-x-pF");
			}	
				
			show_band(band);
			lcd_putstring(1, 0, "             ");
			while(get_keys());
		}
		
        
        if(key == 5) //Band (+)
		{
		    show_band(band);
			lcd_line_cls(1);
			
		    runsecs2 = runsecs;
			ok = 0;
			lcd_putstring(1, 0, "Waiting....");
			while(get_keys() == 5 && !ok)
			{
			    
			    lcd_putnumber(1, 10, 3 - (runsecs - runsecs2), -1);
				if(runsecs - runsecs2 > 2)
				{
				    ok = 1;
				}	
			}	
			
			if(runsecs > runsecs2 + 1) //Key has been pressed for longer than a second, new values for current band to be set
			{                          //Also store values in EEPROM 
			    while(!eeprom_is_ready());
				eeprom_write_byte((uint8_t*)(band * 2), i); 
				
			    while(!eeprom_is_ready());
				eeprom_write_byte((uint8_t*)(band * 2 + 1), get_cap());
				
				while(!eeprom_is_ready());
				eeprom_write_byte((uint8_t*)32, band);
								
	            lcd_line_cls(1);
				lcd_putstring(1, 0, "Stored.");				
				wait_ms(1000);
				lcd_line_cls(1);
			}
            else	
			{
			    if(band < MAXBANDS) //Change band 1 up
				{
				    band++;
				}
                				
				while(!eeprom_is_ready());
				eeprom_write_byte((uint8_t*)32, band);
				
				show_band(band);
				
				lcd_putstring(1, 0, "Recalling.");
				
			    l1 = eeprom_read_byte((uint8_t*)(band * 2));
				c1 = eeprom_read_byte((uint8_t*)(band * 2 + 1));
								
	            if(l1 >= 0 && l1 < 128)
	            {
		            set_coils(l1);
		            i = l1;
	            }
	            else
	            {
		            set_coils(65);
		            lcd_putstring(0, 0, " -x-uH");
		            wait_ms(1000);
		        }    
									
														
			    if(c1 >= 0 && c1 <= MAXCAP)
			    {
			        set_cap(c1);
			    }	
			    else
			    {
				     lcd_putstring(0, 7, "-x-pF");
			    }	
			    lcd_putstring(1, 0, "             ");
			}	
		}
		
		//Meter check
        if(loopcnt0++ > 10)
        { 
            
            s0 = get_adc(0) - s0off;
            s1 = get_adc(1) - s1off;
            
            if(s0 != s0_old)
            {
				if(s0 > 999)
				{
					s0 = 999;
				}	
				lcd_putstring(1, 0, "FWD:    "); 
				lcd_putnumber(1, 4, s0, -1);
				s0_old = s0;
			}
			
			if(s1 != s1_old)
            {
				if(s1 > 999)
				{
					s1 = 999;
				}
				lcd_putstring(1, 8, "REF:     "); 
				lcd_putnumber(1, 12, s1, -1);
				s1_old = s1;
			}	
            
            loopcnt0 = 0;
        }    
        
	}
	return 0;
}


 

Advertisements

The semi-automatic antenna tuner – Version 1b

This article is outdated! Please read about the new version of the antenna tuner here!


People frequently reading my blog know that I love to improve the things presented here. This is revision one of my semi-automatic antenna tuner for QRP. I found that the reading of the SWR value on the LCD is a little bit uncomfortable. So I decided to use an “old-style” analogue meter. This one has been pulled from a home stereo amplifier.

Semi-automatic antenna tuner V2 (C) DK7IH
Semi-automatic antenna tuner V2 (C) DK7IH

The problem with the installed directional coupler is that the amount of energy and so the induced voltage is a reverse function of coupled frequency. Thus an operational amplifier has been added to amplify the DC voltage from the directional coupler. A 50k stereo potentiometer regulates negative feedback an so reduces the op’s gain.

Semi-automatic antenna tuner V2 (C) DK7IH
Semi-automatic antenna tuner V2 (C) DK7IH

Thanks for watching! 73 de Peter

A semi-automatic antenna tuner for QRP use

This article is outdated! Please read about the new version of the antenna tuner here!


After I had finished my 5 band multibander for QRP SSB operation I had 2 choices becoming QRV on the hf bands – either to build up something like an antenna farm (which would have caused severe problems with my familiy 😉 ) or to build a multi band antenna capable of being used on all short wave ham bands. In order to survive the next months with more or less stable health I have decided to take the latter alternative.

Browsing my good old antenna handbook by Rothammel I came across an untuned multiband dipole. This is known sometimes as a “doublet antenna“. It’s a simple dipole, fed by an open wire feed line which has to be matched to the transmitter for each band of operation. The length of one branch of this antenna is about a quarter wavelength of the lowest operating frequency which makes it a half-wave dipole for in my case 80 meters. On the internet I found lots of users of this antenna speaking positively about its performance, so I decided to give it a try. Antenna construction is very simple and the doublet antenna does not spoil the optical impression of your ground property seroiusly.

But one major shortcoming of this antenna should not be ignored: The “doublet” antenna can not be operated directly from coax line, it has to be matched for each band seperately to the desired frequency with its specific impedance to come as close as possible to the 50 ohm of the transceiver. Open wire feed line must be used because there is always a high VSWR on the feedline due to the fact that the dipole is not tuned to the operating frequency. But as losses are low in double wire line even if SWR is high, this is not a problem. Be sure that more than 95% of your transmit power will reach the antenna.

Due to the fact that my antenna installation requires only 5 to 6 meters of feedline from my roof window to the antenna’s feed point, I first built a ladder line from flexible cable and homemade acrylic spacers. But this tended to be a little bit service-unfriendly. Always whenI tried to pull back the antenna for modifications, the line (the spacers to say more detailed)  got entangled in the roofing-tiles. So I bought commercial 450-Ohm Wireman line that does not show this problem.:

Double Zepp (Doublet) antenna - Multiband with tuner and 450 Ohms feed line
Double Zepp (Doublet) antenna – Multiband with tuner and 450 Ohms feed line

After having installed antenna and feedline, I first I built a simple L-match tuner for test purposes. If this antenna had not worked with me I would not have lost much time and money. But no need to worry. After having set up the antenna and the tuner I was quite satisfied. Performance was beyond my expectations. But with using this setup more often, I found out that retuning after having QSYed was not that nice. I had written down the settings for capacitor und inductance on a piece of paper so that they could be recalled relatively quickly. But it was not overwhelming conveniant. Thus my idea was: If you have the settings for each band on a paper table, why not putting them into a microcontroller and let the micro do the tuning?

The basic concept of the tuner

The tuner is an L-Match tuner that can match high Z antennas. Long antennas tend to have higher impedances than usually the 50 ohm transceiver’s output. Integrated into the tuner is also an SWR measurement circuit (directional coupler from old CB radio) so that an external SWR meter is not neccessary. The tuner is tuned manually. After matching has been achieved, the values for L and C are stored by pressing a button and can later be recalled by bandswitch. Retuning is easy. Just press buttons for L+, L-, C+ or C-, retune and store the modified settings. After that: Have fun in a QSO!

Coils

There are 6 coils in the tuner, switched (shortened) by 6 relays. The inductances are doubled (more or less) from one coil to the successor, so that in combination nearly each inductance between 0.5 uH and 39 uH can be switched. It turned out that this concept works fine. The single inductances are:

20uH, 10 uH, 5 uH, 2.5 uH, 1 uh, 0.5 uH

Coil data: Each coil except the smallest one is wound on a T80-2 Amidon toroid. Use 0.3 mm diameter copper enameled wire. The winding data:

  • L1 (20uH):  60T.
  • L2 (10uH): 43T.
  • L3 (5uH):  30T.
  • L4 (2.5uH): 21T.
  • L5 (1uH):  13T.
  • L6 (0.5uH, wound on T50-2 core): 10T.

Output transformer

Another coil must be wound because the antenna has an unbalanced circuit inside (1 coil, 1 cap). The feed line on the other hand is balanced, so this has to be kept in mind. To convert the unbalanced output of the tuner circuit to the balanced feeder line, I use a 1:4 balun at the output of the coil chain (T1 in circuit diagram). Wind 12 turns bifilar of 0.8 mm twisted (about 3 twists per cm) enameled copper wire to a FT114-43 Amidon core using this pattern.

Hint: On the picture below there is a balun transformer that I previously had installed. It was a Guanella balun but it did not perform satisfyingly. Tuning could not easily be achieved on 10 and 15 meters.

Capacitor

The tuner uses a motor driven air dielectrical and butterfly shaped capacitor with max. 220 pF capacity. The advantage of a butterfly type is that it needs only 90° to turn it from minimum to maximum capacity. The motor (a 5V dc version) is connected via a 240:1 gear drive by TAMIYA. The drive has two outlets providing one axle at each side of the drive. To one of the axles I connected the capacitor, the other one connects to a potentiometer to report the current swing angle to the microcontroller.This allows precise feedback of the capacitor’s current position which is essential for setting it to the desired value. The value of this variable resistor does not really matter since it is only a simple voltage divider. Anything between 5k and 100k should fit. Make sure that you use a piece that is easy to turn to minimize friction. To connect the axles I used PVC tubing with an inside diameter of 3 mm.

This is the setup:

Semi automatic antenna tuner for QRP (C) 2016 by Peter Rachow (DK7IH)
Semi automatic antenna tuner for QRP (C) 2016 by Peter Rachow (DK7IH)

Circuit

Here’s the schematic of the tuner:

Semi automatic antenna tuner for QRP (C) 2016 by Peter Rachow (DK7IH)
Semi automatic antenna tuner for QRP (C) 2016 by Peter Rachow (DK7IH)

Right at the 50 Ohms input where the transceiver is connected you can see a 120 kOhm resistor. The purpose of this one is to keep static electricity away from your rig. Antennas with open ends (like the “doublet”) can build up high voltages particularly when strong rainfall coincides with heavy winds. The raindrops build up an electrical potential during their way through the clouds. I once have seen sparks of 1 to 2 cm of length in my shack when I brought the feed line wire of the antenna close to a grounded metal cabinet.

First impression of performance

I have been using the tuner for three weeks by now. My antenna has got a total length of 40 meters, height is from 10 to 12 meters above ground. Feed point is approximately centered. The antenna with this tuner allows operation on all the 5 bands of my QRP multibander. Signal reports are usually good. On 20m I receive 5 and 9 reports very often. Transmit power only is 10 watts. On 40m and 80m the same is true. Even 15 meters, usually not so fine on a 40 meter long doublet, works fine. 10 meters has not been tested yet due to band conditions.

Maximum distance so far was to W2YP (East coast NY) with my rig having 10 watts output on 25th February receiving a 57 report.

Enclosure

I used a simple plastic box that is available for eletrical installations. RF leads are on top:

Semi automatic antenna tuner for QRP (C) 2016 by Peter Rachow (DK7IH)
Semi automatic antenna tuner for QRP (C) 2016 by Peter Rachow (DK7IH)

Software

I’m currently doing some improvements concerning software. If you are interested in the software, please drop me a mail: peter.rachow(at)web.de !

Enhancing the tuner

This tuner mainly for matching long wire antennas which have a comparatively high Z in relation to the 50 Ohms of a radio tranceiver. If you also want to match low Z antennas (shorter than 1/4 wavelength), the capacitor must be put to the opposite of the coils:

tuner-for-hi-or-lo-z

If you would like to have the capacitor in place for switching between hi an low Z antennas another relay will do the job. The microntroller has still plenty of usable ports.

Thanks for reading!

Peter (DK7IH)

Mounting a rod antenna to a homemade handheld QRP transceiver

When I started to recognize that going outside with a small handheld QRP SSB transceiver for the 20 meter band is more than just a test to find out doesn’t work at all, I conceived a more rugged mounting for the partable rod antenna. Due to the fact that this antenna (which now is about 220 centimeters long) exerts significant leverage to the BNC connector and thus to the cabinet of my transceiver. After 3 or 4 periods of outdoor usage I found that it had cut the front panel with the BNC socket from the transceiver’s inner cabinet frame. F…! (F…-word censored!)

The objective of a practical solution was to keep away excessive leverage force from the transceiver. The most practical way to solve this problem was to construct a simple mounting frame that could bear the force without leading it to the radio:

Antenna mounting frame for portable rod-antenna (C) by Peter Rachow- DK7IH
Antenna mounting frame for portable rod-antenna (C) by Peter Rachow- DK7IH

The holder is made of 0.8 mm Aluminium in u-shaped form where the radio fits in. The rig’s cabinet screws hinder the TRX from falling outside, a Velcro® strip fixes the radio inside the frame. On the backside of the frame I’ve attached a piece of aluminium pipe where the base of the antenna fits in. That’s all:

QRP SSB handheld tranceiver in mounting frame for portable rod-antenna (C) Peter Rachow - DK7IH
QRP SSB handheld tranceiver in mounting frame for portable rod-antenna (C) Peter Rachow – DK7IH

Easy and practical. That’s the way it’s got to be!

Annotation: I once again revised the antenna. The matching circuit was abolished. I now simply use a larger coil of about 55 turns of 1 mm diameter enameled wire on an 8.5 mm diameter PVC rod. Works great. Standing wave ratio is 1.1 to 1! 😉

73 de Peter (DK7IH)

(C) 2015 by Peter Rachow

Improved matching for 20-meter-band rod antenna

Recently I have revised the rod antenna for my handheld QRP SBB transceiver. The main objective was to simplify the matching circuit. As I’ve pointed out before in the antenna article, one of the major problems with shortened antennas is the low feed point impedance. The first version of the antenna matcher used a capacitor and a coil to form part of a PI-filter. This new circuit uses an autotransformer made of a linear coil.

Improved version of rod antenna for 20 meter handheld SSB QRP  transceiver (C) Peter Rachow (DK7IH)
Improved version of rod antenna for 20 meter handheld SSB QRP transceiver (C) Peter Rachow (DK7IH)

The tap is at about 1/4th of the total windings which transforms the feed point impedance of about 10 ohms to the coxial cable with 50 ohms. A 5 meter wire acting as the second part of the dipole should be used to increase performance of the rod antenna. All dimension concerning antenna length have remained unaltered, please see respective article!

An easy-to-build rod antenna for 14 MHz (20 meter band)

For my handheld QRP transceiver I have developed a rod antenna for outdoor use when cycling or hiking. In this article I’ll first give the reader some basic considerations on shortened antennas and afterwards the pracital consequences of these.

Shortened Antennas

A full-sized vertical antenna usually has got a length of a quarter wavelength. Some special constructions of a 1/2, 5/8 wavelength and others are also commonly known. But for a rod antenna the basic construction is a 1/4 wavelength based circuit. Full-size 1/4 wavelength antennas that have the correct length (1/4 multiplied by 0.95 shortening factor) have got a feed point impedance of between 40 to 50 ohms. So they can be directly connected to a 50 ohm coaxial cable. The problem: For 14 MHz this antenna would have an overall length of about 5 meters. Not very appropriate for a handheld transceiver except you were Arnold Schwarzenegger.. 😉

When the mechanical length of an antenna is shorter than 1/4 of the wavelength that it is desired for, a mismatch can be obeserved. The antenna not longer is resonant to the operating frequency. An additional capacitive reactance appears. This must be compensated by an inductive reactance. Therefore shortened antennas have an integrated coil either at the bottom (bottom loading coil), anywhere in the middle (center loading coil) or top (top loading coil).

Another problem must be faced: Feed point impedance is usually much lower than for a full size antenna. Sometimes only between 10 and 15 ohms. Thus some sort of impedance matching circuit must be integrated, too,

Last, degree of effiency will also decrease. So, don’t expect too much from a shortened antenna!

To sum up the things that have been mentioned before: We have to face 2 general electrical problems with short antennas:

  • A correct loading coil must be found, and
  • proper impedance matching must be performed.

Practical construction

Into my antenna I integrated 2 loading coils. One at the bottom to serve as an impedance matcher and one slightly below the center to compensate capacitive reactance.

The circuit:

A whip antenna for 14 MHz (C) Peter Rachow, DK7IH, 2015
A whip antenna for 14 MHz (C) Peter Rachow, DK7IH, 2015

The antenna is mounted to a standard male BNC-connector.

Mechanical deimensions and coil data:

Bottom coil (L2):

L2, the bottom coil, is 50 turns of 1 mm diameter enameled wire wound on a 8mm diameter plastc tubing from the local hardware store. From the bottom end of L2 a 120 pF capacitor is lead to the ground potential of the BNC plug. This, together with L2 sets up low pass filter serving as an impedance matcher.

Edit: Another impedance matching circuit I’ve described here.

The plastic tubing used for L1 and L2 is hollow. Into this tubing a 6mm diameter aluminium rod fits in exactly. The length of the rod between the two coils is 45 cm. Following is another piece of the plastic tubing carriyng L1.

Center coil (L1): L1 is 45 windings of 0.6 mm diameter enameled wire.

The top rod of the antenna is a telescopic antenna with an overall length of 120 cm that can be bought on the internet. It’s outer diameter is also 6 mm, so it also fits into the plastic rod.

Here are the pictures to make clearer how the antenna is constructed:

Whip antenna for 14 MHz (C) Peter Rachow, DK7IH, 2015
Rod antenna for 14 MHz (C) Peter Rachow, DK7IH, 2015
Full view of whip antenna for 14 MHz (C) Peter Rachow, DK7IH, 2015
Full view of rod antenna for 14 MHz (C) Peter Rachow, DK7IH, 2015

To increase the usually low degree of efficiency of such an antenna I have manufactured a sort of “counterpoise” that represents the 2nd part of a dipole : A 5 meter long insulated cable with a large crocodile clip that is clipped to the ground potential of the metal BNC connector.

Edit: In the meanwhile I have used this rod antenna for 14 MHz / 20 meters several times during outdoor activities. What I’d never have believed: I could make lots of QSOs with it! Particularly if you are in a high place (e. g. on a look-out) you can work distances of about 1000 to 3000 kilometers right with 4 watts out of your hands. Provided the station you’re answering is strong. Then there is a realistic chance that he might hear you with reasonable signal strengh.