Skip to content

Instantly share code, notes, and snippets.

@NT7S
Created April 20, 2015 21:12
Show Gist options
  • Save NT7S/3acfd9e00e60b1bfd0f6 to your computer and use it in GitHub Desktop.
Save NT7S/3acfd9e00e60b1bfd0f6 to your computer and use it in GitHub Desktop.
Si5351 Antenna Analyzer
#include <si5351.h>
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <Wire.h>
#include <DFR_Key.h>
#include <LiquidCrystal.h>
#define V_SAMPLE A1
#define I_SAMPLE A2
#define Z0 50
#define SLOPE 0.178
#define INTERCEPT -76
LiquidCrystal lcd( 8, 9, 4, 5, 6, 7 );
Si5351 si5351;
DFR_Key keypad;
int index = 0;
float swr = 0.0F;
float ant_v, ant_i, ant_z;
unsigned long freq = 28500000UL; // Initialization frequency
unsigned int tune_step = 5; // This is in 10^tune_step Hz
void setup()
{
// Start up serial
Serial.begin(57600);
// Setup the LCD
lcd.begin(16, 2);
lcd.cursor();
// Setup keypad
keypad.setRate(10);
// Setup ADC
pinMode(V_SAMPLE, INPUT);
pinMode(I_SAMPLE, INPUT);
// Setup Si5351
si5351.init(SI5351_CRYSTAL_LOAD_8PF, 0);
si5351.drive_strength(SI5351_CLK0, SI5351_DRIVE_2MA);
si5351.set_correction(0); // Change to appropriate cal constant
}
void loop()
{
char temp_str[17];
unsigned int v_adc, i_adc, key;
// Tune the Si5351A
tune(freq);
// Read SWR bridge values
v_adc = analogRead(V_SAMPLE);
i_adc = analogRead(I_SAMPLE);
ant_v = SLOPE * v_adc + INTERCEPT;
ant_i = SLOPE * i_adc + INTERCEPT;
ant_z = (convert_dbm_milliwatts(ant_v) / convert_dbm_milliwatts(ant_i)) * Z0;
if(ant_z >= Z0)
{
swr = ant_z / Z0;
}
else
{
swr = Z0 / ant_z;
}
sprintf_seperated(temp_str, freq);
lcd.setCursor(0, 0);
lcd.print(temp_str);
lcd.setCursor(0, 1);
lcd.print("SWR: Z: ");
lcd.setCursor(4, 1);
if(swr > 10.0F/* || swr < 1.0F*/)
{
lcd.print(">10");
lcd.setCursor(11, 1);
lcd.print((unsigned int)ant_z);
}
else
{
lcd.print(swr, 2);
lcd.setCursor(11, 1);
lcd.print((unsigned int)ant_z);
}
// Set the cursor under the digit to change
// First find the number of digits in the freq
unsigned int digits = 0;
unsigned long temp_freq = freq;
while(temp_freq > 0)
{
temp_freq /= 10;
digits++;
}
// Next, find number of commas in displayed freq
unsigned int commas = 0;
temp_freq = freq;
while(temp_freq > 999)
{
temp_freq /= 1000;
commas++;
}
// Then find number of commas to skip in tune step
unsigned int comma_skip = 0;
temp_freq = power_10(tune_step);
while(temp_freq > 999)
{
temp_freq /= 1000;
comma_skip++;
};
// Now calculate the cursor position
unsigned int cur_pos = 9 + commas - tune_step - comma_skip - 1;
lcd.setCursor(cur_pos, 0);
// Read buttons
key = keypad.getKey();
// TODO: tuning limits from library
switch(key)
{
case 2: // left
if(tune_step < digits)
{
tune_step++;
}
break;
case 3: // up
if(freq + power_10(tune_step) < 160000000)
{
freq += power_10(tune_step);
}
break;
case 4: // down
if((freq > power_10(tune_step)) && (freq - power_10(tune_step) > 8000))
{
freq -= power_10(tune_step);
}
break;
case 5: // right
if(tune_step > 0)
{
tune_step--;
}
break;
}
// Handle serial commands
while (Serial.available() > 0) // see if incoming serial data:
{
char inData = Serial.read(); // read oldest byte in serial buffer:
uint32_t a;
switch(inData)
{
case 'F':
a = Serial.parseInt();
//Serial.println(a);
freq = a;
tune(freq);
break;
case 'R':
Serial.print(freq);
Serial.print(",");
Serial.print(swr);
Serial.print(",");
Serial.println(ant_z);
break;
}
}
}
void tune(unsigned long tune_freq)
{
si5351.set_freq((unsigned long long)tune_freq * 100ULL, 0, SI5351_CLK0);
}
void sprintf_seperated(char *str, unsigned long num)
{
// We will print out the frequency as a fixed length string and pad if less than 100s of MHz
char temp_str[6];
int zero_pad = 0;
// MHz
if(num / 1000000UL > 0)
{
sprintf(str, "%3lu", num / 1000000UL);
zero_pad = 1;
}
else
{
strcat(str, " ");
}
num %= 1000000UL;
// kHz
if(zero_pad == 1)
{
sprintf(temp_str, ",%03lu", num / 1000UL);
strcat(str, temp_str);
}
else if(num / 1000UL > 0)
{
sprintf(temp_str, ",%3lu", num / 1000UL);
strcat(str, temp_str);
zero_pad = 1;
}
else
{
strcat(str, " ");
}
num %= 1000UL;
// Hz
if(zero_pad == 1)
{
sprintf(temp_str, ",%03lu", num);
strcat(str, temp_str);
}
else
{
sprintf(temp_str, ",%3lu", num);
strcat(str, temp_str);
}
strcat(str, " MHz");
}
unsigned long power_10(unsigned long exponent)
{
// bounds checking pls
if(exponent == 0)
{
return 1;
}
else
{
return 10 * power_10(exponent - 1);
}
}
float convert_dbm_milliwatts(float dbm)
{
return pow(10, (dbm / 10));
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment