The 49er active bridge v2.0, as one or two software upgrades. The display used in this version is a 4 line 20 character display on a i2c data link, which may be used perhaps as an engineering panel for the 49er radio set, or any other radio set design application.
The antenna impedance as seen by the "Swr" measurement has been adjusted to show the "+j" and "-j" notation in-front of the inductance or capacitance component values.
The Arduino Uno analog ports listing is below, however it may be wise to use an external voltage reference and an analog signal ground to increase the conversion accuracy overcoming a digital noisy ground signal.:
analog port A0 = Vswr forward voltage
A1 = Vswr reflected voltage
A2 = Transmitter signal power
A3 = receiver signal strength
A4 = i2c display connection
A5 = i2c display connection
The Tx signal on analog port "A2" has a full scale voltage of 5Volts, as does all the arduino analog ports, but the current with the supplied code the calculated transmitter full power reading is around 40Watts, current code setting. For greater reading change the multiplier "100" to " 1000" for 400Watts full scale, or a multiplier of "10000" for a 4KW maximum reading in the program line below:
float tx_power_output = ((tx_signal_level * tx_signal_level) / 50) * 100; // tx power = (v * v) / antenna
For the Rx signal on analog port "A3", the setting has an S9 signal is -73dBm (50uV), which equates to half voltage on the analog port. The overall "S meter" range from approximately -130dBm (Rx = 0.38uV) to around -60dBm (Rx = 1mV) signal meter, from base ground voltage to full scale voltage on the analog port. "A3". The forward and reflected voltages from analog ports "A0" and "A1", are used to calculate the characteristic impedance of the load antenna, by mathematically calculating the "Zo" from the SWR measured value, and hence then find the load resistance and reactance of the antenna.
Below is a photo picture illustrating both the digital vfo and active bridge display panels, each panel is connected to its own Arduino Uno development board. The two Arduino Uno boards are synchronised together by the CW key line of "D4".
/*
This program written by Alastair GW0AJU.
This project is for an active bridge for a "49er" circuit board.
date 19/11/15
Ardunio board used = Ardiuno Uno
*/
#include <math.h> // (no semicolon)
//********** liquid display setup *********
#include <Wire.h>
#include <LCD.h>
#include <LiquidCrystal_I2C.h>
#define I2C_ADDR 0x27 // <<- Add your address here.
#define Rs_pin 0
#define Rw_pin 1
#define En_pin 2
#define BACKLIGHT_PIN 3
#define D4_pin 4
#define D5_pin 5
#define D6_pin 6
#define D7_pin 7
LiquidCrystal_I2C lcd(I2C_ADDR,En_pin,Rw_pin,Rs_pin,D4_pin,D5_pin,D6_pin,D7_pin);
byte a[8] = {B00000,
B01110,
B10001,
B10001,
B01010,
B01010,
B11011,}; // character of the synbol of "ohm"
//******************** morse / PTT key connection **************
int cw_key = 4; // pin 4 for cw key connection
int cw_tone;
int cw_sense;
int PTT_key = 7; // ptt switch on microphone
// tie all TX/RX electrical switching for the 49er radio circuitry to pins 4 and 7,
// logic connection through OR-gate switching of sensing pins 4 and 7 for TX/RX modes.
//**************** SWR bridge and antenna load calculations ****************
float rx_dbm =0;
long rx_signal_value = 0;
long swr_forward = 0;
long swr_reflected = 0;
float swr_match = 0;
float vswr_forward = 0;
float vswr_reflected = 0;
float v_forward = 0;
float v_reflected = 0;
float v_forward_w = 0;
float v_reflected_w = 0;
float top = 0;
float bot = 0;
float swr_impedance = 0;
float tswr_impedance = 0;
float RL = 0;
float Zin = 0;
float swr =0;
float opp = 0;
float ind = 0;
float cap = 0;
float cap_scale = 0;
float ind_scale = 0;
float cap_scale_t = 0;
float ind_scale_t = 0;
float res = 0;
float res_load = 0;
int run_one = 1;
//*********** transmitter power and receive signal power mearsurements ********
float rx_signal_level = 0;
float rx_signal_voltage = 0;
float tx_signal_level = 0;
float tx_power_output = 0;
int key_alter = 0;
//********** start of arduino DDS VFO control program *********
void setup()
{
Serial.begin(9600);
pinMode(cw_key, INPUT); // morse key
pinMode(PTT_key, INPUT); // ptt switch on microphone
// ********* start up display messages ************
lcd.begin (20,4);
// LCD Backlight ON
lcd.setBacklightPin(BACKLIGHT_PIN,POSITIVE);
lcd.setBacklight(HIGH);
lcd.home();
lcd.createChar(0,a);
lcd.setCursor(0,0); // first line of display
lcd.print(" 49er QRP Radio");
lcd.setCursor(0,1);
lcd.print(" active bridge v2");
lcd.setCursor(0,2); // second line of display
lcd.print(" program code by ");
lcd.setCursor(0,3); // second line of display
lcd.print(" Alastair GW0AJU");
delay(1500);
lcd.setCursor(0,1);
lcd.print("test transmitter ");
lcd.setCursor(0,2); // second line of display
lcd.print("test antenna ");
RL = 50; // start up antenna value
}
//************* void loop ***********************
void loop()
{
radio_monitor();
}
//*************** start of program code sub-routines ****************
//************ transmit / receive control subroutine ********
void radio_monitor()
{
if (digitalRead(cw_key) == HIGH || digitalRead(PTT_key) == HIGH)
{
rx_pwr();
if (run_one == 1)
{
active_load();
run_one = 0; // to stop display of active components message flickering
}
}
else if (digitalRead(cw_key) == LOW || digitalRead(PTT_key) == LOW)
{
tx_pwr();
run_one = 1; // to stop display of active components message flickering
}
}
//**************** processes for receive mode ***************
void rx_pwr()
{
double Rx_signal; rx_signal_voltage;
int rx_signal_value = analogRead(3); // analog port 3 to measure RX signal input
rx_signal_voltage = ((rx_signal_value));
Rx_signal = (double)log10((1/(rx_signal_voltage * rx_signal_voltage)));
Serial.println(rx_signal_value);
int range = 22; // scale the range of the rx_dBm measurement on analog(3)
int offset = 470; // to offset the rx_dBm into a required window measurement
rx_dbm = (offset - ((Rx_signal + 30) * range));
// an S9 signal is -73dBm (50uV), which equates to half voltage on the analog port
// range from approximately -130dBm (0.38uV) to around -60dBm (1mV) signal meter
lcd.home();
lcd.setCursor(0,0);
lcd.print("Rx = ");
lcd.setCursor(5,0);
lcd.print(" ");
lcd.setCursor(5,0);
lcd.print(rx_dbm,0);
lcd.setCursor(11,0);
lcd.print("dBm ");
}
// ****************************************************************************************
//********** processes for transmit mode ***************
void tx_pwr()
{
float tx_power_measure = analogRead(2); // analog 2 to measure tx power output
float tx_signal_level = 0.0048 * tx_power_measure;
float tx_power_output = ((tx_signal_level * tx_signal_level) / 50) * 100; // tx power = (v * v) / antenna
lcd.home();
lcd.setCursor(0,1);
lcd.print("Tx = ");
lcd.setCursor(5,1);
lcd.print(" ");
lcd.setCursor(5,1);
lcd.print(tx_power_output,2);
lcd.setCursor(11,1);
lcd.print("Watts");
swr_forward = 0; // reset value to zero
swr_reflected = 0; // reset value to zero
swr_forward = analogRead(0);
swr_reflected = analogRead(1);
v_forward = 0.0048 * swr_forward; // forward swr voltage
v_reflected = 0.0048 * swr_reflected; // reverse swr voltage
float ratio = v_reflected / v_forward;
float swr_value = ratio;
RL = swr_value * 50; // assume match to a 50ohm co-axial cable
lcd.setCursor(0,2);
lcd.print("Swr= 1:");
lcd.setCursor(7,2);
lcd.print(swr_value,4);
lcd.print(" ");
}
//*************** calculate the active load of the antenna *****************
void active_load()
{
res_load = RL;
//******* capacitive loaded antenna *****
if (res_load < 50)
{
cap = 300E-9 / ( res_load * res_load);
cap_scale = cap * 1E12;
if (cap_scale <= 1000)
{
cap_scale_t = cap_scale;
lcd.setCursor(0,3); // bottom line of the display
lcd.print(" ");
lcd.setCursor(0,3);
lcd.print("Imp= ");
lcd.print(res_load,1);
lcd.write(byte(0));
lcd.print("-j");
lcd.print(cap_scale_t,0);
lcd.print("pF");
}
else if (cap_scale > 1E3 && cap_scale <= 1E6)
{
cap_scale_t = cap_scale/1E3;
lcd.setCursor(0,3); // bottom line of the display
lcd.print(" ");
lcd.setCursor(0,3);
lcd.print("Imp= ");
lcd.print(res_load,1);
lcd.write(byte(0));
lcd.print("-j");
lcd.print(cap_scale_t,1);
lcd.print("nF");
}
else if (cap_scale > 1E6 && cap_scale <= 1E9)
{
cap_scale_t = cap_scale/1E6;
lcd.setCursor(0,3); // bottom line of the display
lcd.print(" ");
lcd.setCursor(0,3);
lcd.print("Imp= ");
lcd.print(res_load,2);
lcd.write(byte(0));
lcd.print("-j");
lcd.print(cap_scale_t,2);
lcd.print("uF");
}
else if (cap_scale > 1E9 && cap_scale <= 1E12)
{
cap_scale_t = cap_scale/1E9;
lcd.setCursor(0,3); // bottom line of the display
lcd.print(" ");
lcd.setCursor(0,3);
lcd.print("Imp= ");
lcd.print(res_load,1);
lcd.write(byte(0));
lcd.print("-j");
lcd.print(cap_scale_t,1);
lcd.print("mF");
}
else if (cap_scale > 1E12)
{
cap_scale_t = cap_scale/1E12;
lcd.setCursor(0,3); // bottom line of the display
lcd.print(" ");
lcd.setCursor(0,3);
lcd.print("Imp= ");
lcd.print(res_load,1);
lcd.write(byte(0));
lcd.print("-j");
lcd.print(cap_scale_t,1);
lcd.print("F");
}
}
///***** inductive loaded antenna ******
if (res_load > 50)
{
ind = (res_load * res_load) * 120E-12;
ind_scale = ind * 1E12;
if (ind_scale <= 1000)
{
ind_scale_t = ind_scale;
lcd.setCursor(0,3); // bottom line of the display
lcd.print(" ");
lcd.setCursor(0,3);
lcd.print("Imp= ");
lcd.print(res_load,1);
lcd.write(byte(0));
lcd.print("+j");
lcd.print(ind_scale_t,0);
lcd.print("pH");
}
else if (ind_scale > 1E3 && ind_scale <= 1E6)
{
ind_scale_t = ind_scale/1000;
lcd.setCursor(0,3); // bottom line of the display
lcd.print(" ");
lcd.setCursor(0,3);
lcd.print("Imp= ");
lcd.print(res_load,1);
lcd.write(byte(0));
lcd.print("+j");
lcd.print(ind_scale_t,0);
lcd.print("nH");
}
else if (ind_scale > 1E6 && ind_scale <= 1E9)
{
ind_scale_t = ind_scale/1E6;
lcd.setCursor(0,3); // bottom line of the display
lcd.print(" ");
lcd.setCursor(0,3);
lcd.print("Imp= ");
lcd.print(res_load,0);
lcd.write(byte(0));
lcd.print("+j");
lcd.print(ind_scale_t,1);
lcd.print("uH");
}
else if (ind_scale > 1E9 && ind_scale <= 1E12)
{
ind_scale_t = ind_scale/1E9;
lcd.setCursor(0,3); // bottom line of the display
lcd.print(" ");
lcd.setCursor(0,3);
lcd.print("Imp= ");
lcd.print(res_load,0);
lcd.write(byte(0));
lcd.print("+j");
lcd.print(ind_scale_t,2);
lcd.print("mH");
}
else if (ind_scale > 1E12)
{
ind_scale_t = ind_scale/1E12;
lcd.setCursor(0,3); // bottom line of the display
lcd.print(" ");
lcd.setCursor(0,3);
lcd.print("Imp= ");
lcd.print(res_load,0);
lcd.write(byte(0));
lcd.print("+j");
lcd.print(ind_scale_t,1);
lcd.print("H");
}
}
if ( res_load == 50)
{
lcd.setCursor(0,3); // bottom line of the display
lcd.print(" ");
lcd.setCursor(0,3);
lcd.print("Imp= ");
lcd.print(res_load,0);
lcd.write(byte(0));
lcd.print(" antenna ");
}
}
//**************************** end of program code ****************************