Saturday, September 15, 2018

New AD8307 power meter

Having done previously two power meter's based on the AD8307, with analog display and with computer interface, decided to build one other unit more self contained and with a ref calibrator included.

Here's the outcome:

The circuit is a simple one:

Taken from here.The AD8307 output is connected to an Arduino analog input and computation is done in software, with output to the LCD and usb line.

Build process here:

 The slug repellent tape is excellent for RF blindage, only need's to have something bellow to give some more rigidity.
It brings the AD8307 noise level to -76dBm.

Board assembly:

The calibrator was based on the one here.

It's not spot on according to the Marconi and R&S but does an approximate job in case the input needs to be validated.

Bellow validating the 0 dBm output of the Marconi power meter:

1.5db down the reference is not bad (possible accounting 0.5 for the cable and plugs thenselfs).

20 dB attenuation of the 0 dBm signal:

..still of by at least 2.1 db down. The attenuator used was measured at 19.7db.

If I need more precision will use the other meter's I have:

For quick check in circuits with risk of blowing something it will be better to use the homemade one, the price different between an AD8307 and the other sensors is in the 20 fold at least.

The other power meter meter's I built before was this one:

from the post here.
The digital voltmeter, on top of the unit, does not display dBm instead the output of the opamp after the AD8307. So the compute dBm needs a table.

And the one inside this VNA

From this post.

The Arduino code used on the new AD8307 power meter is this one:

// AD8307 with LCD and serial output
// main code example from here:
// some changes made by CT2GQV - 2018
// version 20180915

// initialize the library with the numbers of the interface pins
#define I2C_ADDR    0x3F
#define BACKLIGHT_PIN     3
#define En_pin  2
#define Rw_pin  1
#define Rs_pin  0
#define D4_pin  4
#define D5_pin  5
#define D6_pin  6
#define D7_pin  7
LiquidCrystal_I2C       lcd(I2C_ADDR,En_pin,Rw_pin,Rs_pin,D4_pin,D5_pin,D6_pin,D7_pin);

//pwr sensor stuff
const int sensorpin = A0;

// serial print the voltage at the Arduino A0 / from,44216.0.html#13
void printDouble( double val, byte precision){
 // prints val with number of decimal places determine by precision
 // precision is a number from 0 to 6 indicating the desired decimial places
 // example: printDouble( 3.1415, 2); // prints 3.14 (two decimal places)

 Serial.print (int(val));  //prints the int part
 if( precision > 0) {
   Serial.print("."); // print the decimal point
   unsigned long frac;
   unsigned long mult = 1;
   byte padding = precision -1;
      mult *=10;
   if(val >= 0)
     frac = (val - int(val)) * mult;
     frac = (int(val)- val ) * mult;
   unsigned long frac1 = frac;
   while( frac1 /= 10 )
   while(  padding--)
   Serial.print(frac,DEC) ;

void setup() {
 Serial.begin(57600); // should be enough
// set up the number of columns and rows on the LCD
lcd.begin(16, 2);
lcd.setBacklightPin(BACKLIGHT_PIN,POSITIVE); // init the backlight
lcd.setBacklight(1);        // Backlight on

void loop() {
 // power in
 int sensorval = analogRead(sensorpin);

 // might need to read or match agains analog ref.
 //float voltage = (sensorval/1024.0) * 5.0;
 float voltage = (sensorval/1023.0) * 5.0;
 float pwr = ((voltage-0.269) * 40)-77;
 float volts = ((voltage-0.269) * 40);
 float pwrW = pow(10,((pwr-30)/10));
 float vts = sqrt(pwrW * 50);
 float ptp = vts * 2.828;
 lcd.print("Pwr ");
 lcd.print(pwr, 1);
 lcd.print("dBm   ");

// Serial.print(sensorval); Serial.print(" DAC   ");
printDouble(voltage,3); Serial.print(" Vdc   ");
Serial.print(pwr); Serial.println(" dBm");

if (vts > 0.9)
  lcd.print("rms  ");
  lcd.print(vts, 2); lcd.print("V  ");
  float ptp = vts * 2.828;
  //lcd.print(" p2p ");
  //lcd.print(ptp, 2);
 if (vts < 1 and vts > 0.001)
 vts = vts * 1000;
 lcd.print("rms  ");
 lcd.print (vts, 2);  lcd.print("mV  ");
 float ptp = vts * 2.828;
 //lcd.print(" p2p ");
 //lcd.print(ptp, 2);
 if (vts < .001)
 vts = vts * 1000000;
 lcd.print("rms  ");
 lcd.print(vts, 2); lcd.print("uV  ");
 float ptp = vts * 2.828;
 //lcd.print(" p2p ");
 //lcd.print(ptp, 2);


That's it, have a great day!


DK3LJ said...

Bom dia Ricardo,

the AD8307 is very precise when calibrated at one frequency but varies quite significantly across frequencies. So, 0dbm at 1 MHz gives a very different voltage than 0dbm at 100 MHz. One way to compensate that is by adding a network to the input that attenuates low frequencies.

Ricardo - CT2GQV said...

Hello Jan,

Thank you for the comment.
The compensation network can be done but on this one I'm going to use the lazy method approach, will create a table at reference frequencies and take note of the values, measured and real, then will use it to compensate. I also have the other two "calibrated" power meters if I need a precise value.