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()); }
No comments:
Post a Comment