Monday, 15 May 2017

BASIC Tech Group - MyNews - 44 The SWR meter

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.

Screen Shot 2017 05 15 at 12 46 10

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

Screen Shot 2017 05 14 at 14 42 57

So far so good.

PROGRESS SO FAR

What I have done so far is to buikd the AD8307s and Nano circuit,

IMG 1086

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

IMG 1085resistors.

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: