AD9833 Signal Generator – Part 2

This is the next stage of experimenting with the AD9833. This time adding some control to the device.

Warning! I strongly recommend using an old or second hand keyboard for your MIDI experiments.  I am not responsible for any damage to expensive instruments!

These are the key Arduino tutorials for the main concepts used in this project:

If you are new to Arduino, see the Getting Started pages.

Parts list

  • Arduino Uno
  • AD9833 signal generator module
  • 1x 10KΩ Potentiometer
  • 1x Button switch
  • Amplification/speaker for output
  • Breadboard and jumper wires

The Circuit

AD9833 Signal Generator - Part 2_bb

This is the same circuit as for the AD9833 Signal Generator project but with the addition of a potentiometer on A0 and a switch on digital pin 2.

Recall that the AD9833 itself requires the following connections to the Arduino:

  • VCC to 5V
  • GND to GND
  • SDATA to MOSI (D11)
  • SCLK to CLK (D13)
  • FSYNC to an Arduino digital pin (D10)

2020-11-19 18.29.21

The Code

Once again this is use the MD_AD99833 library from MajicDesigns.

The main functions required are as follows:

// Initialise the library
MD_AD9833 AD(FSYNC); // Hardware SPI

// In the setup() function
void setup() {
  AD.begin();
}

// In the loop() function when required to
// set the frequency or change the mode
void loop () {
  ...
  AD.setFrequency(freq);
  ...
  AD.setMode(MD_AD9833::MODE_SINE);
  ...
}

The code itself will check for the button being pressed.  The button is initialised in INPUT_PULLUP mode which activates the internal “pullup” resistors – this means the button will go LOW when pressed.  When pressed it changes the mode, cycling through sine, triangle, square, square/2, off.

It will also read the A0 analog input for a value between 0 and 1023 and turn this into a frequency value between 30 and 1053.

In each case I am only sending a new value out to the AD9833 if the value has to be changed – so if the potentiometer has changed position for example.

You can hear in the video some “clicking” which seems to happen when the frequency is changing.  I think this is due to a sharp frequency change causing an immediate cut-off at whatever part of the wave was already playing – you can see these as an immediate “drop to zero” in the waveform.

Update on the Clicks!

It looks like this might be a small bug in the MD_AD9833 library.  Basically you can write to the AD9833 in two ways – treating the two parts of the frequency value as independent “high” and “low” parts, or as a single atomic update.  To do a single write (i.e. ask the device only to act after receiving both values) needs a special bit (“B28”) to be set in the control register.

The library assumes that this bit only needs to be set once on initialisation (which is the obvious thing to assume!) but it would appear that this might not be the case.  The AD9833 datasheet is very unclear on the topic, but if I add a line to set the bit every time the frequency is changed the “clicking” goes away and the frequency changes are now nice and smooth.

To update the library fine the following file in your Arduino library area: libraries\MD_AD9833\src\MD_AD9833.cpp and find the “MD_AD9833::setFrequency” function.  At end of the function there are two calls to spiSend preceded by a comment about the B28 bit setting behaviour in the library.  Just add a line as follows.

spiSend(_regCtl); //<<<-- Add this line
spiSend(freq_select | (uint16_t)(_regFreq[chan] & 0x3fff));
spiSend(freq_select | (uint16_t)((_regFreq[chan] >> 14) & 0x3fff));

Generally speaking it isn’t good practice to edit one of your libraries.  At the very least when the library is next updated your change will get overwritten, but I see this as a temporary measure. I’ve already reported that it might be a potential issue against the library itself so hopefully if it is confirmed to be the case, it will be fixed at some point relatively soon.  Anyway, this fix certainly seems to work for me.

My theory for the “clicks” is as follows (feel free to ignore this bit).  The frequency is a 28-bit value, written out in two 14-bit chunks.  But if the AD9833 updates the frequency immediately after the first write, then it has the potential to jump by a factor of 8192 units (14 bits) at a time! When immediately followed by an update to the second frequency value it would immediately jump back.

I’m not entirely sure, but I think the “unit” of frequency is (from the datasheet):

Clock frequency / 2^28

In this case the module is driven by a 25MHz clock, so this would be:

25000000 / 268435456 = 0.093

If I’ve got my sums right then a 14-bit change corresponds to a frequency “jump” of over 760Hz!  No wonder it is sounding as a “click”.  The worst potentiometer settings will be those where there is some “jitter” near to one of these frequency jump boundaries.  Trying to set it to 760Hz for example will have it continually “clicking” as the frequency updates.

By setting the “B28” bit each time we are telling the AD9833 not to update the frequency until both parts of the frequency have been received, resulting in a nice smooth change.

Download it from GitHub here.

Closing Thoughts

With the update in the library, this now works really well.

As I mentioned in the last project, it looks like it might be possible to hook up several of these modules to an Arduino so some simple additive synthesis may be possible.

Kevin

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s