It has been some time since I have posted the article on building a simple VFO/signal generator using the AD9850 module and a microcontroller, originally based on the work Richard, AD7C. I have received quite a bit of feedback from several people, along with a few requests for improvements to make the hardware more suitable for HAM radio use (my original goal was a signal generator!). So here it is, the AD9850 VFO Mk II.
The version of the VFO described in this post is based on the original design from my previous post, so you may want to read that first, especially some of the design rationale and gotchas commonly encountered with the cheap AD9850/9851 DDS modules available from eBay and elsewhere.
The main features of this version of the hardware:
- RIT/XIT offsets – allow to fine tune/offset the frequency from the one displayed by ±25kHz, in selectable steps
- TX signal input, so the micro actually knows when to apply the XIT offset
- Revised display layout, TX indication
- Revised controls – additional button for RIT/XIT, modified functions of the other buttons and the encoder.
- Output limited to 1MHz-30MHz to stay within the specs of the DDS
The person most responsible for pushing me towards making this radio-oriented version of the code is Rich Carstensen, W8VK. He is building some really nice QRP rigs with it and using it as a replacement for the classic mechanical dials.
The current version of the generator/VFO has some minor differences compared to the previous one. Namely there is an extra button added for handling the RIT/XIT offsets and there is a new /RIG-TX input signal added for RX/TX switching. The signal is active low (TX), with an internal pull-up, TTL level (either 3.3 or 5V levels, depending on Vcc). As before, the schematics shows the corresponding Arduino pin names for those using an actual Arduino board to build this.
The photo of the hardware shows 4 buttons – the left-most one is Reset, then RIT/XIT (C button), IF (B button) and Cursor mode/Zero (A button). The encoder is of a pushable type with a built-in switch. There is another button barely visible just above the RIT/XIT button – that one I am using to simulate the PTT switch for testing, the schematics shows a connector there instead where the RX/TX switching signal needs to be brought in.
There are several modes which are changed using the buttons and the encoder:
- The VFO mode – the display shows the frequency, turning the knob tunes using the pre-selected tuning step. Pressing the encoder allows to change the the step.
- “Cursor” mode – Holding down the A button (closest to the encoder) and turning the knob moves a cursor over the displayed frequency, releasing the button and turning the encoder changes the selected decade directly. Pressing the encoder knob returns back to the normal VFO tuning.
- IF mode – pressing the B button toggles IF offset on and off. This is indicated on the display by text “±IF”. Pressing both A and B together allows to program in the desired IF offset using the encoder, using the same procedure as the “cursor mode” for the main VFO frequency. Pressing the buttons together again toggles the additive or subtractive IF, pressing the encoder button will return back to the VFO mode.
- RIT mode – the C button activates the RIT mode when the /RIG-TX signal is inactive (high). Turning the encoder permits to select the desired offset, up to ±25kHz. Pressing the encoder changes the RIT tuning step, pressing the A button resets the offset to zero.
- XIT mode – the C button activates the XIT mode when the /RIG-TX signal is active (key the rig and press the C for a short moment). Turning the encoder permits to select the desired offset, up to ±25kHz. Pressing the encoder changes the tuning step, pressing the A button resets the offset to zero again. If a non-zero XIT offset is selected it will be displayed whenever the rig is keyed to help avoid transmitting on an incorrect frequency.
The settings – frequencies, offsets, IF state – are all saved in the EEPROM if no change was done for 10 seconds, so next time you will be back on the same frequency with the same settings as when you have turned the rig off.
You will need the following dependencies (the same as in the original article):
- The Bounce2 button debouncing library
- The Rotary encoder library, v 1.1
- Arduino IDE (1.6.5-r5 works)
- The VFO code itself
- Update 24.5.2017 v. 2.1 – fixed a bug for when the IF > received frequency. Now it will work correctly even for the Bitx 40 that uses 12MHz IF
- Update 6.11.2018 v. 2.2 – fixed a numeric overflow bug in the frequency setting code. Thanks to Chris W0EP!
Arduino IDE needs to be configured for the LilyPad Arduino because the circuit uses 8MHz clock unlike the original Arduino Uno and similar that use 16MHz clock.
On the first power up the EEPROM is not programmed so the display may show gibberish and the DDS will output invalid signals. It is best to start without the module connected. Then set the VFO and IF frequencies, check the RIT/XIT and reset them, if required. If the display is showing gibberish, simply keep turning the encoder knob until it hits the frequency limit (either 1MHz or 30MHz) and which point the display will reset. From that point on everything will work as expected.
An alternative solution to the above procedure is to pre-program the EEPROM as follows:
- bytes 0-3 – the main VFO frequency (32 bit signed integer), stored from the least significant byte to the most significant byte.
- bytes 4-7 – IF frequency, stored as signed 32 bit integer, stored from least to most significant byte.
- byte 8 – IF frequency polarity, 0 – subtractive IF, any other value – additive IF
- byte 9 – IF state, 0 off, any other value IF on
- bytes 10-11 – RIT offset, 16 bit integer, stored from least significant byte
- bytes 12-13 – XIT offset, 16 bit integer, stored from least significant byte
- byte 14 – selected VFO tuning step
- byte 15 – selected RIT/XIT tuning step
If in doubt, refer to the functions storeFreq() and loadFreq() in the code.
Seen in the wild
- Ben KC9DLM has sent me a link to his implementation, it seems to work great! FB, Ben!