Friday 1 June 2018

BPF for Direct Conversion RX

I have breadboarded a AD8307 module (from SV1AFN) with an Arduino Nano to make an RF meter. The AD8307 has a 50R input impedance. I have added on the front a 40dB attenuator tap of 4x680R and 50R. Thus the divide ratio is 4x680/25. I have written the software to allow this to display the actual RF voltage at the input. Code below.

Then I have built a prototype BPF, transformer + 100p --> 8p coupling --> transformer + 100p, output tapped on primary (both type 5u3L from SPECTRUM COMMUNICATIONS). I roughly tuned this to 40m. I applied an input from my SI5351 VFO from 6000 to 8500kHz. This is what I got:

IMG 0101

Screen Shot 2018 06 01 at 16 25 10

With a bit of tuning I can probably get the top a bit flatter, but I am pleased with the result.

Code

// RF_METER

#include "Oled.h"                                 // include

#define AREF 3250                                 // actual value of 3V3 ref (mV)
#define AMAX 1023
#define SLOPE 25.0                                // 25mV/dB
#define INTERCEPT 87.0                            // -85 + 40dB
#define ATTN 40.0                                 // attenuation
#define IMP 50                                    // load ohms

float Vrms, dBm, mW;                         // global variable to display

void setup() {
  oled.begin();                                   // begin OLED
  analogReference(EXTERNAL);                      // set ADC to use external ref, Nano 3V3
}

void loop() {
  int ADCin;
  double mV;

  ADCin = analogRead(A3);                         // 0-1023
  delay(50);
  mV = (double)(map(ADCin, 0, AMAX, 0, AREF));    // AREF in mV, calculate & convert to double

  dBm = (mV / SLOPE) - INTERCEPT + ATTN;          // in doubles
  mW = pow(10.0, (dBm / 10.0));                   // in double, out double, 0dBm = 1mW
  Vrms = sqrt((mW / 1000.0) * IMP);               // in double, out double
  
  dispUpdate();                                   // display
}

void dispUpdate() {                               // display loop
  oled.firstPage();
  do {
    if( Vrms < 1.0 ) {
      dispNumL(35, 5, (Vrms * 1000.0), 0);       // display mV
      dispMsgL(90, 5, "mV");
    }
    else {
      dispNumL(35, 5, Vrms, 1);                  // display
      dispMsgL(90, 5, "V");
    }
    
    dispNumL(35, 25, dBm, 0);                    // display dBm
    dispMsgL(90, 25, "dBm");

    if ( mW > 1000.0 ) {
      dispNumL(35, 45, (mW / 1000), 1);          // display W
      dispMsgL(90, 45, "W");
    }
    else {
      dispNumL(35, 45, mW, 1);                   // display mW
      dispMsgL(90, 45, "mW");
    }
  } while(oled.nextPage());
}

No comments: