Arduino Network Analyzer

Network Analyzer on an Arduino Shield which covers from 0-72MHz.

Similar projects worth following
The network analyzer shield uses an Analog Devices AD9851 DDS chip clocked at 180MHz which will output a sine wave at any frequency from 0Hz and 72MHz. The DDS output is filtered with a Butterworth LPF and then passed to a two transistor amplifier. The shield will output approximately 0dBm (maybe 1-2dBm if you turn the Pot up; may get distortion, though) into 50 Ohms. The output and input connectors are SMA. The power detector is an Analog Devices AD8307. It's inputs are terminated with a 50 Ohm load. There is no filtering on the input of the power detector so the chip is responsive from very low frequencies all the way up to 500MHz.

This is really three tools in one: a sine wave generator (0-72MHz @ 0dBm), a power detector (LF-500MHz, -70dBm to +10dBm), and, when used in concert together, a scalar network analyzer.

The license is the MIT License, as it seems to have almost no restrictions on use. Do what you will with it, just don't hold me liable if it goes wrong.

As an electrical engineer, I love test kit. However, it's really expensive. I have the idea of building a Spectrum Analyzer with a dual conversion superheterodyne architecture. It would cover DC to daylight and be everything I'd ever wanted...

But I decided to start smaller. Besides, one of the most important parts of a Spec An is the RBW filter. How do I know if I had a good one? I could use the Spec An itself to tell me or I could make a simpler piece of test kit (this Network Analyzer shield) that would help out in building all manner of RF things.

This was a great way to get my feet wet and learn many things about building circuit boards for RF work. What you see here is Rev 2. Rev 1 had many issues, the worst of which was the amplifier on the output. I used an Op Amp which couldn't swing rail to rail so I was getting lot's of distortion (that I could see on my Rigol 70MHz scope) and also made a really great oscillator at ~600MHz (which I only found when I put it on a Spec An at work (+3dBm... my bad, FCC, when I hooked it up to a short piece of wire and briefly listened to my sine wave signal on a short wave receiver)). I also screwed up the DC biasing... Oh well, that's why I made Rev 2!

I wrote a program to display the trace and control the board in Python. It has a known error where sometimes when decreasing the number of samples in a sweep, it throws an index out of array bounds error and stops working. I could fix it by putting a state machine into the program, but it works pretty well as is so I haven't done that yet.

Zip of files in my KiCad project folder.

Zip Archive - 96.57 kB - 03/09/2016 at 01:00


PCB Gerber FIles.

Zip Archive - 70.00 kB - 03/09/2016 at 00:58


Arduino SNA Sketch.txt

Network Analyzer Arduino code.

plain - 2.26 kB - 03/05/2016 at 20:58


Arduino Network

Network Analyzer display source code.

x-python-script - 10.62 kB - 03/05/2016 at 20:55



PDF Schematic of the Network Analyzer Shield.

Adobe Portable Document Format - 52.00 kB - 03/05/2016 at 18:55

Preview Download

View all 5 files

  • 1 × AD9851 Semiconductors and Integrated Circuits / Misc. Semiconductors and Integrated Circuits
  • 1 × AD8307 Amplifier and Linear ICs / Logarithmic Amplifiers
  • 1 × LM7301 Amplifier and Linear ICs / Operational Amplifiers
  • 2 × 2N3904 Discrete Semiconductors / Transistors, MOSFETs, FETs, IGBTs
  • 1 × KC5032A Frequency Control / Oscillators

  • Update

    Brett Killion08/17/2016 at 14:50 2 comments

    After using this a bit, it works decently well but there are some areas that could use improvement:

    - The software can use some general polishing, most likely adding a state machine to avoid the error where decreasing the sweep size basically causes a seg fault.

    - The two transistor amp could probably use some rework. A high speed op-amp may be more suitable. Just be wary of the DC biasing...

    - I don't remember which specific inductors and capacitors I selected for the filter, but 72 MHz might be beyond their self resonant frequency. That's something I should have checked before ordering/soldering them.

    All in all, I am quite pleased with how this works. It's a phenomenal tool for measuring crystals for selection/characterization for use in crystal ladder filters. I haven't tested it with amplifier circuits or other frequency selective things but I suspect that below 30 MHz it's great and over any 1-2 MHz bandwidth it is quite flat. It's only when the response is taken from 1-72 MHz that you see the lack of flatness, but it's still quite usable (especially since I added the calibration feature)!

  • Uploaded KiCad and Gerber files

    Brett Killion03/09/2016 at 01:03 0 comments

    I uploaded the Gerber files for the project as well as the KiCad files. I wasn't sure how to get the KiCad project in there so I just zipped up everything that was in my KiCad project directory.

    If there is a better way to post the KiCad files, I'm all ears (eyes...?).

  • Software Design

    Brett Killion03/05/2016 at 20:50 0 comments

    The inspiration for this software came from Alexander Frank ( who got it from Rich Heslip ( who got his from PA2OHH ( I made some pretty substantial modifications and in fact started over at one point but it's not my original idea so that's the history as best I know it.

    I wrote it in Python 3 (using Anaconda, which contained most of the packages, except PySerial, which I had to download separately) . Here is a screenshot from my Network Analyzer running:There is no option to select a port when it's running, you just have to know the port of your Arduino, edit the port name in the python file, then run the program.

    Also, if you decrease the samples there's a chance it will stop running due to an array index out of bounds error.

    All the controls are self-explanatory, I believe, with the exception of "Calibrate". When you click on Calibrate, it will complete a sweep at the current settings and save that trace as a reference. Ideally, this is done when you directly connect output to input. Then once the reference is created, connect the device under test to get a relative power reading. It moves out of relative mode back to absolute mode when either the frequency settings are changed or the number of samples per sweep are changed.

    There are some magic numbers in the code where it converts from the ADC readings to power levels. I roughly calibrated the power detector by using my oscilloscope to observe the peak-to-peak voltage of the signal at the detector inputs, then converted those to dBm. I adjusted the potentiometer to lower the signal strength and made another observation. I plugged the readings into a spreadsheet and then did a best fit line to get the equation. That's where the magic numbers came from.

    On the Arduino, the code is very simple. It parses a serial input for commands. If there is a number between 1 and 72,000,000, it sets the output frequency to that number. If it's anything else, it takes a power reading.

    When taking a power reading, it reads the ADC 16 times, adds the conversion results together, then bit shifts right twice. This oversampling and decimating does two things: it averages out noise and it effectively adds two more bits to the converter (going from 10 bits to 12).

    The sweep moves relatively quickly until the number of samples per sweep move up to 500 and 1000. At 1000 samples per sweep, it takes about 4 seconds to sweep the whole frequency range.

    Here is a sweep of a 10MHz crystal on the Network Analyzer:

    And here is a narrower sweep of the same crystal:

    Look for the full Python and Arduino code in the files section.

  • Hardware Design

    Brett Killion03/05/2016 at 18:38 0 comments

    There are several similar designs out there (most notably Alexander Frank's: which I only found after having designed my shield.

    The AD9851 takes in a 30MHz reference clock which it multiplies by 6 to get its internal 180MHz clock. It takes I2C commands to control it's output frequency. It's a current output whose maximum current is set by a resistor. I went with a 3.92k resistor to give a max current of 10mA. My sine wave is then centered at 5mA and swings from 0-10mA.

    I needed to filter out the aliased signal (basically 180MHz-desired output frequency) so I used a 7th order Butterworth LPF (because a flat passband is important here). I designed it for an input and output impedance of 100 Ohms. This way, the DDS sees essentially two 100 Ohm resistors in parallel (input and output resistors) giving a 50 Ohm impedance and converting my 0-10mA current into a 0-0.5V voltage swing. I was aiming for an output of 0dBm which is a 0.632V swing so I was a little short. I also wanted a buffer so that the DDS wasn't directly driving the output/load.

    Enter the two transistor amplifier. It's a common emitter followed by a common collector with feedback. The design came for this came from Rich Heslip (

    The schematic of my DDS/Filter/Amplifier is shown below:I added the 1K potentiometer to give some control to the output signal level. Turned up to 1K, the output is very small as it basically works as a voltage divider (it appears in series with the amplifier input impedance which is about 70ish Ohms). Turned down to zero, you get horrible distortion as the amplifier goes into saturation. In between though, you can finely tune the pot to give a nice 0dBm output sine wave.

    The input goes straight to a 51 Ohm resistor (no input filtering) to provide a broadband match. This means that the power detector is more sensitive to noise and such but also means it can be used as a power detector up to 500MHz. The output of the Analog Devices AD8307 (logarithmic power detector) goes to an Op Amp. This buffers the signal before it goes into the Arduino's ADC and also multiplies it by 2 so more of the ADC's range is utilized.

    Look for the complete schematic on the main project page in the files section.

    I made the circuit on a four-layer board. RF traces run on the top layer and the I2C signals run almost entirely on the bottom layer. The board was made by Elecrow.

    Elecrow did a great job and even though I only ordered five boards, they shipped me nine. All had been tested (I could see the probe marks on the pads). I think it was ~$25 for the boards and I paid the $20 for 3 day shipping (otherwise, it would literally take the slow boat from China). For around $50, I had nine four-layer boards that were 5cm x 5cm in my hands nine days after I clicked the button to submit my order.

View all 4 project logs

Enjoy this project?



Montilien wrote 02/07/2017 at 19:53 point


good work!

but I cannot launch python script under python 3.6.0

this release refuse installations of modules "serial" and "tkinter"

have you some idea to resolve this problem? I have tried python 2.7 so, with no more results...

Is it possible to obtain a .exe (windows binary executable) of your script?

Best regards



  Are you sure? yes | no

Brett Killion wrote 02/13/2017 at 15:00 point

I have only tried it under Python 3.5. Python 2 won't work. On my computer, I installed Anaconda Python and then also PySerial. That should be everything it needs to run. I can't give an .exe as I don't have windows (or know how to cross-compile it).

  Are you sure? yes | no

daedstudio wrote 02/15/2017 at 16:51 point

Uninstall all python distributions....

Install Anaconda 3 x64 or x86:

Install PyCharm (Community version) from:

Install in same order as downloaded....


Then you open PyCharm, and in the first prompt - "Welcome to PyCharm", you click - Configure > Settings.....

Then you click at - Project Interpreter

In the slide menu, you choose - C:\ProgramData\Anaconda3\python.exe
(It should be the only distribution, if you uninstalled everything before)
Push apply, and wait for the loading of all the libraries, should take a moment..

When done, exit PyCharm.....


Then you open cmd prompt as admin, and type:

pip uninstall numpy
/// Note: When uninstalled, check with pip list, to be sure that it's gone.

pip list

/// Then install numpy and pyserial..

pip install numpy

pip install pyserial

That should work....

And Brett.. I haven't forgotten to sent you a schematic.. I've just been so busy the last couple of weeks, so haven't worked much on it.. :o)

  Are you sure? yes | no

Marco Mauro wrote 11/16/2016 at 10:49 point

massive congrats very insipiring project, thank you for sharing ! 
I have some questions for my application:
- Is it possible to measure the quality factor (Q-factor) of a quartz crystal resonator @10 MHz nominal frequency, using your network scalar analyzer ? - If so, How can I measure the Q-factor starting from the output of the power detector log amplifier AD8307 ? Thank you so much for your help

  Are you sure? yes | no

Brett Killion wrote 11/17/2016 at 16:58 point

Connecting a crystal between the Signal out and Power in and running a frequency sweep will show the frequency response of the crystal (Q-factor can be calculated from that (BW_3dB/Center_freq)). I did this in the screen captures for a 10MHz crystal and the peak and trough is clearly visible.

  Are you sure? yes | no

Marco Mauro wrote 11/17/2016 at 17:03 point

thank you Brett  you helped me a lot !

  Are you sure? yes | no

Bill K wrote 03/07/2016 at 04:06 point

I'm interested in the KiCad files.  Thanks for the offer.

  Are you sure? yes | no

Matt Barnett wrote 03/06/2016 at 23:00 point

Very interesting work. I've needed a network analyzer for some time but sadly this one doesn't cover the frequency I'm interested in. For a modified design, I was thinking about the LTC6950(up to 1.4 Ghz) for synthesis and AD8317(1 Mhz to 10 Ghz) for sampling. Above 1.4 Ghz, it would probably be best to rely on an outside clock source for accuracy or even better, professional gear. Also, if common RF is magic, then microwave is voodoo, which seems like a circuit design nightmare.

  Are you sure? yes | no

Brett Killion wrote 03/07/2016 at 02:32 point

I still have an idea for a Spectrum Analyzer + Tracking Generator kicking around that would go up to 2 or 3 GHz. It would be based around the AD4351 (PLL+VCO) which covers 35MHz to 4.4Ghz. It would be a dual conversion superheterodyne setup.

I think it would be pretty complicated so that's why I warmed up with this bad boy.

  Are you sure? yes | no

Klima wrote 03/06/2016 at 21:35 point


Wouldn't it be wise to shield the "IN" signal right from the connector?

  Are you sure? yes | no

Brett Killion wrote 03/06/2016 at 21:52 point

Yes. I couldn't think of an easy way to get it done though.

Since the signal is coming from the DDS at 0dBm, I wasn't too concerned about the noise floor (which is probably at -50 to -60dBm. I don't have a proper signal generator to test/calibrate it so I don't actually know). I did leave some bare copper around the AD8307 so a shield could be added later.

Shielding the chip is probably the best way to decrease the noise since it has the most area to pick up interference. The trace is relatively small by comparison so it wouldn't contribute as much (I don't think).

  Are you sure? yes | no

Francois Bujold wrote 03/06/2016 at 20:21 point

Could this be used to built an ascilloscope?

  Are you sure? yes | no

Brett Killion wrote 03/06/2016 at 21:34 point

The software or hardware? The software definitely could.

The hardware probably could not. The power detector is logarithmic so waveforms would look distorted. Also, the Arduino ADC is rather slow so bandwidth would be quite limited.

For an o- scope, your best bet would be to get a fast ADC (10MHz - 40 MHz) and connect it to something somewhat powerful, like an ARM microcontroller. Then you could read the samples and pass them to a host quick enough to get decent bandwidth.

Bottom line is: scopes are hard... that's why I built a Network Analyzer :)

  Are you sure? yes | no

Alexander Lang wrote 03/06/2016 at 18:11 point

I think this could be very useful.  I have been looking for a similar device for sometime.  Any chance you will be selling these or releasing the gerbers?

  Are you sure? yes | no

Brett Killion wrote 03/06/2016 at 21:28 point

I have thought a bit about selling them, in fact this is kind of my first step into market research. If there is enough interest I could probably put something together.

 I will also post the KiCad files so if people want to spin their own, they can!

  Are you sure? yes | no

miramarhacker wrote 03/07/2016 at 02:08 point

I would pay a fair price for one of these - just board or populated.  Nice job!

  Are you sure? yes | no

Similar Projects

Does this project spark your interest?

Become a member to follow this project and never miss any updates