As part of my planned QRP PA, giving 3.2W output on 40, 30 & 20m, I am including an SWR meter. These look simple but are far from it.
The circuit I am trying to build is based on an Arduino Nano to do the calculations and drive a OLED display, and a couple of AD8307 log detectors to measure the Forward and Reflected power outputted from a conventional circuit using tow 1:10 transformers to measure the load line current and voltage.
When a wave travels from TRX to ANT a forward voltage FWD is output, when a reflected wave travels from ANT to TRX a reflected voltage REF is output. That's the theory anyway. (see this plagiarism article) The actual circuit looks like this
So far so good.
PROGRESS SO FAR
What I have done so far is to buikd the AD8307s and Nano circuit,
and write some software to display a couple of bars for FWD power, SWR, display the values and say which band I am operating on. This involves detecting (over an average of ten measurements) the AD8307 outputs in millivoltss, converting this to dBm according to the ICs slope of 25mV/dB, converting this to dBm and then milliwatts across the 50R
resistors.
I have found that individual calibration is needed to get the same sensitivity from each AD8307, see code below. The slopes seem to be equal, but the intercepts different. Anyway I am now getting roughly the correct SWR for a 20dB Return Loss.
And at the moment I am stuck as my SWR transformers do not seem to giving the right outputs. I am driving the TXR end from my AD9851 VFO buffer outputs with 10mW and using a load of 50R at the output, built-into my RF Meter box. And the results are WRONG - Negative SWR! Reflected power bigger than Forward power... Why?
Code
// PA_LPF_TRX_OLED
// V0.95 16-5-17 need h/w for testing/calibTFMRLOSSn
// to add TRX
#include "Oled_128X64_I2C.h"
// analog reference (mV), A/D count, read avg
// slope and TX/display trigger (mW)
#define AREF 3300
#define ADCOUNT 1023
#define READAVG 10
#define TXTRIG 2
// analog inputs, band button, band relays, TXRX relay (PTT)
#define FWDPIN A0
#define REFPIN A1
#define SW 4
#define BAND1 7
#define BAND2 6
#define PTT 5
// display variables
double mwFwd, mwRef, swr;
// display text for bands
char bandTxt[][4] = {
"40m", "30m", "20m"
};
byte band;
bool txFlag;
void setup() {
Serial.begin(9600);
pinMode(SW, INPUT_PULLUP);
pinMode(BAND1, OUTPUT);
pinMode(BAND2, OUTPUT);
pinMode(PTT, OUTPUT);
// analog ref AREF
analogReference(EXTERNAL);
oled.begin();
// start on 40m
band = 0;
// TX off
txFlag = false;
}
void loop() {
int aFwd, aRef, n;
double mV, dBm;
// read SWR bridge inputs and average
aFwd = 0;
aRef = 0;
for (n = 0; n < READAVG; n++) {
aFwd += analogRead(FWDPIN); // typ +20dB level, gives 0dB at AD8307, or 2.5V (775 d/a)
delay(50);
aRef += analogRead(REFPIN); // typ -10dB level, gives -30dB at AD8307, or 1.5V (465 d/a)
}
aFwd /= READAVG;
aRef /= READAVG;
// 1. Adj slope for 20dB drop (470/50R), plot
// 2. Adj intercept for correct mW
// aFwd to mW, slope & intercept
mwFwd = convert(aFwd, 25.0, -86);
mwRef = convert(aRef, 25.0, -88);
Serial.print("F: ");
Serial.print(aFwd);
Serial.print("\t");
Serial.print(mwFwd, 3);
Serial.print("\t R: ");
Serial.print(aRef);
Serial.print("\t");
Serial.println(mwRef, 3);
// calc SWR
swr = ( 1 + sqrt(mwRef / mwFwd) ) / (1 - sqrt(mwRef / mwFwd) ); // calc SWR
// band change
if (digitalRead(SW) == LOW) {
while (!digitalRead(SW));
if (band < 2) band++;
else band = 0;
bandSw();
}
// switch to TX at 100mW
if (mwFwd > TXTRIG) {
digitalWrite(PTT, HIGH); // TX = HIGH
txFlag = true;
}
else {
digitalWrite(PTT, LOW);
txFlag = false;
}
dispUpdate();
delay(50); // loop stability
}
// convert A/D count, to mW
double convert(int aIn, double sl, double cal) {
double mV, dBm;
mV = (double)(map(aIn, 0, ADCOUNT, 0, AREF));
dBm = (mV / sl) + cal;
return pow(10.0, (dBm / 10.0));
}
// band relays, wiring HIGH = relay ON
void bandSw() {
switch (band) {
case 0:
digitalWrite(BAND1, HIGH); // 40m
digitalWrite(BAND2, HIGH);
break;
case 1:
digitalWrite(BAND1, HIGH); // 30m
digitalWrite(BAND2, LOW);
break;
case 2:
digitalWrite(BAND1, LOW); // 20m
digitalWrite(BAND2, LOW);
break;
}
}
//=====PICTURE LOOP
void dispUpdate() {
oled.firstPage();
do {
dispMsg(20, 0, "QRP POWER AMP"); // title
dispMsgS(0, 15, "FWD");
dispMsgS(0, 25, "SWR");
dispMsg(50, 35, "FWD");
dispMsg(50, 50, "SWR");
dispMsgL(10, 40, bandTxt[band]); // band "40m" "30m" "20m" large font
// values display active only on TX
if (txFlag == false) {
dispBar(20, 15, 5, 0); // blank bars
dispBar(20, 25, 5, 0);
}
else {
dispBar(20, 15, 5, mwFwd / 50 ); // 0-5000mW = 0-100bar
dispBar(20, 25, 5, (swr - 1) * 25); // 1-5 = 0-100bar
if (mwFwd > 1000) {
dispNum(80, 35, mwFwd / 1000, 1);
dispMsg(110, 35, "W");
}
else {
dispNum(80, 35, mwFwd, 0);
dispMsg(110, 35, "mW");
}
dispNum(80, 50, swr, 2);
}
} while (oled.nextPage());
}