Power and SWR Meter with dual bargraphs and sticky bar, using 2x AD8307

This project has now been updated, see here: Power and SWR Meter - Rev II

Back to main page

Page last updated 2016-05-27. Added a new version, with improved functionality - The new version is implemented as an Arduino Sketch
First publication of page 2013-09-29

  • microwatts to kilowatts
  • accurate SWR at power levels down to 1mW 
  • dual bargraphs, with 100 bars each
  • sticky bar for PEP reading
  • instantaneous power, 100ms average power, 1s average power and 100ms peak power
  • 1, 2.5 or 5 second PEP
  • adjustable SWR alarm threshold, 1.5:1 to 4:1 
  • adjustable power threshold for SWR alarm 
  • automatic scale selection (auto ranging), mW to kW
  • power is measured 200 times per second
  • virtual serial port over USB
  • "rotate and push" navigation of configuration menus
  • calibration (if required) against an accurate known power level
  • uses 5V, 200mA, either by using USB wall wart or computer USB port 
  • 0.025 dB resolution (12 bits referenced at 2.6V)
  • screensaver mode with customizable screensaver messages

Building blocks:
  • Teensy++ 2.0 (Arduino compatible) Microcontroller board (www.pjrc.com or www.sparkfun.com)
  • 20x4 LCD (any HD44780 compatible 20x4 LCD will work, $10 on ebay)
  • Rotary Encoder with a builtin pushbutton (Panasonic EVQ-WTEF2515B, eBay)
  • Detector circuit using a tandem match coupler and 2x AD8307 logarithmic amplifiers

Some display examples:

A 20x4 LCD can be coerced into displaying four simultaneous bargraphs, each showing what effectively amounts up to 100 bars.  This is achieved by turning each character position of the LCD display into six bars (one in every six bars is not visible).

This display shows a continous carrier, at 103W:

A sticky bar can be implemented by showing a long and fat bar in the middle of a character position which is not being used, thus showing an approximation of the highest level within a period of say, 1, 2.5 or 5 seconds. This sticky bar is then of course with a much coarser resolution, or only 20 bars in total, instead of 100. The sticky bar is only visible if that particular character position is not being used to show the “regular” bars. This methodology works surprisingly well.

This display shows a SSB voice signal. The highest power seen within the selected PEP period (1, 2.5 or 5 seconds) is 84W. The sticky bar shows the PEP value. The highest power within the last 100 milliseconds is 8.5W, as also indicated by the bargraph. Other available displays can be selected with the rotary encoder, to depict average power and instantaneous power:

This display shows 99W being transmitted into a very badly aligned antenna. The transmitter sees a good load, as it is in front of a tuner that has been aligned for a good match. The meter is positioned between the tuner and the antenna:

Below is a different display selected, indicating the exact same situation. Now we see that the forward power is 211W and the reflected power is 112W, i.e. we have 99W out (apparently the SWR display was flickering between 6.4 and 6.6). On this display the bargraphs have been compacted down to 14 character positions each. This display has two power graphs for forward and reflected power, no sticky bar and no SWR graph:

10 bits or 12 bits ADC resolution:

Most similar implementations that I have seen use 10 bit analog to digital converters (ADC) built into the microcontroller, usually referenced against 5 volts.  This gives a measurement resolution of approximately 5mV per bit, which translates to 0.2 dB, when considering that the AD8307 has a slope of 25mV per 1 dB.

This project allows for two different configurations (the microcontroller automatically senses which configuration is used):

  1. use the 10 bit ADCs built in the AT90USB1286 microcontroller, referenced against 2.56V.  This provides a measurement resolution of 0.1 dB; or
  2. use an external 12 bit ADC, referenced against 2.6V.  This provides a measurement resolution of 0.025 dB.

The second option is a bit of an overkill, perhaps even somewhat nonsensical.  However it was simple to implement.  Additional component cost is approximately $15 (USD).  However, the 12 bit ADC chip is very small and not easy to solder.  The choice is yours :)

Microcontroller Firmware:

For those who like to tinker, the firmware is is free software, released under the GNU General Public License.

The latest version of the firmware is written in the Arduino Environment, with Teensy Extensions available here:


The source code is available at the bottom of this webpage, see the file: PSWR_Axxx_ArduinoSketch.zip.  This zip file contains a Folder which includes a number of files.  All of those together constitute the source code.

Note that certain firmware features can be tailored through modification of parameters in the PSWR_A.h file included in the source code for the firmware.

The firmware source code is commented throughout and should hopefully be relatively easy to understand/modify/expand/adapt.

An older version of the firmware (including 90% of current features) is also available, see file Power_SWR_Meter_075.zip.  This version can be compiled using Atmel AVR Studio, version 6 or later.  The zip file also contains a pre-compiled HEX file that can be uploaded into the Teensy++ 2.0 microcontroller.

Detector Circuit and Tandem Match Coupler:

(click on schematic to enlarge)

A double sided printed circuit board was used, only one side etched, a number of holes drilled to connect between the two sides. Some of my home made printed circuit boards turn out to be somewhat less than perfect :)  Well, this one was just barely good enough to get the work done:


Here is an X-ray view of the PCB layout for the detector circuit.  Please refer to the bottom of this webpage to download an accurate size PCB layout for the detector circuit:

Here is a picture of the detector board populated with components for the 10 bit ADC option and hooked up for testing:

Below, the same detector board has been populated with components for the 12 bit ADC option.  The main drawback of this option is the miniscule size of the AD7991 ADC chip (see the middle of the printed circuit board).  It takes a very good iron and a steady hand to solder:

The detector circuit uses all surface mount components.  R1 – R6 are SMD1210, 1/2W.  Other resistors and capacitors are SMD0805.  Whether to include the AD7991 and its associated components or not, depends on which option is chosen. 

You may notice the lack of any slope adjustment circuitry around the AD8307.  If necessary, any mismatch between the two AD8307 detectors can be automatically adjusted out by the microcontroller firmware, using two separate signal levels, first in the forward direction and then also in the reverse direction.  Hence, no additional circuitry is required around the AD8307 offset and output pins.  See  Menu Option “Calibrate”, under the section on Meter Displays and Configuration Menus.


A very comprehensive description of what a Tandem Match coupler does can be found here:


I have no preferred way to build the Tandem Match directional coupler.  The main issue is a good balance and isolation between the two transformers.  However, in the end, it comes down to accuracy and luck; how similarly you wind the ferrite cores, and how identical the cores themselves are. My own builds were only marginally successful at achieving isolation approaching 30 dB at 28 MHz and above.  There are many successful build descriptions available  (ARRL Antenna Book, internet…).

Printed circuit board version of a Tandem Match Coupler:

Another version, this one built free style into a shielded enclosure:

A third version, a combined Tandem Match Coupler and Detector Circuit (10 bit ADC):

Circuit Description (Tandem Match and Detector):

The Tandem Match directional coupler consists of 2x 30:1 transformers.  The ferrite cores I used are Laird 28B0375-400 (Digikey 240-2296-ND).  These cores seem to handle power levels of up to 500W (200W output has been tested with high levels of SWR).  Other Tandem Match Coupler implementations have successfully used cores such as T50-3, T68-2, FT114-61 etc.

The 50 ohm terminations for the coupler consist of 3x 150 ohm 1/2W resistors in parallel.  The third resistor is actually two resistors in series acting as a voltage divider, 127 (1/2W) and 24 ohms  (1/4W).  Actually the 24 ohm resistor is in parallel with 1100 ohm, which is the internal resistance of the AD8307.

30:1 gives a coupling of 1/30, or [20log(1/30)] -29.5dB

The voltage division gives a further attenuation of [20log(23.5/150.5)] -16.1dB

The maximum input power specified for AD8307 is 17dBm.  Then the maximum input power the meter can handle is:

17dBm + 16.1dB + 29.5 dB = 62.6 dBm or 32.6dBW, which is 1800W.

On the other hand, there is a trade off.  We are using a voltage reference of 2.56V or 2.6V.  While this adds the benefit of a simpler circuit and higher measurement resolution (0.1 dB when using 10 bit ADC, 0.025 dB when using 12 bit ADC), it caps or limits the max AD8307 input to approximately 15.5 dBm, rather than the 17dBm as specified.  A very acceptable trade off for the higher measurement resolution. 

In other words, the highest possible input power reading when using 30:1 transformers and a 127 ohm + 23.5 ohm (24 ohm in parallel with the internal 1100 ohm in the AD8307) voltage divider is just over 1kW (1300W). 

To be able to measure power levels above 500W (or 200W in reality, with high SWR levels) you may need to use larger cores for the Tandem Match coupler. 

Using T68-2 or T68-3 cores and a 40:1 ratio, as described in the ARRL Antenna Book, or perhaps better, FT114-61, will make the meter suitable for power levels up to 2kW, without any modification required of the resistors R1 through R8.

I like using surface mount components.  This is my personal choice, it is of little or no relevance at short wave frequencies, the 10 bit version of the detector circuit could of course also be built using through hole components.

Informative links to two other similar power meter implementations, including 2x AD8307 and Tandem Match directional couplers:




The Controller circuit:

Teensy 2++ from PJRC.com (Atmel AT90USB1286 microcontroller running at 16MHz).  The cheaper Teensy 2.0 cannot be used, as it doesn't have enough Flash ROM and RAM to support the firmware.  The current version of the firmware uses approximately 40 kB of Flash, 7 kB of RAM and 50 bytes of EEPROM.

A cheap 15PPR mechanical rotary encoder with 30 detent and a built-in push switch (Panasonic EVQ-WTEF2515B) , available from several sources on eBay.  Note that the 5V connection shown on the schematic is not used with the Panasonic encoder.

20x4 LCD (HD44780 compatible), available from multiple sources on eBay

Here is the version using the internal 10 bit ADC:

(click on schematic to enlarge)

This version makes use of the internal 2.56V reference available in the AT90USB1286 microcontroller.  This gives 2.56V/1024 = 2.5mV per bit, which equals 0.1 dB measurement resolution. (example power level resolution:  ... 9.55W, 9.77W, 10.0W, 10.2W … … 95.5W, 97.7W, 100W, 102W …)

Here is an alternate version to be used with the AD7991 12 bit ADC:

(click on schematic to enlarge)

The AD7991 version of the detector circuit uses an external 2.6V reference for the 12 bit ADCs. This gives 2.6V/4096 = 0.635mV per bit, which equals 0.025 dB measurement resolution.

Note that two versions of AD7991 are available, AD7991-0 and AD7991-1.  The only difference between the two versions is the I2C address of the chip.  The firmware automatically senses which chip is being used.

Red LED for SWR alarm, green LED to indicate whether serial output is active. 

Optional:  A resistor, a NPN small signal transistor (BC547 or similar) and a relay to break the PTT path in case the SWR alarm has been activated.

If SWR alarm has been activated, then deactivate by a short push of the pushbutton.

The Section Meter Displays and Configuration Menus gives a detailed overview of the firmware functionality.

Both the 10 bit and the 12 bit versions of the meter are powered by 5 volts through the USB port, either using a 5V USB wall wart , or directly from a Computer USB port.  Total current draw is approximately 200mA, including LCD and the detector circuit.  If powered by Computer USB port, then the meter can also provide measurement data to the computer via the USB port.

Here is a picture of an early version of the Power/SWR Meter.  This version used an external combined detector+Tandem Match Coupler circuit.  The meter is connected to a signal generator, approx 50mW input, 25 ohms (2x 50 ohms in parallel) as a load gives an SWR of 1.98 (should be 2.0):

(click on picture to enlarge)

Here is a picture showing the innards of the controller (not much here).  In the latest upgrade, the detector circuit has been included in the box:

(click on picture to enlarge)

Meter displays and configuration menus:

Serial output (USB virtual serial port):

The command $ppoll produces two numbers, Power and SWR:

1234.12345678, 1.02

Power is in watts, lowest readable power level is 10nW.

$pinst    produces a human readable message, instantaneous power (nW-kW) and SWR

$ppk      produces a human readable message, peak (100ms) power (nW-kW) and SWR

$ppep     produces a human readable message, PEP power (nW-kW) and SWR

$pavg     produces a human readable message, average (1s) power (nW-kW) and SWR

Example:  87.9W, VSWR 1.21

$pinstdb  produces a human readable message, instantaneous power in decibel over milliwatt (dBm) and SWR

$ppkdb    produces a human readable message, peak (100ms) power in decibel over milliwatt (dBm) and SWR

$ppepdb   produces a human readable message, PEP power in decibel over milliwatt (dBm)  and SWR

$pavgdb   produces a human readable message, average (1s) power in decibel over milliwatt (dBm) and SWR

Example:  49.4dBm, VSWR 1.21

$plong    produces a human readable message, example:

Power (inst, peak 100ms, pep 1s, avg 1s):
103W, 103W, 103W, 102W
Forward and Reflected Power (inst):
103W, 253mW
VSWR 1.10

The command $pcont will produce the output of one of the above ($ppoll, $pinst, $ppk, $ppep, $pavg, $pinstdb, $ppkdb, $ppepdb, $pavgdb or $plong) continuously, 10 times per second.

For example the commands:       


will produce continuous reporting of the instantaneous power and SWR.

Continuous mode is retained if the Meter is reset or power cycled.

 Use $ppoll, $pinst, $ppk, $ppep, $pavg, $pinstdbm, $ppkdbm$ppepdbm$pavgdbm, or $plong again after $pcont to turn back from continuous mode.

Here is the complete list of USB commands implemented in the latest version (Arduino Sketch):

$ppoll             Poll for one single USB serial report, inst power (unformatted).
$pinst             Poll for one single USB serial report, inst power (human readable).
$ppk               Poll for one single USB serial report, 100ms peak power (human readable).
$ppep              Poll for one single USB serial report, pep power (human readable).
$pavg              Poll for one single USB serial report, 100ms avg power (human readable).
$p1savg            Poll for one single USB serial report, 1s avg power (human readable).
$pinstdb           Poll for one single USB serial report, inst power in dB (human readable).
$ppkdb             Poll for one single USB serial report, 100ms peak power in dB (human readable).
$ppepdb            Poll for one single USB serial report, pep power in dB (human readable).
$pavgdb            Poll for one single USB serial report, 100ms avg power in dB (human readable).
$p1savgdb          Poll for one single USB serial report, 1s avg power in dB (human readable).
$plong             Poll for one single USB serial report, actual power (inst, pep and avg)
                   as well as fwd power, reflected power and SWR (long form).

$pcont             USB serial reporting in a continuous mode, 10 times per second.

                   $ppoll, $pinst, $ppk, $ppep, $pavg or $plong entered after $pcont will
                   switch back to single shot mode.

$sleepmsg=abcdefg  Where abcdefg is a free text string to be displayed when
                   in screensaver mode, up to 20 characters max.
$sleeppwrset x     Power above the level defined here will turn the display into meter mode.
                   x = 0.001, 0.01, 0.1, 1 or 10 mW (milliWatts).
$sleeppwrget       Return current value.

$tuneset x         x = 1.1 to 4.0. SWR tune threshold.
$tuneget           Return current value.

$alarmset x        x = 1.5 to 3.9. 4 will inactivate SWR Alarm function.
$alarmget          Return current value.
$alarmreset        Deactivate Alarm if activated.
$alarmpowerset x   x = 1, 10, 100, 1000 or 10000 mW (milliwatts).
$alarmpowerget     Return current value.

$pepperiodget x    x = 1, 2.5 or 5 seconds.  PEP sampling period.
$pepperiodset      Return current value.

$calset cal1 AD1-1 AD2-1 cal2 AD1-2 AD2-2
                   Write new calibration values to the meter.
$calget            Retrieve calibration values.

                   Format of calibration values is:
                   cal1 AD1-1 AD2-1 cal2 AD1-2 AD2-2
                   cal1 and cal2 are calibration setpoints 1 and 2 in 10x dBm
                   ADx-1 and ADx-2 are the corresponding AD values for
                   AD1 (forward direction) and AD2 (reverse direction).
                      normally the AD1 and AD2 values for each setpoint would be the same,
                      however by doing reverse calibration through the Controller Menu functions
                      it is possible to balance any small differences there might be between the
                      two AD8307 outputs.
                      Note that I have not found this to be necessary at all :)

$scaleget          Retrieve user definable scale ranges.
$scaleset          Write new  scale ranges.

                   The scale ranges are user definable, up to 3 ranges per decade,
                   e.g. 11, 22 and 55 gives:
                   ... 11mW, 22mW, 55mW, 110mW ... 1.1W, 2.2W, 5.5W 11W 22W 55W 110W ...
                   If all three values set as "2", then
                   ... 2W, 20W, 200W ...
                   The third and largest value has to be less than ten times the first value.

$addebug           read raw AD input - also works with $pcont, same as $ppoll etc...

$version           Report version and date of firmware.
$help              Display the above instructions.

Calibration considerations:

The basic functionality of the power measurement routines is to read the voltage output of the two logarithmic amplifiers (both forward and reverse direction) and calculate the resulting power levels in dB-milliwatt.  To do this, the meter needs two accurate signal levels, 30 to 40 dB apart, as calibration points.  The calibration should be performed with as low SWR as possible, using a 50 ohm dummy load.

The Calibration Menu requires the signal levels to be input in decibel referenced against 1 milliwatt, or dBm.  To convert Watts to dBm, you can use the following formula:

dBm = 10 * log(P)              where P is power in milliwatts; or

dBm = 10 * log(P) + 30     where P is power in watts

If the Tandem Match Coupler transformers are made with a 30 to 1 ratio, then the meter should be accurate to within +/- 1 dB or so, using the pre-set calibration levels provided in the firmware. However, the calibration procedure can accommodate any other Tandem Match transformer ratios, and a calibration against an accurate reference will result in an almost equally accurate meter.

Calibrating in the forward direction sets the calibration points for both the forward and the reverse AD8307.

Calibrating in the reverse direction (switching the input and the output) will only set the calibration point for the reverse AD8307.  Therefore, a forward direction calibration should always be done first.  A reverse calibration is useful to compensate for any slight variations between the two AD8307.  The calibration routine automatically senses whether power is going in the forward or the reverse direction.

The single level calibration is sufficient for most purposes.  The first level is set by registering the actual power measured using the dB-level dialed in with the Rotary Encoder as a reference (default 40dBm = 10.0W, can be any level between 10.0 and 53.0 dBm).  The second level is set at 30 dB lower, assuming that the AD8307 slope gradient is  25 mV per dB.  The AD8307 datasheet indicates that the slope gradient is between 24 and 26 mV per dB.

The first level calibration is normally not required, use the single level calibration instead.

The second level calibration is useful if you want the meter to be accurate to within a dB over the full power range.  This is best achieved by inserting a calibrated attenuator, between 30 and 40 dB, after having done the single level (or first level) calibration procedure.  Best procedure is to do single level calibration in both directions and then the second level calibration in both directions as well.

Some measurement data:

As part of this project I have now built four or five Tandem Match Couplers.  Below are typical measurement values for Tandem Match Coupler directivity and SWR measurements:




Measured SWR at 50 ohm

Calculated directivity (dB), based on 50 ohm measurement

Measured SWR at 16.67 ohm

Measured SWR at 25 ohm



> 46.1





> 46.1





> 46.1




































3.0 – 3.1








In other words, there is some room for improvement if to be used at 50 MHz.  But even at 50 MHz the results are no worse than my commercially made HAM grade Power/SWR meters.

The SWR measurement accuracy is almost ridiculously good.

Back to main page

Web Site Hit Counter

To download any of the files below, please click on the down arrow ďat the right hand side of the file.

Loftur Jónasson,
May 27, 2016, 6:43 PM
Loftur Jónasson,
Feb 21, 2016, 2:01 PM
Loftur Jónasson,
Feb 10, 2014, 11:34 AM