An Arduino Si5351a quadrature VFO controller

Front view of the VFO. The display is indicating the Receive and Transmit frequencies, the step size, and the current mode. Pushbuttons PB1, PB2 and PB3 are surface mount type soldered to a bit of circuit board material.



Here’s a full-featured VFO I built around the Si5351a synthesizer IC and an Arduino controller. I’ve written a manual describing its construction and features and I’ll excerpt bits of it below as a description. I’ll also link to the complete manual as well as the source code. It’s painfully obvious that I don’t know how to use this HTML editor, so please forgive the strange formatting changes and misaligned bits.

Nick Kennedy, WA5BDU



After getting the basic functions working I began to expand my software to add features necessary to meet my needs for a VFO to be used in a transceiver project. Those features include:


  •  A keyed line input, so the controller can swap between TX and RX frequency outputs as required as the user keys and un-keys the transmitter.
  •  A TX_Out output pin echoes the keyed line input, but doesn’t change state until the TX frequency registers have been sent, and changes back to key up before the RX frequency registers are sent.
  •   An LCD display to show the frequency I’m on, menu options and so on.
  •  A user settable CW Pitch value which is the amount that the VFO shifts between TX and RX states if in CW mode.
  •  CW/Phone mode selection which functions to enable or disable the CW offset shift when the key line is closed.
  •  LSB/USB selection. This chooses the direction of CW offset in CW mode, so the user can listen to a station on either side of zero beat. In CW it’s sometimes called NORMAL and REVERSE operation. There is also an output pin SB_Relay than can be used control a sideband select relay in the receiver.
  •  RIT control. This provides for separate TX and RX frequencies, with both displayed. The receiver can be tuned without disturbing the transmit frequency. RX and TX frequencies can be swapped and the offset can be zeroed without turning off RIT.
  •   Frequency step selection. There are both a menu for selecting from seven step sizes and a quick pushbutton selected step change between fine (10 Hz) and fast (100 Hz).
  •  Band selection with all ham bands from 3.5 to 144 MHz selectable.
  •  A Save State menu option which writes most of the current parameters into EEPROM so the VFO will start in the same state the next time it is powered on.
  •  Three miniature pushbuttons allow quick selection of often used functions while a menu controlled by the rotary encoder is used to access other functions. The pushbuttons operate with the familiar TAP and HOLD logic, giving two uses for each.
  •   A sidetone which sounds when the key is closed. A menu option can enable or defeat this function.

Details of operation

The pushbuttons offer six actions, one of which opens a menu with additional actions. A brief press of a pushbutton is called a TAP and a long press (> 0.5 second) is a HOLD operation.

There is audio feedback in the form of a short beep immediately as a switch is closed, followed by two short beeps after it has been held long enough for the HOLD function.


Above is a listing of functions accessed via the pushbuttons. I tape a copy to the top of my VFO for reference.


There’s a great deal of detail to discuss concerning use of the functions of the VFO, but I’m going to refer the interested reader to the manual and try to keep the size of this page down. I do want to tell a bit about the hardware.


Hardware requirements:
  • An Arduino board, such as a Nano or Uno

  • A Si5351a module

  • A rotary encoder

  • A standard 16×2 LCD display with Hitachi interface

  • Three N.O. pushbuttons

  • A few miscellaneous diodes, resistors capacitors and connectors

An Arduino might be $4 to $5 for a Nano or $9 or so for a Uno

A Si5351a module might be $5 or so. I like the module over the bare chip for avoiding difficult soldering and because it has a built in 3.3 V regulator and 5 to 3 volt logic level shifters for the data lines. You can power and talk to it from your 5 V Arduino.

My rotary encoder is a Bourns PEC11L-4020F-S0020 encoder with switch from Mouser.  The switch isn’t used.


Above is a schematic for the VFO.  It doesn’t show the Key Out jack, which if used connects to D10 on the Arduino. Also the USB/LSB select relay if used would be driven by A2.



Here’s a photo of the rear of the VFO. CLK0 and CLK1 are the two quadrature RF outputs.  The KEY/PTT input will cause the VFO to swap between receive and transmit frequencies, it will also generate a sidetone if desired and actuate a Key Out circuit with which to key a transmitter. 



Above is a photo of a Si5351a module connected to an Arduino UNO for testing. I think it’s impressive that with just four wires the system functions by coming up on the default frequency with quadrature outputs.



Here’s an oscilloscope trace of the two quadrature outputs. The output is about 3 Vpp open circuit and about 2.1 Vpp into 50 ohms.



A couple of variations

Some receivers have a divide-by-four logic arrangement in front of a circuit that develops I & Q signals. Since this VFO provides I & Q outputs already, there’s generally no need for an output of four times the indicated frequency. However, one friend wanted to use this VFO with his existing hardware which needed the X4 signal. So I added a flag which will cause the VFO to operate in the X4 mode. It requires editing one line in the source code. At startup, the LCD reminds you of which mode is being used.

The Si5351a can have up to three outputs. Friend #2 wanted to use that 3rd output to drive his transmitter while the other two were used for his phasing receiver.  There’s no reason you couldn’t use one of the two quadrature outputs for the transmitter, since it already jumps between TX and RX frequencies. But my friend didn’t want to risk adverse loading effects by having both a RX and a TX stage driven off the same output.  So I did another version which provides a third output on CLK2 for the transmitter. After some comedy of errors keeping it on the right frequency and making sure it didn’t QRM the receiver, I think I finally got it right.


Files you’ll want:

Links to the manual for the VFO and for the Arduino source code are given below. The manual is a PDF file. It includes information on processing the source code in the Arduino IDE and sending it to your Arduino. The file ‘si5351a_quad.ino’ is the Arduino source code, which is a plain text file.



By Nick, WA5BDU

Nick Kennedy from Arkansas - retired EE from nuclear power business. Hobbies are ham radio, electronics and programming.


    1. In the code my VFO is based on, 80 meters is a lower limit so the vco frequency doesn’t go too far below its datasheet limit. However, I’m seeing now that there’s an output divider ‘R’ that’s not being used. I’m going to see if it can put the VFO on 160.
      73, Nick

      1. I don’t believe the Divider will work with Si5351a programmed for Quadrature signal output… As an alternative, using a 12MHz crystal instead of the normal 25-27MHz crystal will get down to 160M range. But of course, it will limit the upper range…

        I’ll be very interested to see your Divider results.

        Are you using Arduino Sketches? Or Atmel Studio?
        The later, while more complex, will give you faster tighter code. There is a lot of overhead in the Arduino libraries…

        1. Yeah, I wondered if it might be necessary to change the phase offset value to keep the same 90 degree offset. I’d hope that it might be that simple, but I’m not sure yet.
          I’m using the Arduino IDE. I’ve done bare ATmega AVRs in the past with AVR studio but this is so much simpler. I’m not aware of overhead other than memory for stuff like the bootloader, but there may be some for a clock that seems to be always available.

  1. Another option to get down to 160M:
    In the Si5351 datasheet, section “5.6. Applying a Reference Clock at XTAL Input” means it’s possible to use a programmable clock in place of the 25/27 MHz Crystal.

    So as an option, you could use the “ProgRock” from QRP-Labs, have it programmed for 25/27MHz and for 12MHz, and with one i/o pin from Arduino, switch your Si5351a’s reference frequency when tuning below/above the 3.2MHz limit.

    Just a thought…

    PS. Yes, 12MHz reference xtal/clock is below the Si5351a’s datasheet specs. but I’ve heard that it does work just fine… Your mileage may vary ??

  2. Built a proof of concept version using an I2C version of the lcd, worked perfectly straight off, an interesting well documented design, thank you.
    Curious as why the and diodes for the pb3 switch when there are spare digital io ports availabole.

    73 Bob GM4CID ex VP2LI

    1. Yeah, good observation. I guess I did the diode logic thing on another project and just carried it to this one because it’s easy. But if I did away with it, it would simplify the hardware a tiny bit …
      I think I may have mentioned this in the manual.

      1. Nick,
        I did read and digest the manual, outstanding documentation, and had noticed your reference to use of the diodes.
        Must admit, I too recycle lots of my previously used sketch snippets.

  3. Hey Nick,
    Wonderful info. It gives me a nice firm place to start with my future projects.
    I will check back from time to time to see if you add anything,
    Take care es 73…
    Bob de k2ki

Leave a comment

Your email address will not be published. Required fields are marked *