AVR DDS signal generator V1.0
Sometimes when tuning various electronic hardware we need simple signal generator with various waveform and frequency. One of the options is to by a professional with variable gain professional coating and many additional functions. But if you are an amateur you might want to build one. This small project is dedicated for building one of those signal generators.

Specification
AVR DDS signal generator consists of following parts:
- Atmel Atmega8 8 bit microcontroller;
- Supply source and voltage regulator;
- 2×16 standard LCD and shift register 74HC164;
- 7 buttons;
- R-2R resistor leader for DAC;
- Three outputs: universal(OUT) from DAC, PWM and pulses;
- Metal case;
- and microcontroller firmware.
Atmega8 microcontroller is a simplest of atmega series. There is 8kb of FLASH program memory, maximum frequency is 16MHz, which is used to reach DDS generators maximum resolution at maximum frequency. For know frequency is limited from 1 to 65535Hz with minimal step of 1Hz.
DDS AVR generator is powered with 9V battery. Voltage is reduces to 5V and stabilized by 7805 voltage regulator.
LCD is controlled using three wires through shift register 74HC164. So this register is used as serial to parallel converter in order to save microcontroller pins. LCD is controlled in 8 bit mode.
AVR DDS Generator uses 7 control buttons:
-
Start;
-
Stop, which is a reset also;
-
IP- increasing value;
-
DOWN- decreasing value;
-
Mode1 – signal selection button;
-
Mode2 – signal properties;
-
Freq – signal frequency multiplier selection.
AVR DDS signal generator uses R-2R digital to analog (DAC) converter This is a simplest solution where resistors are connected in a ladder:

In this schematic R=10kohm. By using 8 bits and 5V step value is about 18.5mV. This is enough for getting average quality signals.
Generator has three outputs:
- Universal DAC output through R-2R ladder;
- PWM;
- Impulse (SQ);
Universal output (OUT) is a signal output from DAC. This output is to form various signals like sawtooth, sine, square, triangle.
PWM channel is used to form for PWM signal output – directly from timer.
SQ channel is additional channel to form square pulses or second PWM signal. Will be implemented in future.

In the block chart is described the structure of AVD DDS signal generator. You can se the signal paths. Each block part is described in specification.
Menu and program stages:
After generator is switched on the message is displayed in LCD: LCD SCREENS
„Mode2“ button selects the step of frequency from 1 to 10000Hz by pressing it in series. “Up” and “Down” buttons change the frequency value by step value.
After “Start” button is pressed - last settings are saved in EEPROM and signal generation is started.
Above functionality is implemented and tested. In a future plans there are few more signal generation modes. By pressing “Mode1” you can see following screens whish may change a little during implementation:LCD Screens1
Circuit diagram and PCB
PCB is single sided with some wiring done in top side.
Circuit diagram explanation:
Microcontroller port pins are connected to:
- R-2R DAC is connected to D port pins 0…7;
- Shift register data line is connected to C port’s 0 pin;
- Shift registers synchronize line is connected to port C pin ;
- LCD screen’s E signal is controlled by C ports pin 2;
- Start button is connected to B port pin 0;
- Stop button is reset button;
- Up button is connected to port B pin 3;
- Down button is connected to port B pin 4;
- Mode1 button is connected to C port pin 3;
- Mode2 button is connected to C port pin 4;
- Freq button is connected to C port pin 5;
- SQ signal is coming from AVR b port pin 2;
- PWM signal comes out from Port B pin 1.
Part list (exported from eagle):Parts List
Tools used
In developing this AVR DDS signal generator There were following tools used:
Software:
Hardware tools:
- Parts (Atmega8, PCB coated with photo resistive layer, box,…);
- UV exposure unit;
- PCB Etcher;
- Developer, Etching solution;
- Solder
- Programmer AVR ISP;
- Other tools…
Few words about firmware
Program is written in C language and can be compiled with WinAVR20060421 toolset. Programming is done by using AVR ISP and PonyProg programming software.
Program flow in few words:
When AVR DDS generator is switched on:
- Initialization of LCD;
- Reading previous settings from EEPROM memory and displaying to LCD;
- Using buttons settings and signals can be changed. When “Start” button is pressed, new settings are saved to EEPROM and signal generation starts.
- Note: After power up you can press “Start” to start last saved signal generation immediately;
- Generator is stopped by pressing Stop button which resets the generator. After Reset generator again loads its lasts configuration from EEPROM memory and is ready to start new generation.
EEPROM memory stores following data:EEPROM data
Mode values:
- 0 – OUT_|¯|_;
- 1 – OUT|/|/|;
- 2 – OUT|\|\|;
- 3 – OUT/\/\/\;
- 4 – OUT~~~~;
- 5 – OUT-NOISE;
- 20 – PWM-OCC;
- 21 – PWM-SINMDS;
- 22 – PWMSQSMDS;
- 23 – PWM-CMDS;
Frequency value is divided to 3 EEPROM bytes. Because max theoretical frequency is 16MHz whis hexadecimal value is 0XF42400:
|
Freq[23...16] |
Freq[16...8] |
Freq[7...0] |
Duty value is from 1 to 99 in percents.
Program Structure:
LCD_3w.h – LCD settings
LCD_3w.c it contains LCD control functions
- void sendByteToRegister(uint8_t);
- void LCDenableCommand(void);
- void LCDdisableCommand(void);
- void LCDenableData(void);
- void LCDdisableData(void);
- void LCDsendChar(uint8_t); //forms data ready to send to 74HC164
- void LCDsendCommand(uint8_t); //forms data ready to send to 74HC164
- void LCDinit(void);
- void LCDwritebyte(uint8_t, uint8_t);
- void LCDdefinechar(const uint8_t* ,uint8_t);
- void LCDclr(void);
- void LCDhome(void);
- void LCDstring(uint8_t*, uint8_t);
- void LCDGotoXY(uint8_t, uint8_t);
main.c – main program text where:
- signal tables are stored;
- messages to LCD are described
- EEPROM initialization is done;
- changing parameters are implemented;
- signal generation (using in-line ASM routines) is performed.
Testing
For now testing is done by using frequency counter and Oscilloscope. In a frequency range of 1 to 65535Hz works OK. There can be greater frequency range programmed but with less resolution. I think for audio equipment testing there is more than enough frequencies.
Discussion
As I mentioned earlier, this is a first trimmed version of AVR controlled generator. It has half of working functionality in many cases this can be enough. Main signals are generated and can be controlled. In a future the functionality can be expanded to add PWM generation using timers. Generator generates signals as they are – directly from DAC. There is no variable gain regulation. To be more interesting project there can be VGA amplifier used with feedback to control output signal voltage. The project source code is open to modify and expand functionality. If there will be some good modifications – feedback is always welcome.
You can download AVR DDS Documentation and AVR DDS Source files as they are.
More pictures from the project:
Download Eagle project files
Some software writing ideas were taken from Jespers Mini DDS.
Blogsphere: TechnoratiFeedsterBloglines
Bookmark: Del.icio.usSpurlFurlSimpyBlinkDigg
RSS feed for comments on this post | TrackBack URI for this post
New on WinAVR Tutorial
Running TX433 and RX433 RF modules with AVR microcontrollers,Sometimes in embedded design you may want to go wireless. Might be you will want to log various readi …Programming AVR ADC module with WinAVR,Most of AVR microcontrollers have Analog to Digital Converter (ADC) integrated in to chip. Such solut … |
New on WinARM Tutorial
What are differences between WinARM and WinAVR,Everyone who is working with AVR microcontrollers knows this powerful tool – WinAVR (http://win …LPC2000 watchdog timer,As in all microcontrollers watchdog timers purpose isto reset microcontroller after reasonable amount … |

September 25th, 2006 at 9:39 am
hello!
clean wave! The PWM isnt used for now?
Did you write the sine-function? When i looked at the math.h of avr, it seemed empty with only two functions implemented.
September 25th, 2006 at 12:12 pm
Now PWM isn’t implemented yet. For Sine wave and other signals I used look up tables - look at the source code.
September 25th, 2006 at 6:29 pm
It looks cool, but your DAC is too dependant on the input impedance of your test circuit. I would recomend an op-amp in a voltage follower configuration for your DAC output.
Good work!
September 25th, 2006 at 8:36 pm
Thanks.
I know that Op Amp would be great to solve this problem. This is why this generator is called simple :) In a future I will probably put variable gain operation amplifier and put some feed back to be able control voltage digitally and display it on LCD..
September 26th, 2006 at 11:36 am
Hi,
good site…but why not add a simple follower opamp?
As for the captcha, entering the number is hell on my Firefox box… . It always jumps back to the URL field…
Best regards
Tam Hanna
October 13th, 2006 at 7:14 pm
Hi, I have a problem.
I have to design a DDS Generator. I work with a avr atmega88 at 18,432 Mhz for constant time-flags i used the Timer0 but I can’t reach more than 10000 Hz with ISR overflow interrupts. In your project you use another way of time-division (asm inline). Can you explain me some tipps how it works, cause i doesn’t unterstand the source well. Thanks
October 16th, 2006 at 5:23 pm
I used 24bit phase accumulator() which determines the signal resolution of frequency. The bigger frequency I am generating the smaller resolution I get.
If you would use 18,432 Mhz crystal, then your:
Resolution=fCPU/2^24=18432000/150994944=0.1220703125
Then you can generate frequencies:
fOUT=Accumulator*Resolution;
Accumulator value is updated according to your selected frequency, what means last byte of Accumulator addresses the value form lookup table.
I don’t know if I explained well, but you can see similar project here:
Mini DDS
October 26th, 2006 at 3:59 am
Hello
Great work, I’d be interested in building this.
Could you perhaps share the eagle board file, or a high res image?
Thanks
October 26th, 2006 at 3:18 pm
I have added Eagle project files at the end of article. If you need you may modify or use for any purpose.
October 26th, 2006 at 7:20 pm
Thanks! :)
December 10th, 2006 at 11:24 pm
That’s great
but I would like to undersand this
asm volatile( “eor r18, r18 ;r18
December 11th, 2006 at 10:42 am
ASM line:
eor r18, r18means R18 XOR R18 register R18 becomes zero. refer to AVR Assembly language documentation.
December 11th, 2006 at 1:53 pm
in fact that’s all the asm code that I don’t understand.
Could you explain it here (or by mail) ?
Is it possible to do it with inline asm (only in C)
Regards
December 11th, 2006 at 1:55 pm
you should read “without asm” (instead of “with asm”)
Sorry
December 11th, 2006 at 5:05 pm
I have written blog post about this issue avr dds signal generator in-line asm explained
Might be helpful
December 12th, 2006 at 6:17 pm
Thanks a lot for the avr dds signal generator in-line asm explained
I have some suggestions
Why not using a DAC800 (very inexpensive DAC) ?
I see in you C code that you use a switch inside the loop.
That’s not a good idea as the condition (mode) is tested during each loop
a good solution for this was given to me by an opensource game creator.
Instead of using the integer variable mode you should use a pointer to function ptr_mode
You make a function for each part of your switch
void mode_0(void)
void mode_1(void)
void mode_2(void)
Instead of assigning a value to the variable mode you can assign the adress of the function &mode_0 or &mode_1 … to the function pointer ptr_mode
So in the loop there is no switch (or if) but the call of the function
ptr_mode();
which call the “good” function mode_0() mode_1() …
That’s just a trick… but I think it can be usefull in such a case
Regards
Sebastien CELLES
PS: you can contact me at
http://www.celles.net/contact
December 12th, 2006 at 8:42 pm
I have been thinking about DAC800 or other similar chips. But this project was some sort of a good practice of embedded programming while implementing DDS algorithm. Performance is as good as would be with DAC800 but it works.
Bout programming style where you suggest to use function pointers is good suggestion i think. My code is messy and require clean up and optimisation, but i think won’t stick with it as there is another project in my mind. Anyway nice to to see your interest here. Hope to stay in touch.
January 30th, 2007 at 7:05 pm
this project doesnt work for me , it will show error message after showing splashes .
pleas fix software .
January 30th, 2007 at 8:25 pm
Could you provide more details what kind of errors you get and how do you program Atmega including fuses. Do you use same circuit parts and crystal? Because other were able to duplicate it without problems.
January 31st, 2007 at 9:24 pm
the error shown when the mode is graeter than 23 . atmega an crystal work well in other projects.
i am reading your source code, the error occurwhen mode is greater than 23 , and 23 doesn’t exists in switch cases and default case show error on lcd . im trying to fix it .
—another question .
why you use inline asm for generating signals ?! when start key pressed the program goes to signal generating loop and there isn’t any stop delay , could you write your code in C ?! i can help you to expand your program but i don’t have knowledge in asm .
January 31st, 2007 at 11:57 pm
shankimout, thank you for your analysis…appreciate that.
I understand that there are some glitches with cases in program loop. You are welcome to modify the code.
About inline ASM. One reason why I have used it is to get max performance. With ASM i can get 1 signal sample per 9 MCU clocks. I am using lookup tables with 256 samples per signal period. so one signal period takes 9*256=2304 MCU clock cycles. Using inline ASM i have better control of frequency. It is not dependant on compilation optimisation and other factors. But disadvantage of it that code is tied to MCU. I would welcome effective algorithm written in C that have pretty good performance comparing to ASM.
As I have mentioned this is a first version of generator and it has many shortcomings like there is no ability to regulate Output voltage, code in some places isn’t optimal. I have thought to make second version of generator whit Op amp on exit with controlling ADC, I should fix the stopping generator without resetting MCU. Other features aren’t implemented like PWM etc.
Any additional comments and suggestions are welcome as well.
February 1st, 2007 at 1:07 am
thanx man , i fixed your firmware , it will works for me , and i added a while for up/down , now no need pressing up/down repleatly for decrease and increase frequency .
you can try , in simulator .
get it here : http://nilshare.com/file.php?file=890f961a31ac1705cc20c45f2fc6ac27
February 1st, 2007 at 2:26 am
Thanks shankimout - You are fast ;)
I am placing you fixed version locally Firmware.rar
February 6th, 2007 at 4:05 pm
My friend Scienceprog, thank you very very much for your good work!
I order the components to build one of this good generator. I’m looking for something like this for a long time ago!
You said you’ll enhance the project with an output drive circuit with indication of output level signal on the LCD display, what is really great! I’ll “follow your steps”, can’t wait the time I’ll see it on your project page.
And if you permitt my friend, I’ll add to the “wish list” of your project a “Sweep” function with programmable start/stop sweep frequencies. This will be very useful to measure the response of virtually any device! Your equipment will be superb!!! Thanks again, friend!
February 6th, 2007 at 4:53 pm
Thanks, AVR_lover
Sweep is listed in feature listing of next generator. I didn’t think about frequency limits, but this is good idea.
March 8th, 2008 at 7:16 am
Please explain to me how to make a parameter for setting timer and sinus value?
i mean how to make a sinus table?
March 10th, 2008 at 4:42 pm
[...] second and improved AVR DDS signal generator is here. First AVR DDS V1.0 generator was only an attempt of running DDS algorithm without any amplitude control. This time I [...]
March 30th, 2008 at 7:40 am
[...] to you attention the AVR DDS signal 2.0. Scienceprog.com has an article on it which links to the AVR DDS V1.0 generator as [...]
April 26th, 2008 at 11:43 pm
[...] to analog DAC converter This is a simplest solution where resistors are connected in a ladder: …http://www.scienceprog.com/avr-dds-signal-generator-v10/signal generatorsThis is one of the best analog signal generators ever made easy to use very [...]
September 1st, 2008 at 4:13 pm
Hello and nice work with your signal generator, I’m a fan of the AVR micros and actually I’m building your design on my breadboard for further test, but i have a problem trying to load the hex file in the atmega8, I have a program called bootloader installed in the flash memory that helps me to load any program trough serial to serial comm, but it says that the hex file is too large to load, actually the hex file you have is kind of big
September 2nd, 2008 at 10:47 pm
Hey I waited for a response of you people and I have nothing, truly I’m disappointed because you are giving bad data and files of this signal generator, actually the hex file you give is not for an atmega8 and second it doesn’t work, so please, upload a new working hex file for a real atmega8, not for a simulation program