Welcome
Username or Email:

Password:


Missing Code




[ ]
[ ]
Online
  • Guests: 20
  • Members: 0
  • Newest Member: omjtest
  • Most ever online: 396
    Guests: 396, Members: 0 on 12 Jan : 12:51
Members Birthdays:
All today's birthdays', congrats!
joshua_ (36)
Angstrom (37)


Next birthdays
04/08 SK1701 (26)
04/09 LarsE (40)
04/09 Ryan Arlis (35)
Contact
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.
Forums
4hv.org :: Forums :: Projects
« Previous topic | Next topic »   

Multiple Waveform Function Generator on an ARM7

1 2 
Move Thread LAN_403
Mike
Tue Jun 30 2009, 08:44AM Print
Mike 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 Link2 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 Link2 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 Link2 and Link2 .

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.
Th

Scope shot of output of sinewave at about 2khz:
Th

Sawtooth @ 2khz
Th

Triangle @ 2khz
Th

Squarewave @2 khz
Th

Sinewave @ 166 kHz
Th

Sawtooth wave @ 166 kHz (notice it becoming distorted into a sine )
Th

Sinewave @ about 300kHz:
Th

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 Link2 (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!
Back to top
GeordieBoy
Tue Jun 30 2009, 11:25AM
GeordieBoy 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.

-Richie,
Back to top
101111
Tue Jun 30 2009, 02:29PM
101111 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?..

Regards Christian

Back to top
Mike
Tue Jun 30 2009, 04:13PM
Mike 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.
Back to top
GeordieBoy
Tue Jun 30 2009, 05:03PM
GeordieBoy 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!

-Richie,
Back to top
Mike
Tue Jun 30 2009, 08:08PM
Mike 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.
Back to top
GeordieBoy
Tue Jun 30 2009, 09:03PM
GeordieBoy 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!

-Richie,
Back to top
Bjørn
Tue Jun 30 2009, 09:45PM
Bjørn 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.
Back to top
GeordieBoy
Tue Jun 30 2009, 10:38PM
GeordieBoy 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.

-Richie,
Back to top
...
Wed Jul 01 2009, 03:58PM
... 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 amazed

Great work!
Back to top
1 2 

Moderator(s): Chris Russell, Noelle, Alex, Tesladownunder, Dave Marshall, Dave Billington, Bjørn, Steve Conner, Wolfram, Kizmo, Mads Barnkob

Go to:

Powered by e107 Forum System
 
Legal Information
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.