Calculating dBm and W

I'm building a RF power meter with an AD8307 log amp. http://www.analog.com/static/imported-files/data_sheets/AD8307.pdf
See page 21.
The code is based on the "readanalogvoltage" example in arduino.
I manage to get the calculation form V to dBm to work according to the the formula on the design example.
My next battle is to convert the dBm to W.
By using the formula P=P0 * 10^(dB/10) I get the calculations correct on my Casio.
But I'm a very fresh on C and arduino.
Can anybody give me some pointers on how to solve my problem and maybe also a web page to learn more about math and Arduino.

  ReadAnalogVoltage
  Reads an analog input on pin 0, converts it to voltage, and prints the result to the serial monitor.
  Attach the center pin of a potentiometer to pin A0, and the outside pins to +5V and ground.
 
 This example code is in the public domain.
 */

// the setup routine runs once when you press reset:
void setup() {
  // initialize serial communication at 9600 bits per second:
  Serial.begin(9600);
  
}

// the loop routine runs over and over again forever:
void loop() {
  int dBm=0 ;
 int sensorValue = analogRead(A0);// read the input on analog pin 0:
float voltage = sensorValue * (5.0 / 1023.0);  // Convert the analog reading (which goes from 0 - 1023) to a voltage (0 - 5V):
  dBm=40*voltage-40; // calculate dBm
//int P=10^(4*voltage-7)
  Serial.print(voltage); Serial.print(" V    ");Serial.print(dBm);Serial.println("dBm");// print out the value you read:
  delay(10);

http://arduino.cc/en/Reference/MathHeader

Hi geggil

The formula for converting dBm to W is:

P(Watts) = 10 ^ (( P(dBm) - 30) / 10)

As a check, if P(dBm) = 30, the part in brackets reduces to 0, and 10 to the power 0 is 1, so the power is 1W, which is right.

In C and C++ which the Arduino uses, there is a "pow" function - here is the Arduino reference page about it:

I think the statements below will do the conversion:

double pWatts = pow( 10.0, (dBm - 30.0) / 10.0);

Hope that helps.

Ray

This helped a lot! :slight_smile:
My next step in the project is to use mW on the output when the power is less than 1W.
I'll use use some if and else statements to get that done.

No problem :slight_smile:

I've just spotted something else you may want to look at.

Are you building the design in Figure 41 on page 21 of the datasheet? That circuit covers -30dBm to +60dBm, a range of 90dB. From page 21, it looks like the AD8307 output voltage will go up by 0.25V for each 10dB. So that gives a 2.25V range in the voltage going to the Arduino.

That 2.25V equates to a range of about 460 in the results from analogRead (before converting to dBm). However, you are storing the dBm in an integer, which will only hold 90 different values after the calculation below (i.e. the operating range of 90dBm).

dBm=40*voltage-40; // calculate dBm

So your results will be much less precise than they could be (90 possible answers vs 460). You could try using a float instead of an int for dBm. This will avoid losing the fractional part when you do this calculation in your code:

Cheers

Ray

Tanks alot Ray!
I still have to do some work on the resolution under 10dBm.
Maybe I'll re-scale it to cover 200 W instead of 1 kW, the resolution usable for ham-radio operation will be better.
Normal operation is from 100 mW to 100-150 W.
It is just to re-calculate the voltage divider and mod the formula for the power calculation.

Good luck with it. I am building an Arduino-controlled sweep signal generator, and I plan to add an AD8307 amp to it in the future.

One last thought on your software. The formula (5 / 1023) assumes that the reference voltage used by analogRead is exactly 5V. The default for analogRead is that it uses the Arduino supply voltage. This could be a little different from 5V and if you want to get maximum accuracy, you may want to measure the actual supply voltage (or do some tests feeding in known voltages to the analog pin) and adjust the 5.0 to compensate.

All the best

Ray

I’m aware of the reference voltage issue.
On the final PWR meter I’ll use an external voltage regulator as supply for the log amp and as a reference. It will probably be a 3,3V because I got a good deal on 50 off them on Ebay.

For your sweeper project this link might interest you.
http://www.hamstack.com/project_antenna_analyzer.html

By the way I’m a ham LA9XNA.
In my club ( LA1J ) we have building night every Thursday and I’ll probably introduce a similar project as the SWR meter.
My idea are to add an extra detector for filter tuning.

I forgot to add my latest rev of the code.
It is a work in progress.

/*
  RF_pwr_meter
  Reads an analog input on pin 0, converts it to voltage, dBm and W and prints the result to the serial monitor.
  The hardware are based on the AD8307 log amp( power detector) see page 21 fig 41 in the datasheet.
 */


  void setup() { // the setup routine runs once when you press reset:
  Serial.begin(9600); // initialize serial communication at 9600 bits per second: 
}
void loop() { // the loop routine runs over and over again forever:
  //int P=0;
 float sensorValue = analogRead(A0);// read the input on analog pin 0:
  float voltage = sensorValue * (5 / 1023.0);  // Convert the analog reading (which goes from 0 - 1023) to a voltage (0 - 5V):
  double dBm=(40*voltage-40); // calculate dBm
  double P= pow( 10.0, (dBm - 30.0) / 10.0);
  Serial.print(voltage); Serial.print(" V    ");Serial.print(dBm);Serial.print("dBm   ");Serial.print(P);Serial.println("W");// print result
  delay(1000);
}

Latest update.
I'll do all the internal power calculations in uW and scale the power by dividing by 1k or 1M.
When working directly in W i get problems when the power is less than two digits after comma.
It is going to be some if and then statements.

Hi

When working directly in W i get problems when the power is less than two digits after comma

This could be just a display thing with the println statements. You might try something like this to see if it helps.

Serial.print(dBm, 6);

Shook loose some dormant brain cells with memories of my TWT days (that's travelling wave tube, steady on) at the beginning of my career, you did.

Got some more issues, guess it is only some minor programming issues.
The issue are that some of the caracters are hanging with 3 horisontal bars.
I guess there are an instruction to whipe the prevously used frames.

/*
  RF_pwr_meter
  Reads an analog input on pin 0, converts it to voltage, dBm and W and prints the result to the serial monitor.
  The hardware are based on the AD8307 log amp( power detector) see page 21 fig 41 in the datasheet.
 */

#include <LiquidCrystal.h> // include the library code:
  LiquidCrystal lcd(12, 11, 5, 4, 3, 2); // initialize the library with the numbers of the interface pins

  void setup() { // the setup routine runs once when you press reset:
  Serial.begin(9600); // initialize serial communication at 9600 bits per second:
  
  lcd.begin(16, 2); // set up the LCD's number of columns and rows: 
  lcd.setCursor(5, 0); // (note: line 1 is the second row, since counting begins with 0):
  lcd.print("LA9XNA"); // Print a message to the LCD.
  lcd.setCursor(1, 1); // (note: line 1 is the second row, since counting begins with 0):
  lcd.print("RF-Power meter"); // Print a message to the LCD.
  delay(4000); //Delay 4 sek
  lcd.clear(); //clear display
}
void loop() { // the loop routine runs over and over again forever:
 float sensorValue = analogRead(A0);// read the input on analog pin 0:
  float voltage1 = sensorValue * (5.047 / 1023.0);  // Convert the analog reading (which goes from 0 - 1023) to a voltage (0 - 5V):
  float voltage = voltage1/2; // divide by two because of 2x opamp on input
  double dBm=(40*voltage-40); // calculate dBm
  double Pu= pow( 10.0, (dBm+30) / 10.0); //pwr in uW
  double Pm= pow( 10.0, (dBm) / 10.0); //pwr in mW
  double Pw= pow( 10.0, (dBm-30) / 10.0); //pwr in W
  Serial.print(voltage); Serial.print("V");
  Serial.print(dBm);Serial.print("dBm");
  lcd.setCursor(0, 0);
  lcd.print(dBm);lcd.print("dBm");
   lcd.setCursor(0, 1);
  if (dBm <= 0) goto PrintPu; // jump to print uW
  if (dBm >= 30) goto PrintPw; // jump to print W
 Serial.print(Pm); Serial.println("mW"); // print mW
  lcd.print(Pm);lcd.println("mW"); // print mW on LCD
 PrintPu :
  if (dBm <= 0)  Serial.print(Pu); if (dBm <= 0)  Serial.println("uW"); // print uW
  if (dBm <= 0)  lcd.print(Pu); if (dBm <= 0)  lcd.println("uW"); // print uW
  PrintPw :
  if (dBm >= 30) Serial.print(Pw); if (dBm >= 30) Serial.println("W");// print W
  if (dBm >= 30) lcd.print(Pw); if (dBm >= 30) lcd.println("W");// print W
  delay(500);

}

SAM_02581.jpg

Solved it my!
Put 10 empty space after the uW, mW, W.

Hi ,
Could anyone help me to change this above code for a specific power detector IC LTC5508 to measure power only for 2.4GHz Wifi range frequency?

Hi can you share which Vout to connect with AD8318 as their are 2 vouts should we ground the one and use the second or should we short both of them please share schematic or a picture..Also should we need a attenuator?
thanks and have a nice day :slight_smile:

Sharafath:
Hi ,
Could anyone help me to change this above code for a specific power detector IC LTC5508 to measure power only for 2.4GHz Wifi range frequency?

Sure, just post your attempt and we can help. However, this appears to be an active thread so you shouldn't hijack it. Please start another thread.

it WAS an active thread, in 2014