How to build a signal generator using Arduino and AD9833

Publisher:艺泉阁Latest update time:2023-03-24 Source: elecfansKeywords:Arduino Reading articles on mobile phones Scan QR code
Read articles on your mobile phone anytime, anywhere

  If you're an electronics geek like me who wants to tweak different electronic circuits, having a decent function generator is sometimes essential. But owning one is problematic, as such a basic device can cost a fortune. Not only is it cheaper to build your own test equipment, but it's a great way to improve your knowledge.


  So, in this article, we will build a simple signal generator using Arduino and AD9833 DDS function generator module, which can generate sine, square and triangle waves at the output with a maximum frequency of 12 MHz. Finally, we will test the output frequency with the help of an oscilloscope.

  What is a DDS function generator?

  As the name suggests, a function generator is a device that can be set to output a specific waveform at a specific frequency. For example, let's say you have an LC filter that you want to test the output frequency response of. You can easily do this with the help of a function generator. All you need to do is set the desired output frequency and waveform, and then you can turn it down or up to test the response. This is just an example, there are more things you can do with it as the list goes on.


  DDS stands for Direct Digital Synthesis. It is a waveform generator that uses a digital-to-analog converter (DAC) to build the signal from scratch. This method is specifically used to generate sine waves. But the IC we use can generate square wave or triangle wave signals. The operations that happen inside the DDS chip are digital, so it can switch frequencies very quickly, and it can switch from one signal to another very quickly. The device has good frequency resolution and wide spectrum.


  Learn how the AD9833 function generator IC works

  The core of our project is the AD9833 programmable waveform generator IC designed and developed by Analog Devices. It is a low-power, programmable waveform generator capable of generating sine, triangle and square waves with a maximum frequency of 12 MHz. This is a very unique IC that can change the output frequency and phase with just a software program. It has a 3-wire SPI interface and that's why communicating with this IC becomes very simple and easy. The functional block diagram of this IC is shown below.

poYBAGLriFOABgWRAAIS6vITucU464.png

  The working of this IC is very simple. If we look at the functional block diagram above, we see that we have a phase accumulator whose job is to store all possible digital values ​​of the sine wave from 0 to 2π. Next, we have the SIN ROM, whose job is to convert phase information into information that can later be mapped directly to amplitude. SIN ROM uses digital phase information as the address of a lookup table and converts the phase information into amplitude. Finally, we have a 10-bit analog-to-analog converter, whose job is to receive the digital data from the SIN ROM and convert it into the corresponding analog voltage, and this is the voltage we get from the output. On the output side, we also have a switch that can be turned on or off with just a bit of software code. We will discuss this later in this article. AD9833 datasheet, you can also view it for more information.


  Components required to build an AD9833-based function generator

  Listed below are the components required to build an AD9833 based function generator. We designed this circuit using very common components which makes the duplication process very easy.

  Arduino Nano-1

  AD9833 DDS Function Generator - 1

  128 x 64 OLED display - 1

  Universal Rotary Encoder - 1

  DC Barrel Jack - 1

  LM7809 Voltage Regulator - 1

  470uF capacitor - 1

  220uF capacitor - 1

  104pF capacitor - 1

  10K resistor - 6

  Tact switch - 4

  Screw terminal 5.04mm - 1

  Female head - 1

  12V power supply - 1

  AD9833-based function generator - schematic

  The complete circuit diagram of the AD9833 and Arduino based function generator is shown below.

poYBAGLriEyAHof3AAIN3pB44Qo246.png

  We will use an AD9833 with an Arduino to generate the frequency we want. In this section we will explain all the details with the help of a schematic; let me give a brief overview of what is happening in the circuit. Let's start with the AD9833 module. The AD9833 module is a function generator module and is connected to Arduino according to the schematic diagram. To power the circuit, we used a LM7809 voltage regulator IC with a decent decoupling capacitor, which is necessary because power supply noise can interfere with the output signal, causing unwanted output. As always, the Arduino is the brains of this project. To display the set frequency and other valuable information, we connected a 128 X 64 OLED display module. To change the frequency range we used three switches. The first one sets the frequency to Hz, the second one sets the output frequency to KHz, the third one sets the frequency to MHz and we have another button that can be used to enable or disable the output. Finally, we have the rotary encoder and we have to connect some pull-up resistors otherwise these switches won't work since we are checking for button press events on the pool method. The rotary encoder is used to change the frequency, and the tact switch inside the rotary encoder is used to select the set waveform.

pYYBAGLriEiAbgB8AAhZvWrzqrs594.png

  AD9833 based function generator - Arduino code

  The complete code used in this project can be found at the bottom of this page. After adding the required header and source files, you should be able to compile the Arduino file directly. You can download ad9833 Arduino library and other libraries from the link given below or you can install the library using the board manager method.


  Code description in ino. The files are below. First, we start by including all required libraries. The AD9833 DDS module library is first of all the OLED library, and some of our calculations require the math library.


  Code description in ino. The files are below. First, we start by including all required libraries. The AD9833 DDS module library is first of all the OLED library, and some of our calculations require the math library.


#include // AD9833 module library

#include // OLED wire library

#include // OLED support library

#include // OLED library

#include // math library

 

Next, we define all the necessary input and output pins for buttons, switches, rotary encoders, and OLEDs.


#define SCREEN_WIDATA_PINH 128 // OLED display width in pixels

#define SCREEN_HEIGHT 64 // OLED display height in pixels

#define SET_FREQUENCY_HZ A2 // Button to set frequency in Hz

#define SET_FREQUENCY_KHZ A3 // Button to set the frequency in Khz

#define SET_FREQUENCY_MHZ A6 // Button to set the frequency in Mhz

#define ENABLE_DISABLE_OUTPUT_PIN A7 // Button to enable/disable output

#define FNC_PIN 4 // Fsync required by AD9833 module

#define CLK_PIN 8 // Encoder clock pin

#define DATA_PIN 7 // Encoder data pin

#define BTN_PIN 9 // Internal button on encoder

 

After this, we defined all the necessary variables required in this code. First, we define an integer variable counter to store the value of the rotary encoder. The next two variables, clockPin and clockPinState, store the pin state required to understand the encoder direction. We have a time variable to hold the current timer counter value, this variable is used for button debounce. Next, we have an unsigned long variable moduleFrequency which holds the calculated frequency to which it will be applied. Next, we have debounce delay. This delay can be adjusted as needed. Next, we have three boolean variables set_frequency_hz, set_frequency_Khz and set_frequency_Mhz. These three variables are used to determine the current settings of the module. We'll discuss it in more detail later in this article. Next, we have variables that store the state of the output waveform. The default output waveform is a sine wave. Finally, we have the encoder_btn_count variable, which holds the encoder button count used to set the output waveform.


integer counter = 1; // If the rotary encoder turns, this counter value will increase or decrease

integer clock pin; //Pin status placeholder used by the rotary encoder

integer clock pin status; //Pin status placeholder used by the rotary encoder

unsigned long = 0; // used for debounce

Unsigned long module frequency; // used to set the output frequency

long debounce = 220; // debounce delay

Boolean btn_state; // Used to enable the disabled output of the AD98333 module

Boolean set_frequency_hz = 1; //Default frequency of AD9833 module

bool set_frequency_khz;

bool set_frequency_mhz;

String waveSelect = "SIN"; // The startup waveform of the module

int encoder_btn_count = 0; // Used to check whether the encoder button is pressed

Next, we have two objects, one for the OLED display and another for the AD9833 module.

Adafruit_SSD1306 display(SCREEN_WIDATA_PINH, SCREEN_HEIGHT, &Wire, -1);

AD9833 gen(FNC_PIN);

 

Next, we have our setup() function, in this setup function we first enable Serial for debugging. We initialize the AD9833 module with the help of the begin() method. Next, we set up all assigned rotary encoder pins as inputs. And we store the value of the clock pin in the clockPinState variable, which is a necessary step to rotate the encoder.


Next, we set all button pins as inputs and enable OLED display with the help of display.begin() method. We also check if there are any errors using if statements. Once completed, we clear the display and print the splash screen, we add a delay of 2 seconds, which is also the delay of the splash screen, and finally, we call the update_display() function to clear the screen and update the display again. The details of the update_display() method will be discussed later in this article.


void settings(){

  serial.start(9600); // Enable serial @9600 baud

  gen.Begin(); // This must be the first command after declaring the AD9833 object

  pinMode(CLK_PIN, input); // Set pin as input

  pinMode(DATA_PIN, input);

  pinMode(BTN_PIN, INPUT_PULLUP);

  clockPinState = digitalRead(CLK_PIN);

  pinMode(SET_FREQUENCY_HZ, INPUT);//Set the pin as input

  pinMode(SET_FREQUENCY_KHZ, input);

  pinMode(SET_FREQUENCY_MHZ, input);

  pinMode(ENABLE_DISABLE_OUTPUT_PIN, input);

[1] [2] [3]
Keywords:Arduino Reference address:How to build a signal generator using Arduino and AD9833

Previous article:How to use an oscilloscope to test a battery's transient energy
Next article:How to distinguish signal quality with oscilloscope eye diagram

Latest Test Measurement Articles
Change More Related Popular Components

EEWorld
subscription
account

EEWorld
service
account

Automotive
development
circle

About Us Customer Service Contact Information Datasheet Sitemap LatestNews


Room 1530, 15th Floor, Building B, No.18 Zhongguancun Street, Haidian District, Beijing, Postal Code: 100190 China Telephone: 008610 8235 0740

Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved 京ICP证060456号 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号