Search This Blog

Monday, July 30, 2018

ARM - Quick & Dirty DDS for around $2

Projects / Misc ARM Projects  Original post date: 02/07/2016

Direct Digital Synthesis is a way of generating an analog waveform from a digital circuit with finer timing resolution than a simple clock dividers thanks to the NCO.


This is a simple project that looks at implementing the NCO and the various digital blocks inside an ARM Cortex microcontroller. The higher clock speeds and 32-bit architecture of the ARM chips helps with the update rate.

The main DDS loops is from line: 87 - 91

Source code line: 89 implements the phase accumulator.
line 90: strips off the MSB, looks up the corresponding phase in a sine table and send it out to the DAC via GPIO A.

phase is a variable that controls the incremental phase angle for each of the update steps.


There are a few drawback with the software implementation.

  • DDS relies on a tight timing loop for DAC updates, so any CPU time taken away will affect the quality output waveform. DMA won't help as it requires computations and timer interrupts would only slow things down.
  • Speed is limited by the microcontroller, so this is only useful for low frequency application.
  • Forget about using any abstraction layers as they drastically slows down the GPIO.

There are DDS chips e.g. Analog Devices (or DDS implemented inside a FPGA) that can handle much higher frequencies and do not suffer from these limits.

Since the particular ARM chip I have doesn't have a built-in DAC, I used a discrete R-2R DAC (dongle on the right).

The resistors values are 1K & 2K (1%) as that's what I have in my parts box. A higher set of values (e.g. 10K & 20K) would reduce the non-linearity added by the I/O driver resistance (around 20-30 ohms range).

At high output frequency and without a low pass filter, the discrete steps are much more prounced at the output waveform. (For lower frequencies, the individual voltage steps are much smaller.)

The DDS loop takes 280ns to execute. This means that the loops take 13 or so CPU cycles.


Here is a FFT plot of the same output in frequency domain.

FFT plot of the waveform

The equivalent output resistance of the R-2R is R which in my case is 1K. I picked a 470pF capacitor as my low pass filter.
I like to have at least 16 or more samples per period. i.e. 3.5MHz/16 = 218kHz is the upper limit. The cut off frequency of the low pass filter is 338kHz which is around the right order of magnitude needed. RC filter Calculator here


Here is what happens with the capacitor connected. The cap smooths the output by filling out the discrete steps.
Note: It is a RC circuit, so the smoothing function is an exponential function.


Another way of looking at it is that it forms a low pass filter that removes the high frequency harmonics making it closer to a sine wave. The output amplitude is also attenuated.


Sine waves are not the only type of waveforms that can generated with this.

There are lots of refinements that could be made, but I am going to stop here for now as this is supposed to be a simple weekend type of project.

C source code in here:  My github


No comments:

Post a Comment

Note: Only a member of this blog may post a comment.