Occasionally we need a Variable Frequency Oscillator (VFO) for some new home-brew project. Whether it be a transmitter, transceiver, receiver, or even as a tunable signal generator. With modern micro controllers available installed on breakout boards like the Arduino, and synthesizers likewise available (as with the AD9850 and Si5351) we can have crystal-control stability and wide frequency range available at unbelievably low prices. Tune fast and accurately, even down to the single Hz! Ease of programming is achieved through the Arduino programming methods so that we can tailor the application to satisfy our every need and whim.

There are several delightfully inexpensive displays available that connect with a bare minimum of wiring. These use what is called I2C ( or IIC ) protocol, an abbreviation for “ Inter-Integrated Circuit “. Just 4 wires are used to connect from the Arduino board to the display: Two for power ( +5 volts and ground return) and two for communication (clock and data). These displays will allow the user to read the frequency of the VFO and still have ample room to monitor additional functions, too.

All three modules, the Nano, the synthesizer, and the display, use 5 volt power. Even when there is a 5 volt source already available in a project, I find it expedient to locate a dedicated 5 volt regulator where individual portions are separated by more than a few inches. The TO-220 packaged 7805 regulators are dirt cheap and plentiful. Keeping the regulator in close proximity helps maintain a steady and clean power supply.

Agile Tuning

I chose a rotary encoder to control this project. They are small, reliable, and inexpensive. Two sets of switch contacts are used to determine which way the shaft is turned and how far. The sequences and counts of closure are gathered in the Arduino by using external interrupts, thus reducing delays. An additional set of switch contacts are activated by pressing the spring loaded shaft. These are used to facilitate a rapid and logical tuning method. De-bouncing is performed in the software and the Arduino provides pull-up voltages so no additional components are required.

To tune at a rate other than 1 KHz per step, just push in the tuning knob and turn, while holding it in, to move the cursor under another digit. Want to tune in MHz steps? Just move the cursor left until it's under that digit, release, and tune. Even single Hz steps! Dial up the exact frequency in seconds.

Although the AD9850 produces a clean and stable output the levels at high frequencies can be a bit low for some applications. At 50 MHz it is only .27 volts peak-to-peak into 50 ohms for sine wave. Fine for a signal generator but as a VFO replacement or a driver for a double-balanced mixer then you will need to add a stage of amplification to the output. That single stage amplifier is left to you since the design will depend on the application.



Download the PDF here.

The most basic software simply displays the frequency in Hertz, no commas, no decimal points, just the cursor position indicating which digit is to be incremented or decremented. It begins on whichever starting frequency is programmed into the “FQ” variable (in this case 7.2 MHz). You can set this to a favorite frequency, of course, anywhere between 1 MHz and 50 MHz.

The other value that needs to be set by the user is the frequency of the reference oscillator on the synthesizer board. Ostensibly it is 125 MHz but the accuracy of your frequency generation depends upon how closely you measure it. Here’s how:

Change the value of the “float ref” variable to 125000000. Then start the VFO and program it for 12.500000 (that is a tenth of the supposed reference oscillator frequency). Now use a frequency counter or a well-calibrated receiver to measure the actual VFO output. This is one tenth of the actual reference value. So multiply this measurement by ten and enter that as your new “float ref” value. The output of the VFO should now be as accurate as your measurement permits.

You will see that my reference crystal measured 124997180, which is 2.82 KHz lower than what was marked (125 MHz). This is common. Left unchanged, it would have made my VFO frequencies all about .0000226% low. Not bad, but why not make it better?

With everything all calibrated, let’s look at the program operation. The display is enabled and the “splash screen” is displayed for a couple seconds. This is to show you what version of software is loaded on the Arduino. Without it you need to remember or guess.

Next the main operating program begins by calculating where the cursor is to be placed. We normally start out at the KiloHertz position, meaning that if we turn the knob one click in the clockwise direction then the frequency will increase 1 KHz. Counter-clockwise will decrease frequency one KiloHertz each click. Great for tuning around looking for activity.

The cursor position is computed by subtracting the number of digits in the tuning increment from the number of digits in the frequency. To change the tuning increment (you might call it tuning rate) you press the tuning knob until you feel it click and then rotate it to place the cursor at the new digit place. Release it to begin tuning. Easy and intuitive. Tune to the individual Hz anywhere from 1 MHz to 50 MHz in mere seconds.

To keep from constantly updating the display and needlessly re-programming the synthesizer, the program only does these things if it detects a change. The Arduino controller spends most of its time just checking for an input.


Download the PDF here.

Counting zeros becomes annoying when we deal with big numbers and eight digit frequency displays certainly qualify as “big numbers”. It does make tuning easier if we break the number into 3-digit groups. Instead of “21056000” we can display the same number as “21.056.000” and we can read at a glance. This takes some more complex manipulations since we need to compensate for those decimal places in our cursor control and display.

I encountered a few software glitches in the math routines. One would expect that with such limited hardware. For each of these ambiguities I had to devise a “patch”, which is a sloppy method to correct the problem using small bits of code. Inelegant but efficacious! I think that I found most of them but please let me know if you catch one that I missed.


Download the PDF here.

For those that have limited panel space and cannot use the big LCD display, the little OLED display is a versatile alternative. It uses the same IIC wiring but a different address. That’s a good thing, actually. You can use an LCD and the OLED at the same time! Cost is about the same as the LCD and it draws nearly the same amount of power. With the two font sizes available you can put up to four lines of text. I find that the large text works just right on the top line and then there is ample room for two more lines of the small sized characters available on the lower half of the screen.

It took me just an hour to move the previous sketch (EZvfo.ino) into this one. Little has changed except the display code.

This would be ideal for your next Pocket Portable!

Putting it to use

As for now, this circuit can be installed in a small case and used as a signal generator or a VFO for a transmitter if no frequency conversions are necessary. It can also be used as the oscillator in a direct-conversion receiver. If it is to be used in a frequency-conversion application then you need to incorporate that into the sketch. It is simple since we just add or subtract the difference from the number to be displayed. I can do this if someone needs.

Hopefully you can, at least, pull portions of this code for your own projects. I have tried to keep it small and simple, something to build on. Suggestions are always appreciated.

de ND6T

Return to Home