DIY Generator – AD9833 library and further output noise reduction (part 13)

Today’s post is going to be about two little things. The first one – AD9833 Arduino library which is used to set IC’s output parameters. The second one – I have found out some interesting things about +- 12V converter’s output noise and a way to reduce it.

Links to project’s all posts

  1. VCA822 Gain Amplifier Circuit
  2. LM7171 Offset Circuit
  3. Gain and Offset Control Filter Circuit
  4. Dual 5V Power Supply
  5. Dual 12V TPS65131 Power Supply
  6. Battery Charging Circuit with BQ24295
  7. Basic WEB Interface
  8. IPS Capacitive LCD on an ESP32
  9. IPS LCD, ESP32 with eSPI library and Touch screen
  10. Final PCB Design for the DIY Waveform Generator
  11. Custom Design PCBs and How To Get Them Manufactured
  12. Soldering the PCB
  13. AD9833 Library and Further Output Noise Reduction (this post)
  14. Arduino BQ24295 Battery Charger Library
  15. LCD GUI with LVGL on ESP-32
  16. 3D Printed Enclosure
  17. Finished DIY generator

The Library

I have written a small C++ library for the AD9833. It is Arduino based library used on an ESP-32, but it also should work on other Arduino platforms. This library is one big class with several methods in it. Instead of SPI hardware pins the library uses three regular IO pins – for SCK, FSYNC(CS) and DATA(MOSI). As you can see it does not use any pin for MISO, because AD9833 registers are only writable.

IO pins instead SPI hardware was used because it seemed to be simpler – SPI libraries usually have fourth pin, but it is not needed in this case and if library requires to define it – there are no available free IO pins on the generator’s ESP-32.

The library can be found at my GitHub HERE.


The class AD9833_IC has more than 10 functions (methods) used to set up different IC’s parameters. I would like to comment on some of those.

uint32_t setFrequency(double hz, uint8_t reg);

This function writes frequency value to the selected frequency register. As AD9833 has two registers (0 and 1), variable reg should be 0 or 1. Also, frequency value’s type is double, but actual value written to the register is integer (28 bits). So, this function does some calculations to get the required register’s value, writes it to the IC and returns it as uint32_t back to the user. So, it is possible to check if the value being written is correctly calculated and converted from double.  

uint32_t setPhase(double phase, uint8_t reg);

Function setPhase is similar to setFrequency, but it instead of frequency register, it writes data to the selected phase register. Yet again, the IC has two phase registers – 0 and 1.

void setFrequencyRegister(uint8_t reg);
void setPhaseRegister(uint8_t reg);

These two functions sets frequency or phase registers which are used when IC is outputting a signal. It can be either 0 or 1. If 0 is selected, then a frequency or phase value is takes from the first register. When 1 is selected, the frequency or phase value is takes from the second register.

void setWaveForm(uint8_t waveform);

This function sets output wave form. Parameter waveform can be 0 (sine), 1 (triangle), 2 (square) or 3 (square/2).

void start();
void start(uint8_t waveform, uint8_t freqRegist, uint8_t phaseRegist);

After setting frequency and waveform you need to actually start signal generation. For this, the function start is used. It can be used with or without parameters. I you call just a start() function, then it will start generation with parameters which were already set by the user or are defaults after chip’s startup. It is also possible to pass to the function some parameters for e.g.: start(1,0,0). In this case, before starting signal generation, three parameters – waveform, selected frequency register and selected phase register, will be set.

Also, function start disables IC’s sleep and reset states.

void stop();

Function stop(), as the name implies, stops signal generation. It also puts AD9833 into sleep and reset states.

void directRegWrite(uint16_t data);

Function directRegWrite can be used when other functions are not sufficient. It puts 16 bit of data directly to the IC, so it is up to the user to make this data valid.

There are also some other functions such as getFrequency, getPhase, etc. which return last written to the register value. Note that this value is not read from IC itself, but is taken from a variable which stores the value inside the class.

Usage example

#include <Arduino.h>
#include "ad9833.h"

AD9833_IC generator(1, 5, 3); // creates new object with pins 1,5,3 as SCK, FSYNC, DATA
                                // and initialises IC with stopped state 
                                // (reset and sleep states are ON);
void setup(){
  generator.setFrequency(4000, 0); // sets 4kHz frequency in the register 0;
  generator.start(0,0,0); // starts generation with sine wave with 
                          // selected frequency and phase registers (0 and 0).

void loop(){
	generator.stop(); // stops generation;
	generator.start(); // starts generation again;

TPS65131 converter’s output rail ripple

During a search of possible generator’s output noise sources, I have found out that 12V positive and negative rails (as shown below) are quite noisy.

TPS65131 power save mode output ripple negativeL positiveR
Negative 12V rail on the left and positive – on the right

As you can see it has quite high amplitude of 35-50 mV. Output voltage’s ripple can be lowered by disabling power save on both output rails. After disabling it (desoldering two pull-up resistors), the ripple is almost gone (about several mV are left):

TPS65131 normal mode rail ripple negative-left positive-r
Negative 12V rail on the left and positive – on the right

So, does this have any difference in generator’s output signal noise? Yes, there is a slight difference. In power save mode there are about 5mVp-p of HF noise on the output and with this mode disabled – there are about 4mVp-p (picture below). So, there is a difference of 1 mV.

Generator output HF noise Left-powersave right-normal
Generator’s output HF noise: left-power save, right-normal

Moreover, with power save mode enabled, all system (LCD, ESP32, analog and other circuits combined) consumes about 0.28 A of current when powered only from external charger (with no battery connected). When power save is disabled, total system current becomes around 0.31-0.32 A. So, in normal TPS65131 mode total consumption increases by more than 10%.

At this point I don’t know what is better – slightly lower generators output noise or lower total power consumption. This question is left to be answered in the future.


AD9833 Arduino library files.

Subscribe to a newsletter!

Was this page helpful?