Introduction: 10 Resistor Arduino Waveform Generator

Picture of 10 Resistor Arduino Waveform Generator

If you have an Arduino UNO this project is practically free!

It also makes a great Arduino Nano project.

What you need (only passive components):

  1. Just 10 Resistors
  2. One filter capacitor

What you get:

  1. A Direct Digital Synthesis (DDS) Waveform Generator
  2. True 50 kHz Sin-Wave capability
  3. Sin, Triangle, Ramp Up ,Ramp Down outputs
  4. And Arbitrary Waveform Generation (AWG)


  1. 50 kHz seen on an Analog Oscilloscope
  2. Arbitrary waveform created using a sum of f and 2f
  3. The arbitrary waveform spectrum
  4. An a compact version implemented using an Arduino Nano

Step 1: Breadboard and Circuit Schematic

Picture of Breadboard and Circuit Schematic

The circuit implements a 6-Bit Digital to Analog Converter (DAC) using a 8-4-2-1 Resistor combination.

Arduino Uno Output pins 13 to 9 form the 6-Bits PB5 to PB0.

The Ideal resistors for the 8-4-2-1 network should have been:

1.1 K, 2.2 K, 4.4 K, 8.8 K, 17.6 K and 35. 2 K

However this has been simplified to

1.0 K, 2.2 K, 2.2 K + 2.2 K, 8.2 K + 560, 15 K + 2.7 K and 33 K + 2.2 K

The first 1.0 K instead of 1.1 K has been used to take care of the loading on the PB5 output.

A 0.01 uF filter capacitor is added to the resistor DAC output for smoothing the waveforms.

Step 2: Something for Nerds

Picture of Something for Nerds

A basic DDS waveform generator needs a phase_accumulator to be incremented by a phase_step at a frequency f_clock.

Earlier Waveform Generators using the Arduino Uno have implemented DDS generators with a f_clock frequency based on a timer interrupt at 100 kHz. This limits the practically usable DDS waveform output frequency to f_clock /8 or waveforms to 12.5 kHz.

The current approach attempts to maximize the f_clock. By implementing the DDS loop using a while function wherein a minimum number of instructions cycles are utilized.

Exit from the while loop is based on a variable updated based on the USART Rx interrupt

The current while loop takes 43 cycles and the f_clock would be 16 MHz/43 = 372.09 kHz

The best we could have done if the Arduino Uno exit from while was based on a Reset would have been 40 instructions or 400 kHz.

f_clock/8 is 372 kHz/8 = 46.5 kHz which is practically 50 kHz!

The code is implemented in ' c' using Atmel Studio 6.0

The c-code implements a 24-Bit phase_accumulator of which the higher order 7-Bits are used as an address to a 128 step waveform table containing 6-Bit waveform data with values from 0x00 to 0x1F Hex.

Use the 007DDS.Hex to program the Arduino Uno using Avrdude.

Step 3: Perf-board Circuit & Connections

Picture of Perf-board  Circuit & Connections

The 10-Resistor circuit is wired on a standard perf-board in such a way that the PB5-PB0 terminals are on one side and two ground pins are on the opposite side. All pins match with the Arduino Uno output connectors.

Additional socket pins are soldered for the output connections.

  • Sq Output Reference
  • DDS Waveform Out
  • Gnd

The connections are shown clearly in the figure.

Step 4: Operating the Waveform Generator

Picture of Operating the Waveform Generator

Connect the perf-board 10 Resistor network to the Arduino Uno.

Connect the Arduino Uno to a PC USB port.

Open up the Windows based GUI program attached.

The GUI program is easy to use:

  1. It permits selection of the virtual com port
  2. (Try a second time if the port is not connected the first time)
  3. Setting the output frequency
  4. Selecting the waveform type
  5. And running the program

In the special case of the DDS_Arb (0-50kHz) arbitrary waveform selection

  1. The open file dialog looks for a .csv file which defines the arbitrary waveform
  2. Once this is selected the waveform points are automatically uploaded
  3. Run the arbitrary waveform at the frequency value selected.
  4. Once loaded the waveform points remain in memory and if the same waveform need to be re-run we can cancel .csv selection.

The third figure is a typical screen-capture showing combined GUI of the Aj_SignalGen and my earlier "USB Oscilloscope in a Matchbox " which has been used for capturing all the wave-forms in this Instructable.

To install the Windows GUI:

  1. Extract the Windows GUI.rar to a suitable location on the PC to be used
  2. Run the .exe file
  3. That's it!

The Windows GUI needs .Net 2.0 and has been tested on Win XP and Win 8.1

Step 5: Amplitude Control

Picture of Amplitude Control

Output waveforms swing from 0 V to a maximum value corresponding to the 5 V supply voltage. In many applications it may be necessary to reduce the amplitude and generate waveforms which have a positive to negative swing.

This is accomplished using a external circuit where the DDS Generator output is capacitively coupled to a trimmer potentiometer and the final output taken from the potentiometer wiper point.

Considering that the 8-4-2-1 DAC has an output impedance less than 1 kilo-Ohm a potentiometer of 5 kilo-Ohm is chosen. The coupling capacitor needs to be changed depending on the frequency being used for test.

The figures show the bread-board implementation and the circuit schematic.

A 1 kHz 2V p-p waveform is shown as an example.

Step 6: Typical Sin, Triangle and Ramp Waveforms

Picture of Typical Sin, Triangle and Ramp Waveforms

Figures show a 25 kHz Sin, 10 kHz Triangle and two 1 kHz Ramp waveforms.

Because of the limitation of my DIY Oscilloscope the 50 kHz Sin waveform as seen on an analog oscilloscope is shown at step-1.

Step 7: Arbitrary Waveforms

Picture of Arbitrary Waveforms

Arbitrary waveform data should be created as a .csv file containing one column of data with length 128. The data values should be in decimal whole numbers in the range 0 to 63.

These values when loaded to the Arduino Uno are converted to Hex values between 0x00 and 0x1F and output as arbitrary waveforms.

Three typical waveforms with their corresponding .csv files are provided as examples.

Step 8: Implementation on the Arduino Nano

Picture of Implementation on the Arduino Nano

A small two layer pcb has been created using EAGLE CAD software.

The Eagle files are attached.

Unfortunately the output bits of Port_B got reversed as compared to the circuit implemented on the Arduino UNO.

This reversal in hardware is taken care by reversing the bits in software before the data is output.

This requires a changed Hex file.

008_DDS.hex to be programmed on the Arduino Nano.

The Windows GUI program remains unchanged.


kalymnos (author)2017-12-10

I'm testing it with your version of the linux program, available on your other project,

and using arduino for compilation, everything worked perfectly.

P.S. I tested the compilation of DDS with arduino, and I have an error on

get_switch(uint8_t duty){

AhmedS419 (author)2016-11-04

what is i dont want to use the GUI software and i want make its function executed by hardware?

ajoyraman (author)AhmedS4192017-06-09

Thanks for your comments. I have now implemented a stand-alone mode / USB PC GUI dual mode project.

ajoyraman (author)AhmedS4192016-11-05

Good idea ! Rig up a PC1602 16X2 LCD display and increment/decrement the frequency to be set using two switches. Another switch could select the waveform type. The calculation for phase step corresponding to the frequency is currently done in the VB program this needs to be done on the Arduino. Everything should be good except the arbitrary function may not be possible. Could you work on this and share?

BeenThereD (author)ajoyraman2017-02-10

Im not much of a programmer, but i love the simplicity of the hardware. I might be able to add a display and controls. I'd want to use I2C and a rotary encoder. I cant make any promises i cant keep, except if i do come up with anything, I'll post it here.

ajoyraman (author)BeenThereD2017-02-10

Also consider an option using thumb-wheel switches.

BeenThereD (author)ajoyraman2017-02-10

I do like that idea. I'll have to look around to see whats available these days. That would add a nostalgic look to it, and make it easy to change frequency. Electricaly, I think it will require one output per digit and 5 inputs if i multiplex. Ill have to do an I/O count to see if an Arduino has enough.

ajoyraman (author)BeenThereD2017-06-09

Thanks for your comments. I have now implemented a stand-alone mode / USB PC GUI dual mode project.

ajoyraman (author)BeenThereD2017-02-11

Check out this link: . If you use a BCD switch then only 10 combinations need to be decoded. As we use ADCs the number of pins should be sufficient. Plan for frequencies up-to 19999 Hz. 4 BCD switches and the other digital pins can be used for selection 0/1 for the 10 Thousands, Sin/Triangle and to initiate the setup frequency.

afnca made it! (author)2017-01-25

works great :)

DanC241 (author)2016-10-20

Hi, I'm having a problem with the signal generating software. Every time I go to select a COM port it keeps timing out. I was wondering has anyone else encountered this problem and if so what do I do

ajoyraman (author)DanC2412016-10-20

Pl check through device manager that the driver is installed correctly and what com port the Arduino is connected to. Try to connect to this port. Sometimes I find it connects only on the second attempt. Which version of windows are you on? Do normal sketch uploads work with your setup?

DanC241 (author)ajoyraman2016-10-21

I'm running on windows 10 and this is the first sketch I've tried as I'm new to Arduino. I made sure the drivers were up to date and that the arduino is connected to the right port and it still isn't working is there anything else I can try to fix it? Thanks

ajoyraman (author)DanC2412016-10-21

Sorry, I have checked the GUI only on Win 7 and Xp. However if the GUI opens it should work. I suggest you check the Arduino system by confirming that the 'Blinking-LED' sketch works. Then load the file I have provide or the alternative compiled by ThomasK19 and confirm the loading is OK. Close the Arduino IDE as it may still hold on to the com port. Then try the GUI I have provided. Meanwhile, I will try to check on Win 8.1 and Win 10 if possible. Feedback on Win 10 usage from other members is welcome.

Murray Locksmith (author)2016-03-03

great sound quality!

ThomasK19 (author)2016-02-22

I guess you can convert it for the Arduino IDE by renaming main to setup and drawing the while(1) loop out into the loop routine.

Very nice write-up. Thanks for sharing!

ajoyraman (author)ThomasK192016-02-23

As I am comfortable working with 'c' and have only written simple sketches. I did not write the program as a sketch. It would wonderful if somebody converts it to a sketch which would then be useful to a larger Arduino community. I can provide any technical inputs required.

ThomasK19 (author)ajoyraman2016-02-24

I have modified the c source into an Arduino sketch with almost no issue (see attachment). Though I could not test it due to the lack of the hardware I'm sure it will work as expected.

ajoyraman (author)ThomasK192016-02-24

Great work! I checked it out the Sketch runs fine.

LuisLopezMA 1966 (author)2016-02-23

Hi.only have One question.You Check the wave Outside,wear you have a lot Electromagnetic fields.You even Check
If the wave you mini arduino Make can be use directional ground post.If you can do This
Please posted.We working in That and Any Help Count.

Your 'One question' is tricky.

The noise seen on the output waveforms is partly because of the limitation of 200 points on my DIY scope. The Analog scope display is better. Next the 6-Bit resolution adds to the quantization noise. The D/A converter would have a noise floor of typically 36 db. Working with the PC usb port has limitations on ground coupling between circuits. I have run the Arduino from a desktop, if one uses a laptop and goes to battery mode then the generator is effectively floating and the ground is isolated from other circuits. Your requirement is for an isolation amplifier which would make things more complex.

SalbaheJim (author)2016-02-23

Have you though about adding an op-amp to the output as a follower to offset the loading effects when you use this circuit to inject a signal into another circuit? It's been too many years since I've used an op-amp but it sounds right to me. It would be like adding a nice frosting to the perfect cake! :-)

ajoyraman (author)SalbaheJim2016-02-23

Yes an external op-amp would be useful but I did not add it for two reasons. Firstly, I wanted to use only the minimum of components and that to only passive. And secondly, the I chose 1K as the msb resistor so that the network would have an output resistance of 1K or less (most audio signal generators are 600 Ohm). Audio circuits are coupled through a capacitor and so no level shifting is required. This met my design goal of minimum component count with maximum utility.

About This Instructable




Bio: I am a retired Electronic Systems Engineer now pursuing my hobbies full time. I share what I do especially with the world wide student community.
More by ajoyraman:Android OTG Development InterfaceArduino Uno DDS Audio Signal GeneratorSimple DIY Electronic Enclosure
Add instructable to: