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

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s