#include <Wire.h>
#include <LiquidCrystal.h>
#include <math.h>
//LiquidCrystal lcd(RS, RW, E, D0, D1, D2, D3, D4, D5, D6, D7); /* For 8-bit mode */
// VSS = GBD; VDD=+5V; V0=10K_POT (+5V/GND); A = 220Ohm-(+5V); K = GND
LiquidCrystal lcd(12, A2, 11, 6, 5, 13, A3, 10, 9, 8, 7); /* For 8-bit mode */
const int analogPinF = A0;
const int analogPinR = A1;
float Vreference = 5.00;
float slopeF = 26.178; // Slope of the AD8307 log output (Default = 40)
float interceptF = 44.278; // 0V intercept point (Default = 44)
float slopeR = 28.702; // Slope of the AD8307 log output (Default = 40)
float interceptR = 60.052; // 0V intercept point (Default = 44)
float adcValueF = 0;
float voltageF = 0;
double powerdBmF = 0;
double powerdBmR = 0;
float adcValueR = 0;
float voltageR = 0;
double vswr = 1.0;
double refl_coeff = 0;
byte Timing = 1;
byte ReflectedLCD = 1;
#define IN_Timing 2
#define Buzzer 3 // output for Buzzer control (1 = ON)
#define IN_ReflectedLCD 4
unsigned long pow_fwd = 0; // power forward (watts)
unsigned long pow_ref = 0; // power forward (watts)
// Peak Hold Variables
double peakPowerFwd = 0;
double peakPowerRef = 0;
unsigned long peakHoldTimer = 0;
int peakHoldTime = 0; // Hold peak power
int peakHoldTime_Fast = 500; // Hold peak power for 0.5 seconds
int peakHoldTime_Slow = 2000; // Hold peak power for 2 seconds
void UpdateTXScreen();
void UpdateTXScreenRef();
// Progress Bar Characters
byte block[8][8]=
{
{ 0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10 }, // define character for fill the bar
{ 0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18 },
{ 0x1C,0x1C,0x1C,0x1C,0x1C,0x1C,0x1C,0x1C },
{ 0x1E,0x1E,0x1E,0x1E,0x1E,0x1E,0x1E,0x1E },
{ 0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08 }, // define character for peak level
{ 0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04 },
{ 0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02 },
{ 0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01 },
};
// Progress Bar Variables
unsigned long lastUpdateLCD = 0;
const unsigned long updateIntervalLCD = 1; // LCD update interval
/////////////////// LDMOS parameters
byte fill[6]={ 0x20,0x00,0x01,0x02,0x03,0xFF }; // character used to fill (0=empty 5=full)
byte peak[7]={ 0x20,0x00,0x04,0x05,0x06,0x07,0x20 }; // character used to peak indicator
int lmax[2]; // level max memory
int dly[2]; // delay & speed for peak return
int smooth_lev[2] = {0, 0}; // One for each row
long lastTpep = 0; // update PEP display
int anF = 0; // analog read forward power
int anR = 0; // analog read reflected power
#define T_REFRESH1 0.1 // msec bargraph refresh rate
#define T_PEAKHOLD 1000 // msec peak hold time before return
#define Fall_time 10
/////////////////// End of LDMOS parameters
/// Time measure
//long duration = 0;
//long start = 0;
/// End of Time measure
void setup() {
//Serial.begin(9600);
lcd.begin(16, 2);
analogReference(DEFAULT);
pinMode(IN_Timing, INPUT_PULLUP);
pinMode(IN_ReflectedLCD, INPUT_PULLUP);
pinMode(Buzzer, OUTPUT);
digitalWrite(Buzzer, 0);
// Create custom characters
for (int i = 0; i < 8; i++) {
lcd.createChar( i,block[i] );
}
}
void loop() {
//start = micros();
adcValueF = analogRead(analogPinF);
voltageF = (adcValueF / 1023.0) * Vreference;
powerdBmF = (slopeF*voltageF)-interceptF;
pow_fwd = pow(10, (powerdBmF - 30) / 10);
adcValueR = analogRead(analogPinR);
voltageR = (adcValueR / 1023.0) * Vreference;
powerdBmR = (slopeR*voltageR)-interceptR;
pow_ref = pow(10, (powerdBmR - 30) / 10);
if (pow_fwd == 0 && pow_ref == 0 ) {
vswr = 1.00;
}
if (pow_fwd > 0 && pow_fwd > pow_ref ) {
refl_coeff = abs(sqrt((double)pow_ref / pow_fwd));
vswr = (1 + refl_coeff) / (1 - refl_coeff);
}
/*
if (pow_fwd <= pow_ref && pow_fwd > 0) {
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("E R R O R !");
lcd.setCursor(0, 1);
lcd.print("SWR = infinity");
tone(Buzzer, 700);
delay (200);
noTone(Buzzer);
delay (200);
return;
}
*/
/*
if (pow_fwd > 4000) {
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("R E D U C E");
lcd.setCursor(0, 1);
lcd.print("P O W E R !");
tone(Buzzer, 700);
delay (200);
noTone(Buzzer);
delay (200);
tone(Buzzer, 700);
delay (200);
noTone(Buzzer);
delay (200);
return;
}
*/
Timing = digitalRead(IN_Timing);
if (Timing == LOW){
peakHoldTime = peakHoldTime_Slow;
}
else {
peakHoldTime = peakHoldTime_Fast;
}
/*
if (vswr >= 1.5){
tone(Buzzer, 700);
delay (200);
noTone(Buzzer);
delay (200);
tone(Buzzer, 700);
delay (200);
noTone(Buzzer);
delay (200);
}
*/
ReflectedLCD = digitalRead(IN_ReflectedLCD);
if(ReflectedLCD == HIGH){
UpdateTXScreen();
}
else{
UpdateTXScreenREF();
}
/////////////
anF = map(pow_fwd, 0, 100, 0, 80); // 80 = 16 x 5 colums, full scale 100w
anR = map(pow_ref, 0, 100, 0, 80); // 80 = 16 x 5 colums, full scale 100w
/////////////
//duration = micros() - start;
//Serial.println(duration);
//delay(1000);
}
void UpdateTXScreen() {
if (millis() - lastUpdateLCD > updateIntervalLCD) {
// Peak Hold Logic
if (pow_fwd > peakPowerFwd) {
peakPowerFwd = pow_fwd;
peakHoldTimer = millis();
}
if (millis() - peakHoldTimer > peakHoldTime) {
peakPowerFwd = pow_fwd; // Update after hold time
}
lcd.setCursor(0, 0);
lcd.print("Po:");
lcd.print((int)peakPowerFwd);
lcd.print("W "); // Extra spaces to clear old characters
lcd.setCursor(9, 0);
lcd.print("SW:");
lcd.print(vswr, 2);
lcd.print(" "); // Extra spaces to clear old characters
bar(0, anF);
lastUpdateLCD = millis();
}
}
///////////////// Reflected
void UpdateTXScreenREF() {
if (millis() - lastUpdateLCD > updateIntervalLCD) {
// Peak Hold Logic
if (pow_ref > peakPowerRef) {
peakPowerRef = pow_ref;
peakHoldTimer = millis();
}
if (millis() - peakHoldTimer > peakHoldTime) {
peakPowerRef = pow_ref; // Update after hold time
}
lcd.setCursor(0, 0);
lcd.print("Pr:");
lcd.print((int)peakPowerRef);
lcd.print("W "); // Extra spaces to clear old characters
lcd.setCursor(9, 0);
lcd.print("SW:");
lcd.print(vswr, 2);
lcd.print(" "); // Extra spaces to clear old characters
bar(0, anR);
lastUpdateLCD = millis();
}
}
void bar(int row, int lev) {
// === Fast rise / slow decay logic ===
if (lev > smooth_lev[row]) {
smooth_lev[row] = lev; // Fast rise
} else {
smooth_lev[row] = smooth_lev[row] + (lev - smooth_lev[row]) / Fall_time; // Slow fall =10 Fast fall = 1
}
lcd.setCursor(0, 1);
lcd.write(' '); // Filler space (optional)
for (int i = 1; i < 16; i++)
{
int f = constrain(smooth_lev[row] - i * 5, 0, 5); // Use smoothed level
int p = constrain(lmax[row] - i * 5, 0, 6); // Peak logic stays unchanged
if (f)
lcd.write(fill[f]);
else
lcd.write(peak[p]);
}
// === Peak hold logic (unchanged) ===
if (lev > lmax[row])
{
lmax[row] = lev;
dly[row] = -(T_PEAKHOLD) / T_REFRESH1;
}
else
{
if (dly[row] > 0)
lmax[row] -= dly[row];
if (lmax[row] < 0)
lmax[row] = 0;
else
dly[row]++;
}
}
FWD
REF
Slow
Fast
FWD
REF