/* This program written by Alastair GW0AJU. This project is version 3 of the "49er active bridge" for a DIY Ham Radio Tx/Rx project. date 27th Feb 2017 Ardunio board used = Ardiuno Uno */ #include // (no semicolon) //********** liquid display setup ********* #include #include #include #include Adafruit_ADS1115 ads; /* Use this for the 16-bit version */ #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" //**************** SWR bridge and antenna load calculations **************** float rx_dbm =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; float tx_power_measure = 0; float S_meter = 0; double over_load = 0; double signal_meter = 0; double rx_signal_value = 0; float RST_measure = 0; float load_scale = 0; int16_t adc0; //*********** 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; //********** start of arduino DDS VFO control program ********* void setup() { // ********* 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(" QRP Radio"); lcd.setCursor(0,1); lcd.print(" active bridge v4"); 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 ads.setGain(GAIN_ONE); // 1x gain +/- 4.096V 1 bit = 2mV 0.125mV ads.begin(); } //************* void loop *********************** void loop() { radio_monitor(); delay(300); // measurement sampling rate } //*************** start of program code sub-routines **************** //************ transmit / receive control subroutine ******** void radio_monitor() { rx_pwr(); // only while the receiver is enabled, the Rx signal strength would be displayed tx_pwr(); // only while the transmitter is enabled, the Tx power output would be displayed active_load(); // only while the Tx is enabled, the antenna loading would be displayed } //**************** processes for receive mode *************** void rx_pwr() { adc0 = ads.readADC_SingleEnded(0); // analog port "0" on the adafruit ads1115 16bit adc rx_signal_value = adc0; if ( rx_signal_value <= 1000) // 16bit ADC setting { rx_signal_value = 1010; // (16bit ADC) if AGC voltage is below 100mV, then default value is put into place to give "Rx = 0.0" S meter reading } signal_meter = (rx_signal_value - 1000); // (16 bit ADC) the minus 1000 is to give an AGC noise floor barrier voltage of 100mV to the agc circuit // the value of 500 indicates an "S 9" signal for a 16bit ADC, RST from "Rx:0.1" up to "Rx:9.0 +42.33dB" // the value of 500 indicates an "S 9" signal for a 10bit ADC, RST from "Rx:1.0" up to "Rx:9.0 +6dB" over_load = 20*(double)log10(signal_meter); // for 10bit ADC for "S" meter S_meter = (over_load/0.6); lcd.home(); lcd.setCursor(0,0); lcd.print("Rx = "); lcd.setCursor(5,0); lcd.print(" "); if (over_load <= 54 ) { lcd.home(); RST_measure = (S_meter/10); lcd.setCursor(5,0); lcd.print(RST_measure,1); } else if (over_load > 54 ) { lcd.home(); lcd.setCursor(0,0); lcd.print("Rx = 9.0 +"); load_scale = over_load - 54; lcd.setCursor(11,0); lcd.print(" "); lcd.setCursor(11,0); lcd.print(load_scale,2); lcd.setCursor(16,0); lcd.print("dB"); } } // **************************************************************************************** //********** processes for transmit mode *************** void tx_pwr() { tx_power_measure = analogRead(2); // analog 2 to measure tx power output if ( tx_power_measure == 0 ) { tx_power_measure = 1; } tx_signal_level = 0.0048 * tx_power_measure; 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); if ( swr_forward == 0 ) { swr_forward = 1; } swr_reflected = analogRead(1); if ( swr_reflected == 0 ) { swr_reflected = 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 ****************************