This blog post discusses some practical implementations of super-low-cost ($30 upward) direct digital synthesis (DDS) based signal generator for home use. To save effort and time, they can all be built around an off-the-shelf microcontroller board, and an off-the-shelf direct digital synthesis (DDS) board.
There are several different ideas discussed in this blog post, and all are similar – the principles are exactly the same, just that frequency range and desired control/monitoring capabilities can be chosen to suit needs. They are all be lumped together since they are all so similar.
There is a three-minute demo of the user interface here:
What Does it Do?
This project allows for the creation of controlled sine waves, at a desired frequency. This has uses for testing radio receivers, measuring the frequency response of filters, creating a radio transmission, creating a stimulus for testing amplifiers, and so on.
Manipulations such as frequency sweeping, frequency modulation and frequency shift keying (FSK) is possible with this project.
This project relies on an external amplifier or attenuator to adjust the signal level, although some limited adjustment is possible without additional hardware.
How Does it Work?
For a more in-depth look at DDS, see the blog post here Building a Frequency Synthesiser but briefly, the DDS board constructs a sine wave digitally by sending a table of numbers to a digital to analog converter (DAC). DDS devices allow a desired frequency to be programmed using an internal register (e.g. programmed via an SPI or other I/O bus). The programmed value is fed into a summing device or counter, known as a phase accumulator. This is just responsible for repeatedly adding the programmed value to the existing sum, on each clock cycle. So, if the desired frequency is a low value then the phase accumulator will increment in low values too. If the desired frequency is higher, then the phase accumulator will increment in larger chunks The phase accumulator loops back to zero once it reaches its maximum. Each possible value that the output of the accumulator can take represents a different point on a sinewave. A look-up table is used to convert from the phase accumulator output to an amplitude on the curve of a sine wave. This then drives a DAC and and external filter.
Some of the benefits are:
- Extremely low noise close to the oscillation frequency
- High granularity (sub-Hz is possible)
- On-board RAM and instruction set allow for very fast frequency hopping or ramping (it is possible to achieve FM and FSK modulation using this method)
A disadvantage of DDS is that there can be some spurious content (usually relatively far away from the selected output frequency) that may need filtering for very demanding applications. Since filters can be expensive, often just a fixed low-pass filter is used, as in the project described here.
DDS boards are available from ebay, with a digital input interface, and an RF connector ready for providing the signal output. All that is required is to configure the DDS board to output the desired frequency, using a microcontroller for example.
For the project described here, a FRDM-KL25Z is used. It is very low cost (about $15) and easy to program using a USB cable. For more detail about the board and the programming process, see here: Working with FRDM Boards and ARM mbed
The board has 128 kbyte Flash and 16 kbyte RAM, and lots of input/output pins, on a near-credit-card-sized board around 5mm thick - it's really great!
The easiest implementation was to not have any buttons or display on the device, and just enable the USB connection on the FRDM board to become a USB Serial interface. Thus whenever the user wishes to modify the frequency output, all that needs to be done is to connect the board to a PC via USB, and run terminal software such as PuTTY on Windows or ‘screen’ on Mac or Linux. A text-based menu system becomes the user interface.
With this method, the project can be constructed for about $30 or a bit more, depending on which DDS board is used. I tried two boards; a 0-10 MHz one, and a 0.05-160 MHz board.
If a permanent display is desired, an LCD screen can be attached. It adds another $20 to the cost. If buttons are needed, they can be added too. A rotary encoder or even a keypad could also be attached. There are plenty of free pins available on the FRDM board. Although I didn’t do it for this project, for information on how to attach a keypad, see here: Building a USB Keypad: A Mini-Project
In summary there’s a lot of flexibility concerning implementation. The core functionality uses the USB Serial menu system however. Code can be added to make use of the display, and buttons/keypad/encoder. I'd also like to incorporate a USB based SCPI interface (based on jancumps SCPI project on element14) at some stage. This blog post is just to give ideas, not all combinations are implemented today so if you modify the code to implement a new combination, please do share the code.
The current code implements the text menu system, and rotary encoder for frequency selection, and display update indication of the menu selections and frequency. The plan is to extend rotary encoder usage so that it works with the menu system. So, if the text menu has the options such as sine and ramp at a particular menu level for instance, then the rotary encoder should also allow for selection of these two options before going into the next menu level in the hierarchy.
For this project I decided to develop my own menu system called picocli (I originally planned to take a Linux shell’s source code and run it Linux-kernel-less since the FRDM board has just a microcontroller). I may still revert to that, but for now I’m using custom code). It is at proof-of-concept level but functions reliably enough for now to use in this project, and it implements things like help, tab completion and a last-command history. It will be explored more in Part 2.
I also had to write a custom rotary encoder library rather than use an existing one, because I wanted to integrate things like velocity based modification of behaviour. Anyway, this was a short exercise compared to writing the menu system.
Making the Basic Configuration
The basic implementation (using a DDS board and the FRDM-KL25Z board connected to the PC for control via a USB serial interfaced menu) takes about five minutes to assemble. One or two boards are purchased and wired together with jumper cables.
For the DC to 10 MHz range, AD9834 boards are purchased. I have only tested a single AD9834 board, but two could be connected in theory if desired, for dual output, but there is no way to synchronise the two board outputs with the AD9834 chip.
For approx. 50 kHz to 160 MHz, AD9954 boards are used.
Nearly all the wiring throughout the project relied on jumper wires. To make these to custom lengths, is great. It works with the and then the result is inserted into SIL and DIL header socket shells. Standard pre-assembled jumper wires could be used too.
Here is a table of the specific wiring shown in the diagram above:
|AD9834 DDS board marking||FRDM-KL25Z board marking (conn. J9)|
|FSY (fsync)||B11 (PTB11) J9 pin 7|
|PS (phase select)||B9 (PTB9) J9 pin 3|
|SCK (clk)||E3 (PTE3) J9 pin 11|
|FS (freq select)||B10 (PTB10) J9 pin 5|
|SDA (data)||E2 (PTE2) J9 pin 9|
|RST (reset)||B8 (PTB8) J9 pin 1|
|GND (0V)||GND J9 pin 12|
|5V||5V J9 pin 10|
For using the 160 MHz boards, the connection diagram is below. Please note that I believe this diagram is correct, but I don’t have these actual boards to verify. I used some custom boards (based on the same chip) that I created a while back. However I see no reason why the ebay boards wouldn’t work.
With a bit of effort, it will be possible to have phase locked and phase adjustable outputs with these 160 MHz boards, since the AD9954 chip supports this capability. I have not tried it yet, because I’m still considering the optimal way to do that (I didn’t originally design my custom boards with that capability in mind : (
Still, there is plenty of room in the enclosure to add this capability at a future date once I’ve figured it out.
Building the Software
Instructions on how to use the development environment and how to push the compiled code into the board are described at the location mentioned earlier: Working with FRDM Boards and ARM mbed
The code can be compiled and then programmed into the board via the USB cable. The next blog post will cover the software, but if you wish to use it now (it won’t be pretty code, it still needs tidying) then please let me know.
Connect up the output of the DDS board to an oscilloscope or spectrum analyzer, plug in the USB connection into the PC and the project should power up! Open up a serial terminal and connect to the board. Hit the Enter key and a command prompt (‘$’) should appear. You can type help or ? for assistance. Generally the menu structure has been designed to accept a command, or a command followed by parameters. Some commands will drop you into a new level in the menu, and you can exit that level by typing exit.
So, to output a sinewave at 1.2 MHz, type the following to enter the sinewave mode and invoke the signal output at the desired frequency:
$ sine sine$ frequency 1.2M sine$ on
Here is another example, to generate a frequency sweep from 2.1 MHz to 2.2 MHz. Here the sweep command will drop you into the sweep mode, so type exit afterwards if you want to go into a different mode. You can type help or ? at any time to get help for the mode that you’re in:
sweep range 2.1M 2.3M on
There are extra parameters that can be configured (press ‘?’ to see the commands to do so) for adjusting the sweep steps and so on. I'd like to add a trigger output on the rear panel, so that the project can be used for basic scalar analysis of things like filters.
Adding a Display and User Controls
I decided to use an enclosure and front panel similar to what I’ve used before for this project: Building a SMT Pick-and-Place Buddy and so both projects rely on a Hammond instrument case and LCD on the front, and FRDM board stuck at the back so that the USB connector is accessible. The two signal outputs will also be at the back (using SMA connectors) because the front panel ended up becoming too full. It's not very convenient, but I can live with it.
This time I used a parallel mode LCD which is more inconvenient to use than the I2C displays, but I wanted to use it for the high quality output. The display uses ‘VATN’ LCD technology, which looks very close to Organic LED (OLED) in terms of contrast, when viewed at the right angle. So, it has near-OLED looks, but with LCD display lifetime, which seemed ideal for a test instrument. For the user input, I used a rotary encoder. An optical encoder with no detents is quite good for setting frequency, because it can be rapidly spun for getting from one end of the spectrum to the other in a short time. I used a Marquardt switch too. These almost feel like a keyboard switch, so they are light to press.
The Hammond case comes with aluminium plates, but plastic is easier to machine so I replaced the front panel with a black ABS plastic sheet instead, and cut a few other bits of plastic to hold the switch and rotary encoder at a convenient depth. A 3D printer could be used to make these, although I did it manually with sheet plastic.
After lots of epoxying, the front panel was semi-complete.
Sanding parts makes them easier to epoxy together. Thread-lock glue was used to hold some of the screwed bits together.
The particular rotary encoder I had operated at 5V whereas the FRDM-KL25Z board has 3.3V logic inputs, so a couple of potential divider resistor pairs were used on the quadrature encoder output lines, to drop from 5V to 3.3V (I used 1.8k and 3.3k resistors); the resistors can be seen attached to the header socket that will be connected to the rotary encoder in the photo below.
The LCD screen was a couple of millimetres taller than the inside of the case! : ( so I had to cut a shallow groove in the top and bottom of the case, to accommodate it. A piece of wood was glued to hold the display in the correct position. Jumper cables were used everywhere in case things ever need disassembly.
The performance is quite good, but that’s to be expected from DDS technology.
Here is what it looks like on an oscilloscope, using the AD9834 board; the output extends down to DC incidentally, because there is no output capacitor on the board.
The AD9954 board provides for up to 160 MHz output although at the low end it is limited; much lower than 50 kHz results in reduced amplitude, because my board has a transformer on the output. The ebay versions do not have this according to the photos on ebay, so they should extend down to DC.
It is hard to tell how good or bad a signal is from the ‘scope trace, so the FPC1500 spectrum analyzer was used. A span of 2MHz was examined when the DDS was set to 9.55MHz, and also 134MHz in the case of the AD9954. The result was good. The close-in noise is almost entirely due to the crystal oscillator module. The module on the AD9954 board for example contains an internal phase locked loop (PLL) to generate a 100MHz clock. Another PLL inside the AD9954 multiplies this by 4 to generate a 400MHz internal clock. I have a 400MHz oscillator module (which still uses a PLL) that I may try at some point; it has worse jitter than the 100MHz module, but it means that I can then disable the PLL inside the AD9954. Or I could try to source a better module, but it could get expensive.
The AD9834 board uses a similar style of oscillator module, with a PLL inside it too I suspect.
To see how this compared with a commercial signal generator, I connected a Rigol DG1022Z to the FPC1500. The DG1022Z has a 14-bit DAC internally, as does the AD9954 DDS chip.
The result is fairly similar when set to approximately the same power level. At higher output level this situation can change! - see the second spectrum trace below.
The DG1022Z operates to 25MHz, and I only tested at 10MHz. The AD9954 can go to 160MHz. Of course the DG1022Z is more flexible since it has arbitrary waveform capability too, but if just a sine wave and a few frequency modulation based schemes are required, then the AD9834 or AD9954 are great options.
A simple design has been presented to create a fairly usable signal generator. It costs less than $30 and perhaps half an hour of time to build and program it all. The full enclosure version takes longer of course.
It could be extended with an amplifier circuit if desired. If you build this project as-is or extend or modify it, it would be great to hear about it to bounce off ideas.