If you need assistance, please send an email to forum at 4hv dot org. To ensure your email is not marked as spam, please include the phrase "4hv help" in the subject line. You can also find assistance via IRC, at irc.shadowworld.net, room #hvcomm.
Support 4hv.org!
Donate:
4hv.org is hosted on a dedicated server. Unfortunately, this server costs and we rely on the help of site members to keep 4hv.org running. Please consider donating. We will place your name on the thanks list and you'll be helping to keep 4hv.org alive and free for everyone. Members whose names appear in red bold have donated recently. Green bold denotes those who have recently donated to keep the server carbon neutral.
Special Thanks To:
Aaron Holmes
Aaron Wheeler
Adam Horden
Alan Scrimgeour
Andre
Andrew Haynes
Anonymous000
asabase
Austin Weil
barney
Barry
Bert Hickman
Bill Kukowski
Blitzorn
Brandon Paradelas
Bruce Bowling
BubeeMike
Byong Park
Cesiumsponge
Chris F.
Chris Hooper
Corey Worthington
Derek Woodroffe
Dalus
Dan Strother
Daniel Davis
Daniel Uhrenholt
datasheetarchive
Dave Billington
Dave Marshall
David F.
Dennis Rogers
drelectrix
Dr. John Gudenas
Dr. Spark
E.TexasTesla
eastvoltresearch
Eirik Taylor
Erik Dyakov
Erlend^SE
Finn Hammer
Firebug24k
GalliumMan
Gary Peterson
George Slade
GhostNull
Gordon Mcknight
Graham Armitage
Grant
GreySoul
Henry H
IamSmooth
In memory of Leo Powning
Jacob Cash
James Howells
James Pawson
Jeff Greenfield
Jeff Thomas
Jesse Frost
Jim Mitchell
jlr134
Joe Mastroianni
John Forcina
John Oberg
John Willcutt
Jon Newcomb
klugesmith
Leslie Wright
Lutz Hoffman
Mads Barnkob
Martin King
Mats Karlsson
Matt Gibson
Matthew Guidry
mbd
Michael D'Angelo
Mikkel
mileswaldron
mister_rf
Neil Foster
Nick de Smith
Nick Soroka
nicklenorp
Nik
Norman Stanley
Patrick Coleman
Paul Brodie
Paul Jordan
Paul Montgomery
Ped
Peter Krogen
Peter Terren
PhilGood
Richard Feldman
Robert Bush
Royce Bailey
Scott Fusare
Scott Newman
smiffy
Stella
Steven Busic
Steve Conner
Steve Jones
Steve Ward
Sulaiman
Thomas Coyle
Thomas A. Wallace
Thomas W
Timo
Torch
Ulf Jonsson
vasil
Vaxian
vladi mazzilli
wastehl
Weston
William Kim
William N.
William Stehl
Wesley Venis
The aforementioned have contributed financially to the continuing triumph of 4hv.org. They are deserving of my most heartfelt thanks.
Registered Member #58
Joined: Thu Feb 09 2006, 05:40AM
Location: Tri-Cities, Washington, US
Posts: 317
For my final physics engineering course I had to do a project and one I had been interested in a while is signal generators so I decided to code a Direct Digital Synthesis Generator.
Originally I had planned on using something like an AVR but Bjorn turned me to ARM processors. He also pointed me towards a cheap and very cool dev board that I decided to use. It can be had for just $25 from futurlec The board uses the ARM 2103 processor which can be run up to 58Mhz (using 3x pll multiplier) and includes an onboard analog to digital converter and 32k flash memory.
As for the digital to analog converter I used, I decided to go with the simple but effective R-2R ladder setup that uses repetitive values of resistors that give the most significant and least significant bit the greatest and least control over the outputted amplitude respectively. More info on R-2R ladders can be found and .
The coding itself was difficult for me since I only really had experience in C# visual (which isn't much experience at all heh) and I was now coding this in C via Keil uVision3. Thankfully I had much help from Bjorn in all my questions and also the ARM2103 data sheet that explains all the registers and values.
The first processes I had to setup were Waveform selection and Frequency selection. The waveform selection was accomplished by using a loop to wait for a keypress on one of the GPIO pins, and then a series of if, else statements to have the pointer *Waveform point to a specific wave table. There are 4 wavetables, (sine, square, triangle, sawtooth) and each consist of 256 8bit values. For instance a square wave table of 2 values might look like 0x00, 0xFF , where 0x00 means pins 0 thru 7 are low (off) and 0xFF means pins 0 thru 7 are high (on). The wavetables can be seen in the code later on.
Once the waveform was selected, the next task was to select the frequency. Originally I had planned on using an up and down button, but I decided this to be too difficult since I would need to create a complex algorithm to increase/decrease the rate at which the frequency was changed otherwise it would take a very long time to go through all the possible list of frequencies. Instead I decided to use 2 potentiometers, each wired to a GPIO pin from 3.3v (Reference) as a voltage divider. This is where the onboard 8bit A/D converter comes in and allows the potentiometers to be used for frequency selection. One of the potentiometers is a coarse selection and the other is the fine selection. This is accomplished in the code by using a while loop that will perform the a/d conversion and update the Frequency variable and LCD screen with the frequency value until a button push is received indicating the frequency has been selected. This method works fairly well but is a little inaccurate because the GPIO pins are so sensitive.
Finally the main part of the code that actually generates the waveform just uses an infinite loop where the value in the waveform table pointed to by the pointer given by the accumulator variable is outputted to the FastIO pins, and then the accumulator is incremented. I decided to not use a hardware interrupt or another piece of code to check for user input to see if they want to change the frequency since that would slow down the loop. Instead the user can just push reset on the devboard to reselect the function and frequency.
I used very precise (0.1%) resistors of values 10k and 20k for the r-2r ladder in hopers of making it as accurate as possible. The overall output of the generator is looking nice, right now it only goes to about 300kHz because I have completely unoptimized code since the LCD code uses outdated methods I need to fix. Also I will probably be adding a lowpass filter to help the sinewave a bit and an amplitude adjustment chip (LM358N) I may also have to use a sine to squarewave converter to get higher frequency squarewaves or I could use a direct output from the devboard bypassing the D/A converter... I'm not sure which I will be doing yet.
Anyways, here are some pictures of it in action (excuse the mess of wires, this was just a test setup): First is a pic of the whole setup with LCD on right, arm dev board in middle, D/A converter on bottom right, and board holding buttons/potentiometers on left.
Scope shot of output of sinewave at about 2khz:
Sawtooth @ 2khz
Triangle @ 2khz
Squarewave @2 khz
Sinewave @ 166 kHz
Sawtooth wave @ 166 kHz (notice it becoming distorted into a sine )
Sinewave @ about 300kHz:
As you can see the results are quite nice up to a certain point, however most waveforms start degrading into the shape of a sinewave at very high frequencies. The results should increase quite a bit once I optimize my code because right now I am not getting a good amount of resolution (meaning that the pointer has to skip a lot of values in the wave table resulting in a poor approximation). Also a filter will help a great deal as well.
I also posted the source code in full here (ignore the stupid and sometimes incorrect comments in the code hehe)
Anyways thats about all i've got to share right now, if you have any questions or suggestions i'd love to hear them! Again thanks to Bjorn for a lot of help too!
Registered Member #1232
Joined: Wed Jan 16 2008, 10:53PM
Location: Doon tha Toon!
Posts: 881
Nice project, and well documented. Software DDS implementations are cool for low frequency usage like Audio Frequency testing.
You really need a reconstruction filter (also known as "anti-imaging filter") after the DAC though. In the time domain this filter smooths out the steps of the discrete time output from the DAC. In the frequency domain you can think of it removing all the unwanted high frequency images created by the discrete time sampling process.
If you haven't done so already, take a look at Analog Devices' DDS datasheets. They cover the theory well and you can get a good idea of what spec they achieve with particularly sample clock rates and filters.
A good starting point is to allow your generator to generate outputs up to one third of the sample rate. Design the filter to have it's passband from 0 to Fs/3, it's transition band from Fs/3 to 2Fs/3 and it's stopband from 2Fs/3 upwards. This is a good compromise between achieving a wide useful frequency range for the generator, and the filter design not being too complicated.
FWIW, I have just designed a DDS built around AD's AD9834 device clocked at 24MHz. The output frequency range is DC to 8MHz, and all harmonics/spurii are at least 60dB down. It used a 5th order elliptic lowpass filter to kill off all of the frequencies above 8MHz very agressively.
Registered Member #575
Joined: Sun Mar 11 2007, 04:00AM
Location: Norway
Posts: 263
GeordieBoy wrote ...
I have just designed a DDS built around AD's AD9834 device clocked at 24MHz. The output frequency range is DC to 8MHz, and all harmonics/spurii are at least 60dB down. It used a 5th order elliptic lowpass filter to kill off all of the frequencies above 8MHz very agressively.
That sounds very interesting, if it isn't confidential, maybe present it and code/schematics in a project thread about it?..
Registered Member #58
Joined: Thu Feb 09 2006, 05:40AM
Location: Tri-Cities, Washington, US
Posts: 317
GeordieBoy, thanks for the comments, I will definitely take your advice on designing that filter. Also I did actually get a chance to see AD's DDS sheets, they are very informative, I haven't had a chance to read the whole thing but there is a lot of great info in them for sure.
Registered Member #1232
Joined: Wed Jan 16 2008, 10:53PM
Location: Doon tha Toon!
Posts: 881
Christian,
Unfortunately it is for a commercial design so I won't be publishing the schematic or software. All the information is in the DDS device datasheet though, and there are umpteem examples of DIY DDS projects on the internet.
The thing that is perhaps the most tricky to do is design a decent reconstruction filter to clean up the "lumpy" sampled output from the DAC. This is where a bit of engineering know-how and something like MATLAB comes in handy.
Also the requirements for my application where very specific and almost certainly wouldn't match someone else's spec.
I can summarise that it used a PIC to control AD9834 over SPI, a balanced 5th order elliptic lowpass filter after the DDS, and a high-speed current-feedback op-amp from TI's THS3xxx range to amplify the output up to a decent level for the application.
The best datasheet to look at for reconstruction filters is AD9850 datasheet. Page 17 shows the filter towards the top right corner of the schematic. Even if you don't know how these component values are calculated, you can pinch their filter schematic and modify it to suit your needs. Scaling all of the inductor and capacitor values by a value x, modifies the cutoff frequency of the filter by 1/x without changing its impedance. Likewise multiplying all the inductor values by y and dividing the capacitor values by y, causes the characteristic impedance to be modified by the factor y.
Therefore you can pretty much pinch their design and modify it to suit your own specific spec requirements.
If you really need to change the actual shape of the filter, however, then you have to crack open the maths textbooks and learn about chebychev polynomials etc!
Registered Member #58
Joined: Thu Feb 09 2006, 05:40AM
Location: Tri-Cities, Washington, US
Posts: 317
Richie, you know I think I actually looked at using one of those AD9834 chips but decided against mainly because it was made specifically for DDS and I felt I might learn more if I used a more general chip. Obviously your way was more complex and accurate but a software implementation helped me with learning the code and also becoming a bit more familiar with ARM's. In the future if I was to create a more robust DDS I would definitely take a look at those AD chips again though.
Registered Member #1232
Joined: Wed Jan 16 2008, 10:53PM
Location: Doon tha Toon!
Posts: 881
Yeah, it is true that you learn a lot by programming the DDS algorithm yourself in software. If your microcontroller or DSP has hardware multiply support it's also fairly easy to generate most of the common waveforms without needing any lookup tables.
For example:
1. Rising sawtooth is achieved by mapping the phase accumulator directly to the DAC output level,
2. Falling sawtooth is achieved by inverting the phase accumulator and mapping that to the DAC output level,
3. Triangle is achieved by rectifying the sawtooth wave. (Essentially you compare each value with the half-way value, and if it's greater you flip the sign.) This changes a sawtooth waveform into a triangle, by "full-wave rectification" in software!
4. Squarewave is achieved by testing the Most Significant Bit of the phase accumulator and mapping the result of that to the DAC output level,
5. Pulse trains are generated by comparing the phase accumulated with various "duty ratio" constants, and setting the DAC output low or high according to the result of the comparison.
6. Sinewave can be achieved by using a sigmoid shaped curve to waveshape the triangle waveform into a sinewave. The curve y = (1.5x - 0.5x²) is fairly close and easy to implement with one multiply, two binary shifts and one subtract!
Registered Member #27
Joined: Fri Feb 03 2006, 02:20AM
Location: Hyperborea
Posts: 2058
On this microcontroller the maximum sample rate is 6.5 MHz without unrolling the loop when using a look up table. Unrolling the loop will increase it to 9.8 MHz but will introduce some spurious frequencies that may or may not be a problem. On microcontrollers like this the FLASH memory is usually the bottleneck and you will probably be able to do 11 MHz (16 MHz unrolled) if overclocked and the code is run from SRAM.
By not using the look up table there are some improvements for simple waveforms, 9.8 Mhz (19.6 MHz) sample rate is possible for rising sawtooth. No improvement for sinewave is possible even with single cycle multiplication since table look up is fast in internal SRAM.
Registered Member #1232
Joined: Wed Jan 16 2008, 10:53PM
Location: Doon tha Toon!
Posts: 881
Table lookups are of course limited to the number of entries in the lookup table. This causes the resulting waveform to be heavily quantised in both amplitude and phase.
Whereas calculating waveforms directly from the phase accumulator can preserve the full resolution of the phase accumulator if done properly. So if you have a 16-bit phase accumulator you can output a 65536 point sinewave without requiring a 65536 point lookup table, or having to result to interpolated lookups.
Registered Member #56
Joined: Thu Feb 09 2006, 05:02AM
Location: Southern Califorina, USA
Posts: 2445
This looks like a very nice project to have on your bench even with the current limitations. I have wanted to try a project that had a high speed d/a (or even a simple r2r ladder) hooked directly to some ram, and use a simple binary counter to step through the steps in a sine wave. A slow microprocessor (pic/avr) could be used to load programs into the ram and a if a fast chip (pic18 series goes to 48MHZ) was used a timer pin or simple loop could be used to generate the clock pulse to run the counter.
Your solution is certinly cleaner, and it looks like it can be made quite cheeply
This site is powered by e107, which is released under the GNU GPL License. All work on this site, except where otherwise noted, is licensed under a Creative Commons Attribution-ShareAlike 2.5 License. By submitting any information to this site, you agree that anything submitted will be so licensed. Please read our Disclaimer and Policies page for information on your rights and responsibilities regarding this site.