Wobbulator, RF Network Analyzer

I recently found an interesting measuring project wobbulator with the Raspberry Pi computer from Tom Herbison, a HF Network Analyzer. It consists of the following elements:

For the Hardware Input/Output handling see RaspberryPiIOLibrary

A similar project Poor Ham's Scalar Network Analyzer (PHSNA) with an Arduino UNO as controller and PC for graphics is developed on Yahoo, see at Links. The graphic user interface and the use of the low cost Raspberry Pi computer I like more, than the Arduino - Excel setup.

Unfortunately the dynamic range of the wobbulator was not so good (about 52 dB). So, I tried to improve that, to about 65 dB. After several tries I came very close (60 dB) to that target.

Because the first hardware design of the wobbulator was more for qualitative measurements, I adopted some design improvements from the PHSNA group, and made my own PCB's (Printed Circuit Board), in order to combine the best of the two projects.

Now, after 8 month of work with some throwbacks, it looks like, that the project is successfully finished.


Logarithmic Amplifier

Because of the AD8307 Logarithmic Amplifier, the A/D converter just needs a 10 bit resolution, so I decided from the viewpoint of cost and size to use an Arduino Pro Mini controller module. The alternative, an ATtiny85-20 works in principle, but not reliable.

A PCB (size: 70 x 45 mm) brings together:

For the schematic please see the picture on the right (click to expand), for printing download the PDF file.

To make your own PCB (double sided, thickness 0.5 mm) I will attach the Eagle6 files:

A/D converter, software Arduino Pro Mini

The basic A/D converter and I2C communication software was developed with an Arduino Nano 3 module, with the Arduino IDE and then ported to the Arduino Pro Mini. The Analog/Digital Converter software (Arduino version 1.0.5) can be downloaded here. Also the Python3 test program for the Raspberry Pi. Usually you can buy the Arduino Pro Mini in the +5 V version (clock = 16 MHz). I run this board with 3.3 V only, in order to have a better A/D resolution and a more stable reference voltage. The maximum clock frequency with 3.3 V supply should be 13 MHz, but it works also with 16 MHz at room temperature (4 mA supply current).

For debugging the tool Bus Pirate 3 (firmware version 6.1) is use, with program CoolTerm.app (Mac OS) and 115000 baud, no handshake. When you see the prompt HiZ> hit "i" for information, and "m" for the modes.

For programming the module please see at AVRArduinoProMini.


The communication with the Raspberry Pi is made via I2C/TWI bus.

The tests were sniffed with the Bus Pirate 3 from Links, see:

Legend: + = ACK, - = NACK, [ = Start bit, ] = Stop bit

send A/D channel 3, get analog value 0x200 = 488

The oscilloscope picture (click on enlarge) on the right shows the I2C timing, Data: [0x0A+0x03+], upper trace = SDA, lower trace = SCL). The I2C clock was 100 KHz, the ATmega328 clock was 16 MHz.


A/D converter, software Attiny85-20

Because of the AD8307 Logarithmic Amplifier the A/D converter just needs a 10 bit resolution, I decided from the viewpoint of cost and size to try an Atmel ATtiny85-20 micro controller. This works in principle, but not reliable. I will just explain what is the reason of the problem.

The CPU clock rate was set to 8 MHz, the I2C clock 40 KHz. Because the clock pulses are created by software, the timing is not very accurate, see the oscilloscope picture (click to enlarge) on the right (Data: [0x0A+0x03+], upper trace = SDA, lower trace = SCL). The clock stretching from the slave is 50 to 100 us.

I just found out, that the problem is well known: I2C clock stretching. Maybe there is a software solution for it: Raspberry Pi I2C clock-stretching bug.

In order to make it easier to analyze the problem by digital scope, you can add series resistors in the I2C bus lines. When the Raspberry Pi pull-up resistor are 1k8, then a value of 390R would be good. Then you see at the "0" level, who is pulling the bus down.

Nevertheless I will attach the source code for the ATtiny85-20 and the Python3 test program for the Raspberry Pi. The Links to the I2C/TWI libraries are included in the source code.

The communication with the Raspberry Pi is made via I2C/TWI bus.

The tests were sniffed with the Bus Pirate 3 (firmware version 6.1) from Links, see:

Legend: + = ACK, - = NACK, [ = Start bit, ] = Stop bit

send A/D channel 3, get analog value 0x200 = 512

In order to avoid I2C bus speed problems, the I2C clock rate was reduced from 100 KHz to 40 KHz:

# To check your i2c bus baudrate :
$ sudo cat /sys/module/i2c_bcm2708/parameters/baudrate

# edit a new file
$ sudo nano /etc/modprobe.d/custom.conf
  options i2c_bcm2708 baudrate=40000

$ sudo reboot

$ sudo cat /sys/module/i2c_bcm2708/parameters/baudrate

RF amplitude measurement

In order to have a large dynamic range in measuring the Radio Frequency amplitude coming back from the DUT (Device Under Test), a logarithmic amplifier AD8307 was selected (about 88 db dynamic range). In order to use the full dynamic range of the logarithmic amplifier from +16 dBm (4.0 Vpp at 50 Ohm) to -72 dBm (0.159 mVpp at 50 Ohm) the input level should be accordingly. The definition for 0 dBm is 1 mW (0.63 Vpp at 50 Ohm). I always tell Vpeak-to-peak because most of the time those voltages are measured with an oscilloscope.

The output level of the DDS-Generator therefore should be adopted close to the +16 dBm. While the supply voltage is 5 V, the output current of the DDS-Generator is set via RSET = 3k9 to 10.24 mA. The output of the DDS generator got a symmetric 1:1 transformer and a new low pass filter, see Filter_AD9850_from_DL5FA. With a load resistance of about 50 Ohm the output voltage is maximum 0.63 Vpp, hence 0 dBm at 50 Ohm. Maybe a 3 dB level increase is needed to reach the 0 dBm level, see here for a simple modification.

The input impedance of the logarithmic amplifier is 50 Ohm and the input connection a BNC plug.


Raspberry Pi, hardware

The first prototype had all modules together on the proto board, see the picture on the right. The I/O port from the Raspberry Pi are fed via 26 pin flat cable to a half size proto board, price about 6.50 EUR, see Links. On one side on top the DDS-Generator AD9850 is plugged via a 10 pin connector. Because the control signals of the DDS-Generator are inputs only, the DDS-Generator can be operated with +5 V, while the Raspberry Pi works with +3.3 V. While the Logic 1 level at 5 V supply is specified with a minimum of 3.5 V (70% of supply voltage), it works in reality. With a specified input current of maximum 12 uA the Logic 1 level from GPIO is nearly the same as the supply voltage of 3.3 V. For more details, please see at the Links.


On the other side on top a self made PCB (printed circuit board) is plugged via a 6 pin connector, which holds the Arduino Pro Mini module, the logarithmic amplifier AD8307 and 2 BNC plugs. The upper side side of the PCB is a ground plane for shielding. It shows up, that the 50 Ohm input resistance of the logarithmic amplifier together with very short wires needs no further shielding.

Second prototype

While the evaluation it shows up, that the DDS-Generator produces a lot of RF noise. If you want to have a larger dynamic range of the amplitude, the DDS-Generator must be housed in a metal box and shielded, see the picture on the right. All signals and the +5 V supply are fed through 1 nF capacitors in the wall of the box. Inside the box a 1 mH choke (0.7 Ohm) is inserted in the +5 V supply.

The AD9850 DDS-Generator modules from China are probably so cheap, because the low pass filter was not designed well. There are several proposals to improve that, see AmateurRadioDDSgenerator. I designed my own filter and it works good, for details see Filter_AD9850_from_DL5FA.


Final setup

Finally, after removing some hardware bugs (cold soldering, bad capacitor, etc.) I put all the modules in a housing Teko D13 (WxHxL 150 x 54 x 135 mm, reichelt.de 4.25 EUR). This housing was selected because of the easy handling and low cost.

For easier mounting and as a ground plane a copper plated epoxy board 105 x 120 mm was screwed onto the already provided posts inside the housing (copper side up). The metal housing is soldered at 2 points to the base plate, distance to the wall = 15 mm. The logamp PCB is mounted on 3 screws M2.5 x 8 mm, which are mounted from underneath of the base plate. Two nuts (3.2 mm) are used for the spacing of the logamp PCB. The back side of the PCB is soldered with a piece of copper foil or 3 thick wires to the ground plane.

Because there is already a cutout in the backside of the housing, I extended the cutout so the BNC plugs seats well, see the picture on the right. The upper half of the housing fits without modification.

The flat cable to the Raspberry Pi is routed over the side wall, and cutout over the width of the flat cable by about 1 mm, allowing the housing to close without gap.

The original front plate, transparent red plastic, is just used to close the open front side of the housing.


Raspberry Pi, software

The Wobbulator software can be downloaded (ZIP file) from the github archive, see Links.

For the I2C/TWI interface bus you need a driver library , see Links. The quick2wire-gpio-admin software can be downloaded as a ZIP file from the github archive, into the new Install folder.

Unfortunately the GPIO library needs root rights to work. There is also a GPIO library which does not need that, but it is about 10 times slower, please see here for details.

For installation of the libraries and tools do:

# install documentation tool
$ sudo apt-get install pandoc

# tools to install
$ sudo apt-get install python-pip
$ sudo apt-get install python-virtualenv

$ mkdir Install
$ cd Install

# install GPIO/I2C library
# Download the I2C driver quick2wire-gpio-admin
$ wget https://github.com/quick2wire/quick2wire-gpio-admin/archive/master.zip
$ unzip master.zip
# Rename
$ mv master.zip quick2wire/quick2wire-gpio-admin.zip
$ cd quick2wire-gpio-admin-master
$ make
$ sudo make install
# check for good installation
$ man gpio-admin

# Install GPIO/I2C Python3 library
$ wget https://github.com/quick2wire/quick2wire-python-api/archive/master.zip
$ unzip master.zip
# Rename
$ mv master.zip quickwire-python-api.zip

# setup group 
$ sudo adduser $USER i2c
# logout and login again, to activate the group assignment
or reboot later

# check for function (24(BCM) = 18(pi_header_1) = 5(pins) = DATA)
$ gpio-admin export 24
$ cat /sys/class/gpio/gpio24/value
# set gpio24 output to "1"
$ echo out > /sys/class/gpio/gpio24/direction
$ echo 1 > /sys/class/gpio/gpio24/value
$ cat /sys/class/gpio/gpio24/value
# shut off pin
$ gpio-admin unexport 24

# install i2cdetect
$ sudo apt-get install i2c-tools

New Jessy method for I2C enabling:

$ sudo raspi-config
# select in the menu "Advanced Options"
# select in the menu "A7 I2C  Enable/Disable automatic loading"
# Answer "yes" to "Would you like the ARM I2C interface to be enabled?"
# Info: The ARM I2C interface will be enabled after a reboot"
# Answer "yes" to "Would you like the I2C kernel module to be loaded by default?"
# Exit the program
# Do a reboot

Old method for I2C enabling:

# edit file /etc/modprobe.d/raspi-blacklist.conf
  # Quick2wire software library needs it 2013-12-09 RR
  #blacklist spi-bcm2708
  #blacklist i2c-bcm2708

# edit file /etc/modules
# add line

$ sudo reboot

Check the I2C interface:

# check for i2c device descriptor
$ ls /dev/i2*
crw-rw---T 1 root i2c  89, 0 Dez  9 18:14 /dev/i2c-0
crw-rw---T 1 root i2c  89, 1 Dez  9 18:14 /dev/i2c-1

# check for modules
$ lsmod
Module                  Size  Used by
i2c_dev                 5620  0
snd_bcm2835            15846  0
snd_pcm                77560  1 snd_bcm2835
snd_seq                53329  0
snd_timer              19998  2 snd_pcm,snd_seq
snd_seq_device          6438  1 snd_seq
snd                    58447  5 snd_bcm2835,snd_timer,snd_pcm,snd_seq,snd_seq_device
snd_page_alloc          5145  1 snd_pcm
spidev                  5224  0
leds_gpio               2235  0
led_class               3562  1 leds_gpio
spi_bcm2708             4510  0
i2c_bcm2708             3759  0

$ sudo i2cdetect -y 1
     0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f
00:          -- -- 05 -- -- -- -- -- -- -- -- -- --

In order to have the path of the library folder accessible to Python3, the environment variable PYTHONPATH can be setup with the path of the Quick2Wire library. But this works since Raspbian 2015-11-21 only.

# link Quick2Wire-API (i2c) library to Python
# edit /home/pi/.bashrc
# add
  # for I2C use
  export QUICK2WIRE_API_HOME=/home/pi/Install/quick2wire-python-api-master
# logout and login again, to activate the environment

For Raspbian 2014-01-07 the environment variable PYTHONPATH does not work together with sudo. I could not find out why, my solution 1 is to copy the folder quick2wire to the Python3.2 folder dist-packages, or solution 2 to add the path of the Quick2Wire library directly in the program wobbulator.py.

# Error message:
ImportError: No module named quick2wire.i2c

# solution 1
# found the path from "IDLE3/File/Path Browser"
# copy folder quick2wire-python-api-master/quick2wire to /usr/local/lib/python3.2/dist-packages/

# solution 2
# Edit wobbulator.py
import sys
# setup the path according to your local installation

#import quick2wire i2c module
import quick2wire.i2c as i2c

In order to start the program wobbulator.py from the command line the first line must be a shebang line, see also Links:

# change path to folder
$ cd /home/pi/Install/wobbulator

# Start programm from the terminal command line
# since Raspian 2015-11-21
$ python3 wobbulator2.6.3.py

# for old Rapian
$ sudo ./wobbulator2.6.3.py

Changes to wobbulator.py

After some improvements of the original software I am using now version 2.6.3 with some patches.

 #!/usr/bin/env python3

Because of the different A/D converter the I2C routine must be changes. For easier scaling, i converted the binary value 0 - 1023 to Volt 0 - 3.3 V.

# for function sleep
import time, sys

#define address for ADC chip, Arduino mini
adc_address = 0x05

# Function to get reading from ADC
def getadcreading(address):
    bus.transaction(i2c.writing_bytes(0x05, 0x03))
    avhigh, avlow = bus.transaction(i2c.reading(address,2))[0]
    t = (avhigh << 8) | avlow
    # Uref = 3.32 V / 1023 (10 Bit) = 308 -> scale in Volt
    return (t / 308)

        canvas.create_rectangle(1, 1, 500, 500)
        ampdivlabel = Label(frame, text='10dB/div')
        ampdivlabel.grid(row=0, column=6)

            startV = float(-80)
            stopV = float(20)

            vN = startV + 100/gain

        bias = (getadcreading(chip, address) + getadcreading(chip, address))/2 #<< changed afa

            reading = getadcreading(chip) #includes triggering adc << added afa

                # AD8307 (5 V supply) 23mV/dB, span 0.27 - 2.23 V, *185 = 10 dB/div
                y = int(500 + 25 - (reading * 185))

root.wm_title('RPi Wobbulator v2.6.3RR, use "scrot -s -d 4" for window shot')

The patched program is provided for download.

VNC use

The setup and use of VNC (Virtual Network Computing) is described on page VNC server


Measurements and conclusion

With the Arduino Pro Mega as an Analog to Digital converter I had to modify the main Python program, but now it works in principle, see screen-shot on the right. The 290 steps are measured in about 1.3 seconds, what I think is a good time.

The test object is a Murata 10.7 MHz dual ceramic filter SFW-10.7MA with the data:

In the picture (Graph) to the right you will see 3 traces in blue.


I wanted to check the dB linearity of the logarithmic amplifier in 10 dB steps from 0 to -60 dBm. While measuring I found out, that the 0 dB attenuation was compressed, because of the 3.3 V supply.

In order to improve that, I changed to a 5 V supply. Now the linearity looked better.

Originally you have a practical dynamic amplitude range with about 60 dB, even if the logarithmic amplifier has a maximum dynamic range of about 88 dB.

Considering the actual RF output level at the DDS-Generator of 0 dBm, the possible dynamic range could be 70 dB (open input). The missing 10 dB are coming from noise, because the logarithmic amplifier is sensitive up to 900 MHz. I could not found out how to improve that.

The printed circuit board of the logarithmic amplifier had a ground shield on one side, with some contacting to the wire side. It is important to keep the wires at the front end short.

To get a clean signal, the noisy DDS-Generator must be put in a metal box. All control signals and the power supply got 1 nF pass through capacitors and a ferrite pearl. The +5 V inside got a choke with 1 mH.



Poor Hams Scalar Network Analyzer is a very similar project to the Wobbulator, but depends on MS Windows Excel and more comfortable PLX-DAQ (Data Acquisition for Excel with serial link) from company parallax, see at Links. The RF generator is the same. For level measuring a logarithmic amplifier (AD8307) from project Power meter is used.

The main computing is done with an Arduino UNO module (CPU Atmel ATmega328). It is also possible to use a cheaper (Ebay, about $7) and smaller Arduino Nano 3.0 module.

The normal operation is to make a frequency sweep with a Terminal Program (Win32 - PuTTY) and copy and paste the data block into a text file with extension .csv (comma separated value). This text file can be imported into a spreadsheet (MS Excel, LibreOffice, OpenOffice) and converted into a diagram. This is a lot of handling.

In order to make it more comfortable, you can use the free Data Acquisition Program PLX-DAQ to automate that time consuming process, see picture on the right (click to enlarge). Yes, it works, but in the long run you will get problems. The Program PLX-DAQ is very nice made, but from the year 2007 and it looks, that it is no longer maintained. In my test I used Win7-32 SP1 and MS Excel 2002 SP3. While in the data acquisition test spreadsheet PLX-DAQ.xls the link to the ActiveX program selmaDAQ_Ver2.ocx works fine, in the application spreadsheet PMSNAb4r2.xls the link to the ActiveX Program could not be established (VBA runtime error 464). A workaround is, to load first the test spreadsheet and then the application program into Excel. This also works running Win7-32 in a virtualbox (ver. 4.3.6).

The Arduino UNO software SimpleSNA_WA5BDU_1r9_rev2r62.zip can be downloaded from the Yahoo group PHSNA (Files), but you have to be a member of this group.

The project description is in the files:

Terminal Program PuTTY

Because the mentioned Terminal Program Term232 is not very intelligent, I choose PuTTY to use PuTTY, download windows installer. For use with PHSNA a few parameter changes are necessary or usefull:

How to use the clipboard:

When you start PuTTY next time, just double click left on session name, e.g. Arduino_COM4_9600.

PHSNA operation

The basic operation is to use a Terminal Program, e.g. PuTTY on Windows, or any other comparable one on other operating systems (Mac OS X - CoolTerm.app, Linux - PuTTY) to talk to the Arduino UNO. See the main menu:

slope = 0.18700
intercept = -85.00

DDS is running on: 7040000 Hz  AD9850 mode

Simple SNA by Jim Giammanco, N5IB, and Jerry Haigwood, W5JH
Version 2.62 on 21 Nov 2013, 01-04-2013 Nick, WA5BDU_1r9


   1 - SNA Function
   2 - Generator Function
   3 - Calibrate DDS
   4 - Determine or enter AD8307 constants
   5 - Set start-up frequency
   6 - Change start-up mode to PLX (Excel)
   7 - Test and characterize crystal
   8 - Toggle AD9850/AD9851 modes
   9 - Re-display menu


Unfortunately editing is not possible. Mistyping usually ends in a reset of the Arduino UNO.

AD8307 constants

This is a tricky business. In order to calibrate the analog measurement value of the RF level, you have to dig in the software. In program eeprom_i_o.ino you can find the definition for the slope:

# line 39
serialprintln_P(PSTR("Enter slope (decimal number dBm / count): "));

The parameter calculation slope/intercept you can find in program misc_functions.ino:

  // Power Meter Calibration - Conversion of ADC counts to dBm                
  // the equations below convert the raw output (pin 4) of the AD8307 to dBm
  // for a raw, unamplified AD8307: assuming 0.025 V per dBm, and 0 V corresponds to -84 dBm, 
  // so 0 dBm is 2.1 V, and +10 dBm is 2.35V
  // but most 8307 meters would have a buffer amp with some gain so that +10 dBm will be about 5 V
  // to accomodate that amplifier the parameters below would have to be recalculated... 
  // think y = mx + b, you have to determine the slope y in dBm per volt (e.eg. 18.8)
  // and the intercept in dBm correcponding to zero volts, e.g. -84
  // v_dBm = -84 + ((40*CH0_ADC_counts)/1023.0)*AREF; 
  //     generic transfer function for raw, unamplified AD8307 output

Once you have optimized (lowest voltage from AD8307 with open input) your hardware with low pass filters, chokes, bypass capacitors and shielding, it make sense to do a calibration of the logarithmic amplifier AD8307 with calibrated attenuators. For details, please read this conversation

Frequency Sweep with PLX-DAQ

After finding the previous mentioned workaround for using the software PLX-DAQ, you could enter in cells L2-L4:

Then you click on Connect of the PLX-DAQ control window. The measurement values are read in from the serial link to the Arduino UNO and inserted into the spreadsheet at the proper place, see the picture.

It has a side effect, that this mode of operation (PLX-DAQ) is then stored in the EEPROM of the Arduino UNO. Next time, you connect to the Arduion UNO with a terminal program, you have to wait for about 30 seconds to enter the menu mode.

PHSNA - Poor Hams Scalar Network Analyzer


Raspberry Pi

Python Software

Input/Output Software


List of pages in this category:

-- RudolfReuter 2013-12-09 15:54:41

Go back to CategoryAmateurRadio or FrontPage

RaspberryPiWobbulator (last edited 2015-12-12 12:24:33 by RudolfReuter)