49er active bridge

The 49er active bridge is an Arduino Uno code for an Vswr bridge for the 49er circuit board, or any other radio set design. The code is sourced from the video shown in the posted article "ATU design ideas and SWR measurement principles". In this adaption, a 2 line 16 character display is used, the active bridge to used along side the 49er digital vfo arduino board, for a 49er radio set with two Arduino Uno units each with its own display panel. Although the 49er active bridge shown here is setup for the QRP 49er 40m radio set circuit board, the active bridge application could be used for any of the ham radio band plans, but admittedly the appropriate circuit constructions techniques for the intended band plan use would have to be considered for the required design needs.

The two arduino boards, the 49er digital vfo and the 49er active bridge, are synched together by connect both pin 4 used for the CW key. The CW key is used as an active Tx Low, active Rx high.

While in Tx mode, the 49er digital vfo will show the "Tx CW 40m" and the dial frequency upon which the CW carrier would exactly appear, would be the dial frequency as indicated. The 49er active bridge would then illustrate the Tx signal power and the SWR measurement ratio, from which the measured SWR ratio when the 49er active bridge is in RX mode, would illustrate the calculated antenna loading as a transmission line impedance.

In Rx mode the 49er digital vfo would show "Rx CW 40m" as well as the dial frequency, but however the Rx vfo itself would be higher up by 600Hz for the direct conversion audio tone for CW use, thus referring the CW signal as a lower side signal. The 49er active bridge in RX mode will illustrate both the received signal strength as a "dBm" value, and the transmission line impedance of the antenna load. The antenna load variables are as described in the previous article "ATU design ideas and SWR measurement principles".

For the radio set connections to the Arduino Uno analog ports are also listed, by the way, you will need to construct a Vswr absorption bridge to supply the forward and reflected voltages. The log detector and amplifier chip "AD8307", can be used as a Rx signal measurement detector, typical circuit shown below, but there are other published designs that are perhaps also suitable. I suggest it may be best perhaps to place the Rx signal tap after the mixer output and before the Jfet clamping switch on the 49er circuit board. An idea that may well be a good point, if one uses an arduino relay circuit board, then this could be used as an antenna switch relay. I have added a antenna relay switching code to data pin 6 of the "49er digital vfo" coding.

The Tx signal power is a signal that would be used in a power reading and Vswr bridge.

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.

While the "active bridge" would calculate the antenna load as a transmission line characteristic impedance, a "Smart bridge" could then with the measured antenna load have within addition to the overall "Smart bridge" design an "Antenna Matching Unit", to switch in a 1/4 wave matching transmission line section as a "Smart bridge" design application, to match the antenna loading to the radio set.

However for the moment, the arduino code for the "49er active bridge" is listed below, as before copy and paste into your Arduino IDE:

/* This program written by Alastair GW0AJU.

This project is for an active bridge for a "49er" circuit board.

date 05/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 symbol of "ohm"

//******************** morse / PTT key connection **************

int cw_key = 4; // pin 4 for cw key connection

// TX/RX electrical switching for the 49er radio circuitry to pin 4

//**************** 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

// ********* start up display messages ************

lcd.begin (16,2);

// 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");

delay(1500);

lcd.setCursor(0,0); // second line of display

lcd.print(" written by ");

lcd.setCursor(0,1); // second line of display

lcd.print("Alastair GW0AJU");

delay(1500);

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,0);

lcd.print("Tx = ");

lcd.setCursor(5,0);

lcd.print(" ");

lcd.setCursor(5,0);

lcd.print(tx_power_output,2);

lcd.setCursor(11,0);

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,1);

lcd.print("SWR= 1:");

lcd.setCursor(7,1);

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,1); // bottom line of the display

lcd.print(" ");

lcd.setCursor(0,1);

lcd.print("Z= ");

lcd.print(res_load,1);

lcd.write(byte(0));

lcd.print(" ");

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,1); // bottom line of the display

lcd.print(" ");

lcd.setCursor(0,1);

lcd.print("Z= ");

lcd.print(res_load,1);

lcd.write(byte(0));

lcd.print(" ");

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,1); // bottom line of the display

lcd.print(" ");

lcd.setCursor(0,1);

lcd.print("Z= ");

lcd.print(res_load,1);

lcd.write(byte(0));

lcd.print(" ");

lcd.print(cap_scale_t,1);

lcd.print("uF");

}

else if (cap_scale > 1E9 && cap_scale <= 1E12)

{

cap_scale_t = cap_scale/1E9;

lcd.setCursor(0,1); // bottom line of the display

lcd.print(" ");

lcd.setCursor(0,1);

lcd.print("Z= ");

lcd.print(res_load,1);

lcd.write(byte(0));

lcd.print(" ");

lcd.print(cap_scale_t,2);

lcd.print("mF");

}

else if (cap_scale > 1E12)

{

cap_scale_t = cap_scale/1E12;

lcd.setCursor(0,1); // bottom line of the display

lcd.print(" ");

lcd.setCursor(0,1);

lcd.print("Z= ");

lcd.print(res_load,1);

lcd.write(byte(0));

lcd.print(" ");

lcd.print(cap_scale_t,2);

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,1); // bottom line of the display

lcd.print(" ");

lcd.setCursor(0,1);

lcd.print("Z= ");

lcd.print(res_load,1);

lcd.write(byte(0));

lcd.print(" ");

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,1); // bottom line of the display

lcd.print(" ");

lcd.setCursor(0,1);

lcd.print("Z= ");

lcd.print(res_load,1);

lcd.write(byte(0));

lcd.print(" ");

lcd.print(ind_scale_t,1);

lcd.print("nH");

}

else if (ind_scale > 1E6 && ind_scale <= 1E9)

{

ind_scale_t = ind_scale/1E6;

lcd.setCursor(0,1); // bottom line of the display

lcd.print(" ");

lcd.setCursor(0,1);

lcd.print("Z= ");

lcd.print(res_load,0);

lcd.write(byte(0));

lcd.print(" ");

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,1); // bottom line of the display

lcd.print(" ");

lcd.setCursor(0,1);

lcd.print("Z= ");

lcd.print(res_load,0);

lcd.write(byte(0));

lcd.print(" ");

lcd.print(ind_scale_t,1);

lcd.print("mH");

}

else if (ind_scale > 1E12)

{

ind_scale_t = ind_scale/1E12;

lcd.setCursor(0,1); // bottom line of the display

lcd.print(" ");

lcd.setCursor(0,1);

lcd.print("Z= ");

lcd.print(res_load,0);

lcd.write(byte(0));

lcd.print(" ");

lcd.print(ind_scale_t,2);

lcd.print("H");

}

}

if ( res_load == 50)

{

lcd.setCursor(0,1); // bottom line of the display

lcd.print(" ");

lcd.setCursor(0,1);

lcd.print("Z= ");

lcd.print(res_load,0);

lcd.write(byte(0));

lcd.print(" antenna ");

}

}

//**************************** end of program code ****************************