DDS Signal Generator

[ Home ]

Some years ago I became interested in DDS after reading a document A basic tutorial on Direct Digital Synthesis (DDS)

DDS is a method of generating highly stable signals with very good frequency resolution. Unlike other types of synthesizer a DDS doesn't contain an oscillator at all other than the reference crystal oscillator. It can also generate almost any waveform. 

In essence, DDS requires nothing more than some simple arithmetic, a waveform look-up table and a D/A converter. If you are interested I have tried to explain this in a bit more detail on another page Emulated DDS principles. It struck me that all of these functions could be easily emulated by software. I tested the idea by writing a simple PC program using Visual Basic. Digital output was sent to the parallel port where it was converted to analogue with a simple R2R resistor network. This proved that the idea would work but that a multi tasking PC  was far from the ideal platform. The next step was a prototype using a PIC16F84 micro. This was better, but with my 4 MHz PIC the required arithmetic was too slow to achieve anything more than a few KHz as the upper frequency limit. from the DDS. I considered upgrading to a 20 MHz device but decided that the real problem is that the PIC hardware requires 4 clock cycles per instruction and that even a 20 MHz device would not be adequate.

A bit of web searching confirmed what I had already guessed - there is no such thing as a new idea ! I found two references to emulated DDS. Both of these are very good reading. The first is an article Mini DDS by Jesper Hansen. The second article is Micro Function Generator by Murray Greenman ZL1BPU. In both articles the DDS functions are performed by an Atmel AT90S2313 micro. This micro requires only 1 clock cycle to perform most instructions. Furthermore the basic DDS loop can be coded in far less instructions than are required for the PIC device. The remainder of this article assumes that you have visited the two links above and gained an understanding of the principles involved.

 Jesper's design has the 2313 performing the DDS function. Control of frequency is done via RS232 communication from a PC. This means that the 2313 can be dedicated to performing the fastest possible DDS loop continuously without the need to be able to perform frequency to phase increment calculations. The human interface and frequency to phase increment calculations are all performed by the PC.

I decided to take the idea one stage further and port the PC functions to a second micro so that the unit would be self contained and portable. As this project was going to be developed rather than designed, I chose a PIC16F876 for the control micro as it had ample port pins for whatever was likely to transpire. This approach also simplified Jesper's design in that the RS232 hardware could be eliminated as the AVR & PIC could perform their serial communications at 5V logic levels. Click here for the schematic of the DDS generator

You will see from the schematic that this is a stripped down version of Jesper's design. Some component values have been changed to match the contents of my junkbox. I used an 11.059 MHz crystal as per Jesper's design because I had a number of these rescued from obsolete computer boards. The crystal frequency is not critical. A change of frequency would require a small change to the AVR program to adjust the serial baud rate to 19.2Kb. The PIC program would also require a small change to amend the value of phase resolution. The PIC program is well commented to indicate where changes will be required. In practice my crystal measured 11.061 MHz and the PIC program is adjusted to this value.

The R2R digital to analogue converter is followed by a simple low pass filter. RV1 is set to match the filter impedance by viewing the output of a 100 KHz square wave on an oscilloscope and adjusting for minimum overshoot. The 2nd capacitor of the filter was formed by the capacitance of the screened cable and input capacitance of the output buffer. The output impedance of the low pass filter is quite high so some sort of buffer is required in practice. I used a power MOSFET which I had to hand together with switched and variable attenuators to give output levels of 3V, 300mV and 30mV. This has the advantage that the entire unit is powered by 5V. Click here for schematic of the output buffer.

The AVR software is almost identical to Jesper's original version. The changes which I have made were purely to make the source code compatible for assembly by Atmel AVR studio which is available free of charge. Download links for the assembly and binary files are provided below.

Click here for schematic of the PIC controller. The PIC  is clocked at 4 MHz. Speed is not an issue in this application. The PIC monitors a total of 7 miniature push switches. 5 of these change the frequency in 0.1Hz, 1Hz, 10Hz, 100Hz or 1KHz steps. The 6th switch is an up/down switch. If this is held pressed then the frequency switches decrement instead of incrementing. An audible beep provides feedback on switch action. The 7th switch is the waveform selection switch. As this switch is pressed the waveform switches between Sine, Sawtooth,  Triangle and Square wave. The frequency and waveform switches have an auto repeat action if held down. The frequency and waveform are displayed on a 2 x 16 LCD display.

Note that the frequency displayed is not measured by a frequency counter as it would be in a normal analogue generator. It is simply the contents of a binary counter incremented or decremented by the frequency switches. The PIC then calculates what phase increment the AVR will require to generate this frequency and sends this via the serial interface. The major advantage is a display resolution of 0.1 Hz without requiring a 10 second gate time.

The PIC software is written for compatibility with Microchip's MPLAB assembler MPASM. The required arithmetic for the DDS calculations is implemented in 48 bit fixed point for simplicity. The assembly code is well commented. The phase resolution corresponding to my 11.059 MHz nominal (11.061 MHz actual) crystal is stored in EEPROM and loaded from there at switch-on. This value can be modified by holding down the waveform button at switch-on. The value can then be incremented / decremented with the 1 Hz & up/down buttons. The nominal and new values are both displayed on the LCD. The new value is stored in EEPROM. The unit must be switched off and on again to use the new value.

One limiting factor of this DDS technique is that the basic DDS loop ( about 0.8uS) is still relatively long compared to dds chips clocked at 100 MHz. This means that there is a basic uncertainty of 0.8 uS in phase resolution between any 2 cycles of the waveform. In most applications this is not important and the measured frequency will be very accurate because any phase uncertainty is averaged out over the measurement period. However, when viewed on a good 'scope waveforms having fast transitions such as the square wave and sawtooth will make this phase uncertainty obvious at higher frequencies with jitter of about 8% at 100 KHz..

With the exception of this one shortcoming performance is excellent in practice. Output level is pretty well constant over the entire frequency range. Frequency accuracy and resolution are orders of magnitude better than analogue function generator chips without the requirement for expensive 10 turn pots etc. The generator wave tables can be easily modified to produce any other desired waveforms.

A picture of the finished generator

Schematic of the DDS generator

Schematic of the output buffer.

Schematic of the PIC controller.

Assembler file for AT90S2313 (dds 2313.asm 13Kb)

Binary file for AT90S2313 (dds 2313.hex 4Kb)

Assembler file for PIC16F876 (dds876.asm 37Kb)

Binary file for PIC16F876 (dds876.hex 6Kb)