// THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED WARRANTY TO USE IN YOUR AMATEUR RADIO EXPERIMENTS.
// ALL LICINCED AMATEUR RADIO OPERATORS ARE GIVEN PERMISSION TO USE, COPY AND MODIFY THIS SOFTWARE.
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//******* CHECK YOUR DISPLAY & LIBRARIES ***************
// Arduino 1.6.3 IDE (not tested on earlier IDE)
// Made from sketch by kn9b
// set op to 16x4, but can be used 20x4
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
#include <Wire.h> // #include <Wire.h> default to Wiring for Uno; SCL = A5, SDA = A4, VCC = 5V+, GND = GND
#include "LiquidCrystal_I2C.h"
// Pinouts for NANO I/O // Analog VDC signals from Stockton VSWR Bridge Circiut
#define Vfwdpin_Anlg 6 // Forward Voltage Vfwd VDC A6
#define Vrevpin_Anlg 7 // Reverse Voltage Vrev VDC A774
#define PIN_RS 6
#define PIN_EN 7
#define PIN_DB4 11 // 8
#define PIN_DB5 10 //9
#define PIN_DB6 9 //10
#define PIN_DB7 8 // 11
//LiquidCrystal lcd(PIN_RS, PIN_EN, PIN_DB4, PIN_DB5, PIN_DB6, PIN_DB7);
LiquidCrystal_I2C lcd(0x27,20,4);
const int colums = 16; /// have to be 16 or 20
const int rows = 4; /// have to be 4
int lcdindex = 0;
int line1[colums];
int line2[colums];
///////////////////////////////////////////////////////
// Varibles
float Vfwd;
float Vrev;
float last_Vfwd;
float last_Vrev;
float Afwd;
float Arev;
float Pfwd;
float MaxFwd;
float AvrFwd;
float Prev;
float MaxRev;
float AvrRev;
float SWR;
float MaxSwr;
float AvrSwr;
int RFoff;
void setup()
{
lcd.begin (16,4);
lcd.backlight();
lcd.clear(); // clear all
lcd.setCursor (0, 0); // go to Column, Row
lcd.print("OZ6YK PWR/SWR MT"); // displays text
lcd.setCursor (0, 1); // go to Column, Row
lcd.print("10W Max Operate "); // displays text can be changed depending of use
lcd.setCursor (0, 2); // go to Column, Row
// lcd.print("-----Ready-----"); // displays text
lcd.print("TX to right side"); // displays text
lcd.setCursor (0, 3); // go to Column, Row
lcd.print("ANT to left side"); // displays text
delay(1000); // delay 4 second
}
void loop()
{ // start of main loop // start of main loop // start of main loop // start of main loop // start of main loop
// reads inputs before actions can be taken
Vfwd = analogRead(Vfwdpin_Anlg); // read forward voltage from RF remote directional detector
Vfwd = constrain(Vfwd, 1, 1023); // Vfwd values must be greater than zero to prevent divide by zero in SWR Calc
Vrev = analogRead(Vrevpin_Anlg); // read forward voltage from RF remote directional detector
/////////////////////////////////////////////////////////////////////////////////////////////
// RF Forward / Reverse Power and VSWR Calculations
/////////////////////////////////////////////////////////////////////////////////////////////
/*
Step 1 = Convert Arduino A/D steps to current
Arduino Voltage = Steps X 5 Volts / 1023
Add Arduino V corrections for diode drop of 0.3 V
Arduino Voltage = Arduino Voltage + 0.30
Arduino V corrections for Vpeak to Vrms is factor of 0.707
Tx Line V = Arduino V X 0.707 X 13 turns ratio
Amps = Tx Line V / 50 Ohm Termination Resistor
Amps = [ Steps X 5 ) / 1023 ) + 0.30 ] X [ 13 X 0.707 / 50 ] = ( ( (Steps X 5) / 1023 ) + 0.30 ) * 0.18382
Step 2 = Convert Line current to power
Power = 50 Ohm Line X current squared
Power = 50 X Amps X Amps
Step 3 = Convert forward and reverse power to VSWR
VSWR = (1+SQRT(Prev/Pfwd)) / (1-SQRT(Prev/Pfwd))
*/
/////////////////////////////////////////////////////////////////////////////////////////////
float Vdiode = ( Vfwd / 1000 ); // gradual diode drop 1000
// Gradual diode drop factor was tested for 40M, 30M, 20M, 17M, 21M
// Fowards Watts 0 to 25 W valid +/- 0.5 W // 12M and 10M valid + 0 to - 1.5 W
Vdiode = constrain(Vdiode, 0, 0.3); // limit drop to 0.3 V
Afwd = ( (Vfwd * 5) / 750 ) + Vdiode; // split up calculation // 1023
Afwd = Afwd * 0.18382; // split up calculation
Pfwd = 50 * Afwd * Afwd;
Vdiode = ( Vrev / 1000 ); // gradual diode drop
Vdiode = constrain(Vdiode, 0, 0.3); // limit drop to 0.3 V
Arev = ( (Vrev * 5) / 750 ) + Vdiode; // split up calculation // 1023
Arev = Arev * 0.18382; // split up calculation
Prev = 50 * Arev * Arev;
float fp = sqrt ( Prev / Pfwd );
SWR = ( 1 + fp ) / ( 1 - fp );
SWR = constrain(SWR, 1, 99.9); // some more than 100
if ( Pfwd > 0.2 ) // peak sample timer and no RF time out timer
{
if ( RFoff > 10000 ) // average and peak timer see text (10000 long for SSB, 2000 short for QSK)
{
// lcd.init(); // this extra init clears and cleans up trash when on battery operation
lcd.clear(); // clear all
MaxFwd = 0; // clears past peaks and averages
AvrFwd = 0;
MaxRev = 0;
AvrRev = 0;
MaxSwr = 1;
AvrSwr = 1;
}
RFoff = 1000;
}
else
{
RFoff = RFoff + 1; // Countdown timer
}
if ((( Vfwd - last_Vfwd ) > 3) || (( Vfwd - last_Vfwd ) < -3) || (( Vrev - last_Vrev ) > 3) || (( Vrev - last_Vrev ) < -3) ) // previous reads are checked to reduce display flicker // +/- 3 to filter A/D noise
{
//////////// Peak Hold ///////////
if ( Pfwd > MaxFwd )
{
MaxFwd = Pfwd;
}
if ( Prev > MaxRev )
{
MaxRev = Prev;
}
if ( SWR > MaxSwr )
{
MaxSwr = SWR;
}
////////////////////////////////// average value integrator Select % values to add up to 100% // 10 / 90 is fast, 5 / 95 is medium, 2 / 98 is slow
AvrFwd = ( AvrFwd * 0.95 ) + ( Pfwd * 0.05 ); // average value integrator
AvrRev = ( AvrRev * 0.95 ) + ( Prev * 0.05 ); // average value integrator
AvrSwr = ( AvrSwr * 0.95 ) + ( SWR * 0.05 ); // average value integrator
////////////////////////////////
lcd.setCursor (0, 0); // go to Column, Row
lcd.print("= Transmitting =");
lcd.setCursor (0,1);
lcd.print("FWD ");
lcd.setCursor (4,1); // go to Column, Row
lcd.print(Pfwd, 1); // displays forward power as xx.x value // ",1" means one decimal place
lcd.print(" "); // to clear trailing digits
// FWD bargraph
lcd.setCursor (9,1); // go to Column, Row
lcd.print(" "); // to clear last bar
lcd.setCursor (9,1); // go to Column, Row
float bar = 12 - ( Pfwd / 2 );
bar = constrain(bar, 0, 10); // limit max bar
for (bar; bar < 11; bar = bar + 1)
{ lcd.print(">"); } // bargraph
// end bargraph
lcd.setCursor (0,2); // go to Column, Row
lcd.print("REV "); // displays menu selected // Clearing not required always 16 Char
lcd.setCursor (4,2); // go to Column, Row
lcd.print(Prev, 1); // displays forward power as xx.x value // ",1" means one decimal place
lcd.print(" "); // to clear trailing digits
// REV bargraph
lcd.setCursor (9,2); // go to Column, Row
lcd.print(" "); // to clear last bar
lcd.setCursor (9,2); // go to Column, Row
bar = 12 - Prev;
bar = constrain(bar, 0, 10); // limit max bar
for (bar; bar < 11; bar = bar + 1)
{ lcd.print("<"); } // bargraph
// end bargraph
lcd.setCursor (0,3); // go to Column, Row
lcd.print("SWR "); // displays menu selected // Clearing not required always 16 Char
lcd.setCursor (4,3); // go to Column, Row
lcd.print(SWR, 1); // displays forward power as xx.x value // ",1" means one decimal place
lcd.print(" "); // to clear trailing digits
// SWR bargraph
lcd.setCursor (9,3); // go to Column, Row
lcd.print(" "); // to clear last bar
lcd.setCursor (9,3); // go to Column, Row
bar = 12 - SWR;
bar = constrain(bar, 0, 10); // limit max bar
for (bar; bar < 11; bar = bar + 1)
{ lcd.print("#"); } // bargraph
// end bargraph
last_Vfwd = Vfwd;
last_Vrev = Vrev;
}
/////////////////////////////////////////////////////////////////////////////////////////////
if ( RFoff > 10000 ) // no RF time out
{
delay (200); // delay
lcd.setCursor (0, 0); // go to Column, Row
lcd.print("No RF, Average/Peak ");
lcd.setCursor (0, 1); // go to Column, Row
lcd.print("FWD ");
lcd.setCursor (5, 1); // go to Column, Row
lcd.print(AvrFwd, 1); // displays forward power as xx.x value // ",1" means one decimal place
lcd.print(" "); // one space to clear last if > 10 (x.x vs xx.x)
lcd.setCursor (10, 1); // go to Column, Row
lcd.print(" / ");
lcd.setCursor (14, 1); // go to Column, Row
lcd.print(MaxFwd, 1); // displays forward power as xx.x value // ",1" means one decimal place
lcd.print(" "); // one space to clear last if > 10 (x.x vs xx.x)
lcd.setCursor (0, 2); // go to Column, Row
lcd.print("REV ");
lcd.setCursor (5, 2); // go to Column, Row
lcd.print(AvrRev, 1); // displays forward power as xx.x value // ",1" means one decimal place
lcd.print(" "); // one space to clear last if > 10 (x.x vs xx.x)
lcd.setCursor (10, 2); // go to Column, Row
lcd.print(" / ");
lcd.setCursor (14, 2); // go to Column, Row
lcd.print(MaxRev, 1); // displays forward power as xx.x value // ",1" means one decimal place
lcd.print(" "); // one space to clear last if > 10 (x.x vs xx.x)
lcd.setCursor (0, 3); // go to Column, Row
lcd.print("SWR ");
lcd.setCursor (5, 3); // go to Column, Row
lcd.print(AvrSwr, 1); // displays forward power as xx.x value // ",1" means one decimal place
lcd.print(" "); // one space to clear last if > 10 (x.x vs xx.x)
lcd.setCursor (10, 3); // go to Column, Row
lcd.print(" / ");
lcd.setCursor (14, 3); // go to Column, Row
lcd.print(MaxSwr, 1); // displays forward power as xx.x value // ",1" means one decimal place
lcd.print(" "); // one space to clear last if > 10 (x.x vs xx.x)
RFoff = 12000; // prevents overflow at 32000 and flags average, peak and display clean up on next transmit
}
} // end of main loop // end of main loop // end of main loop // end of main loop // end of main loop