Run a basic waveform demo with an AD9833 module
I bought an AD9833 module from a seller on aliexpress with the intention of using it to build a function generator to add to my collection of test gear.
This project is a first test to explore:
- the SPI protocol it supports
- different waveforms it can produce
- controlling the frequency
- once you get the SPI configuration correct, it works extremely well, and is very easy to control.
- accuracy at frequencies under 1MHz or so is very good
- accuracy over 1MHz inconclusive .. I need to do some more testing
Here’s the module, with pins attached (with my imperfect soldering, so don’t blame the manufacturer!):
The labeling of the pins is a bit unusual. Here’s the pin definition, and how they connect to an Arduino Uno for hardware SPI:
|Pin||Usage||Arduino SPI Pin|
|VCC||2.3V to 5.5V|
|SDATA||SPI data (MOSI)||11 MOSI|
|SCLK||SPI clock||13 SCK|
|FSYNC||SPI slave select (SS)||10 SS|
NB: the “analog ground” is internally linked to “digital ground” according to the circuit diagram for the module.
The module operates in SPI_MODE2 with MSBFIRST:
- data shifted on falling edge
- FSYNC pin is active low,
- accepts the most significant bit (MSB) of each transfer first.
- The SCLK pin is also specified to be kept high when not in use
The BasicDemoCycle.ino script is a simple non-interactive demo that runs through the different waveforms.
It uses the new SPI.beginTransaction/SPI.endTransaction syntax, although since the script only works with one SPI device, it is redundant to wrap each command sequence in a transaction. But it is a good test of the “right way to do it”. NB: many other scripts found on the net pre-date this syntax.
It is running at very low frequencies in order to produce a visual demo. It sends the measure waveform to the serial port. PlotNValues (a simple Processing sketch) reads the data from the serial port and plots the output value over time, with some coloration effects thrown in for good measure.
Here’s a sample trace. It shows a few cycles of each waveform. From the left:
- sine wave
- square wave (normal cycle time)
- triangle wave
- square wave (halved cycle time i.e. twice as fast)
- output off
Note that square waves are rail-to-rail, since they bypass the DAC. Other waveforms peak at 0.65V per the datasheet.
A few quick measurements with a frequency counter gave very good results under a few MHz. But when I started pushing into the 6-12.5MHz realm, accuracy appeared to drop off markedly.
This may simply be the influence of running the module on a breadboard. I should try it on a PCB.
For now, here are some results (AC-coupled scope traces) with a sinusoid waveform in the breadboard layout.
At 1MHz, still a decent output:
By 8MHz, the waveform is quite distorted and unstable but still on frequency:
By 12MHz, it has devolved to a heavily-modulated mess:
NB: I created a custom Fritzing Part available here for these diagrams.
Running at 300kHz, pretty accurate!
Credits and References
- Thanks to Michaël via email for the idea of an “off” step in the demo cycle
- Module from a seller on aliexpress
- AD9833 datasheet
- Arduino SPI Reference
- Sending out the right signals - informative round-up of various signal generator modules
- Julian’s Postbag: #41 - AD9833 Waveform Generator - my inspiration to try the unit!
- AD9833 Waveform Generator - good project write-up
- Waveform Generation with AD9833, and SPI - some more good details