/* This program written by Alastair GW0AJU. The program application is a an "Impedance SWR active bridge". The application is intended to provide a realtime measurement of the radio transmitter antenna while in operation, with the "Impedance SWR active bridge" as an inline SWR meter. Ardunio board used = Ardiuno Uno date: 12th January 2016 */ #include // (no semicolon) //********** liquid display setup ********* #include #include #include #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" byte b[8] = {B00000, B00001, B00010, B00100, B01000, B10000, B11111,}; // character of the symbol of "angle" byte c[8] = {B01110, B10001, B10001, B01110, B00000, B00000, B00000,}; // character of the symbol of "degrees" //**************** SWR bridge and antenna load calculations variables **************** long swr_forward = 0; long swr_reflected = 0; float vswr_forward = 0; float vswr_reflected = 0; float v_forward = 0; float v_reflected = 0; float swr_impedance = 0; float RL = 0; float Zin = 0; float swr =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; //*********** transmitter power variables ************ float rx_signal_level = 0; float rx_signal_voltage = 0; float tx_signal_level = 0; float tx_power_output = 0; //******** start of program code for the impedance swr active brdige ****** void setup() { // ********* start up display messages ************ lcd.begin (20,4); // LCD Backlight ON lcd.setBacklightPin(BACKLIGHT_PIN,POSITIVE); lcd.setBacklight(HIGH); lcd.createChar(0,a); // ohms symbol lcd.createChar(1,b); // angle symbol lcd.createChar(2,c); // degrees symbol lcd.clear(); lcd.home(); lcd.setCursor(0,0); // first line of display lcd.print(" Impedance SWR"); lcd.setCursor(0,1); // second line of display lcd.print(" active bridge"); lcd.setCursor(0,2); // third line of display lcd.print(" program code by"); lcd.setCursor(0,3); // fourth line of display lcd.print(" Alastair GW0AJU"); delay(2000); lcd.clear(); lcd.home(); lcd.setCursor(0,0); // first line of display lcd.print("Transmitter power"); lcd.setCursor(0,1); // second line of display lcd.print("Standing wave ratio"); lcd.setCursor(0,2); // third line of display lcd.print("Impedance vector"); lcd.setCursor(0,3); // fourth line of display lcd.print("Transmission line"); delay(2000); lcd.clear(); lcd.home(); RL = 50; // start up antenna value } //************* void loop *********************** void loop() { radio_monitor(); delay(400); // 400ms delay between display updates to prevent display flickering } //*************** start of program code sub-routines **************** void radio_monitor() { active_load(); tx_pwr(); } //********** calculation processes for the impedance SWR active bridge *************** //** calculation of the transmitter power output, SWR value and the impedance vector ** void tx_pwr() { // ********** transmitter power output measurement ********** float tx_power_measure = analogRead(2); // analog 2 to measure tx power output voltage 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,1); lcd.setCursor(11,0); lcd.print("Watts"); // *** calculation of the antenna impedance match as the SWR value ********* swr_forward = 0; // reset value to zero swr_reflected = 0; // reset value to zero swr_forward = analogRead(0); // swr forward voltage from impedance bridge swr_reflected = analogRead(1); // swr reflected voltage from impedance bridge v_forward = 0.0048 * swr_forward; // forward swr voltage measured value v_reflected = 0.0048 * swr_reflected; // reverse swr voltage measured value float ratio = v_forward / v_reflected; // float ratio = v_reflected / v_forward; float swr_value = ratio; lcd.home(); lcd.setCursor(0,1); lcd.print("Swr= 1:"); lcd.setCursor(7,1); lcd.print(swr_value,4); lcd.print(" "); // **** calculation of the antenna as an impedance vector angle ***** RL = swr_value * 50; // calculation of antenna resistance, assume match to a 50ohm co-axial cable reference float target = 50; float angle = ((double)atan2(RL,target))*(180/PI); // arc tangent of y/x lcd.home(); lcd.setCursor(0,2); lcd.print(" "); lcd.setCursor(0,2); lcd.print("Vec= 50"); lcd.write(byte(0)); lcd.print(" "); lcd.setCursor(9,2); lcd.write(byte(1)); lcd.print(" "); lcd.print(angle,1); lcd.write(byte(2)); } //***calculate the active load of the antenna as a transmission line measurement *** // calculation of transmission line impedance equivelant value based of 50ohm cable reference // characteristic impedance = SQR( inductance / capacitance ) // where cable inductance = 300nH/m and the cable capacitance = 120pF/m void active_load() { float 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 ****************************