I am facing issue in my project of function generator which can generate sine, square and triangular wave using AD9833 module and Arduino uno.
Code is works properly and it generates square wave but its not generating sine and triangular wave form.
Here i am using this libraries:
Here is the code:
#include <AD9833.h> // Library for AD9833 Module
#include <Wire.h> // Wire Library for OLED
#include <Adafruit_GFX.h> // Support Library for OLED
#include <Adafruit_SSD1306.h> // OLED library
#include <math.h> // Math Library
#define SCREEN_WIDTH 128 // OLED display Width, in pixels
#define SCREEN_HEIGHT 64 // OLED display height, in pixels
#define SET_FREQUENCY_HZ 5 // Pushbutton To Set Frequency In Hz (D5)
#define SET_FREQUENCY_KHZ 6 // Pushbutton To Set Frequency In KHz (D6)
#define SET_FREQUENCY_MHZ 7 // Pushbutton To Set Frequency In MHz (D7)
#define SCL_PIN A5
#define SDA_PIN A4
#define FNC_PIN 10 // Fsync Required by the AD9833 Module
#define CLK_PIN 2 // Clock Pin of the Encoder
#define DATA_PIN 3 // Data Pin of the Encoder
#define BTN_PIN 4 // Internal Push Button on the Encoder
int counter = 1; // Counter value for the rotary encoder
int clockPin; // Current state of CLK_PIN
int clockPinState; // Previous state of CLK_PIN
unsigned long timeDebounce = 0; // Used for debouncing
unsigned long moduleFrequency = 0; // Frequency to set output
const long debounce = 220; // Debounce delay in milliseconds
bool set_frequency_hz = true; // Default frequency unit
bool set_frequency_khz = false;
bool set_frequency_mhz = false;
String waveSelect = "SIN"; // Startup waveform of the module
int encoder_btn_count = 0; // Encoder button press count
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, -1);
AD9833 gen(FNC_PIN);
void setup() {
// Initialize Serial Communication
Serial.begin(9600);
Serial.println(F("=== AD9833 Function Generator Initialized ==="));
// Initialize AD9833 module
gen.Begin();
Serial.println(F("AD9833 module initialized."));
// Configure Encoder Pins
pinMode(CLK_PIN, INPUT);
pinMode(DATA_PIN, INPUT);
pinMode(BTN_PIN, INPUT_PULLUP);
Serial.println(F("Encoder pins configured."));
// Read initial state of CLK_PIN
clockPinState = digitalRead(CLK_PIN);
Serial.print(F("Initial CLK_PIN state: "));
Serial.println(clockPinState);
// Configure Frequency Selection Pushbuttons
pinMode(SET_FREQUENCY_HZ, INPUT);
pinMode(SET_FREQUENCY_KHZ, INPUT);
pinMode(SET_FREQUENCY_MHZ, INPUT);
Serial.println(F("Frequency selection pushbuttons configured."));
// Initialize OLED Display
if (!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) { // Address 0x3C for 128x64
Serial.println(F("Error: SSD1306 allocation failed."));
for (;;); // Loop forever if display initialization fails
}
Serial.println(F("OLED display initialized successfully."));
// Display Startup Message
display.clearDisplay(); // Clear the Screen
display.setTextSize(2); // Set text size
display.setTextColor(WHITE); // Set text color
display.setCursor(30, 0); // Set cursor position
display.println("AD9833");
display.setCursor(17, 20); // Set cursor position
display.println("Function");
display.setCursor(13, 40); // Set cursor position
display.println("Generator");
display.display(); // Update the Display
Serial.println(F("Startup message displayed on OLED."));
delay(2000); // Delay of 2 seconds
// Enable output by default
gen.EnableOutput(true);
Serial.println(F("AD9833 output enabled by default."));
update_display(); // Call update_display Function
}
void loop() {
// Handle rotary encoder rotation
clockPin = digitalRead(CLK_PIN);
if (clockPin != clockPinState && clockPin == HIGH) {
if (digitalRead(DATA_PIN) != clockPin) {
counter--;
Serial.print(F("Encoder rotated CCW. Counter decremented to: "));
} else {
counter++;
Serial.print(F("Encoder rotated CW. Counter incremented to: "));
}
// Ensure counter does not go below 1
if (counter < 1) {
counter = 1;
Serial.println(counter);
Serial.println(F("Counter cannot go below 1."));
}
// Update display based on counter value
update_display();
}
clockPinState = clockPin; // Remember last CLK_PIN state
// Handle encoder button press to change waveform
if (digitalRead(BTN_PIN) == LOW && millis() - timeDebounce > debounce) {
encoder_btn_count++; // Increment the count
Serial.print(F("Encoder button pressed. Waveform count: "));
Serial.println(encoder_btn_count);
if (encoder_btn_count > 2) { // Reset count if greater than 2
encoder_btn_count = 0;
Serial.println(F("Waveform count reset to 0."));
}
switch (encoder_btn_count) {
case 0:
waveSelect = "SIN";
Serial.println(F("Waveform selected: SIN"));
break;
case 1:
waveSelect = "SQR";
Serial.println(F("Waveform selected: SQR"));
break;
case 2:
waveSelect = "TRI";
Serial.println(F("Waveform selected: TRI"));
break;
}
update_display(); // Update the display
timeDebounce = millis(); // Update debounce time
}
// Handle frequency unit selection via pushbuttons
if (digitalRead(SET_FREQUENCY_HZ) == LOW && millis() - timeDebounce > debounce) {
set_frequency_hz = true;
set_frequency_khz = false;
set_frequency_mhz = false;
Serial.println(F("Frequency unit set to Hz."));
moduleFrequency = (unsigned long)counter; // Recalculate moduleFrequency
update_display();
timeDebounce = millis();
}
if (digitalRead(SET_FREQUENCY_KHZ) == LOW && millis() - timeDebounce > debounce) {
set_frequency_hz = false;
set_frequency_khz = true;
set_frequency_mhz = false;
// Calculate frequency in Hz
moduleFrequency = (unsigned long)counter * 1000; // Cast to unsigned long
Serial.print(F("Frequency unit set to KHz. Module frequency: "));
Serial.println(moduleFrequency);
update_display();
timeDebounce = millis();
}
if (digitalRead(SET_FREQUENCY_MHZ) == LOW && millis() - timeDebounce > debounce) {
set_frequency_hz = false;
set_frequency_khz = false;
set_frequency_mhz = true;
// Calculate frequency in Hz and ensure it's within limits
moduleFrequency = (unsigned long)counter * 1000000; // Cast to unsigned long
if (moduleFrequency > 12000000) {
moduleFrequency = 12000000; // Cap frequency at 12 MHz
counter = 12; // Set counter to a value that matches the capped frequency
Serial.println(F("Frequency capped at 12 MHz."));
}
Serial.print(F("Frequency unit set to MHz. Module frequency: "));
Serial.println(moduleFrequency);
update_display();
timeDebounce = millis();
}
// Add a small delay to improve stability
delay(10);
}
void update_display() {
display.clearDisplay(); // Clear the display
display.setTextSize(1); // Set text size
display.setCursor(10, 0); // Set cursor position
display.println("Function Generator");
display.setTextSize(2); // Set text size
display.setCursor(0, 20); // Set cursor position
// Update moduleFrequency based on selected frequency unit
if (set_frequency_hz) {
moduleFrequency = (unsigned long)counter; // Set frequency in Hz
} else if (set_frequency_khz) {
moduleFrequency = (unsigned long)counter * 1000; // Set frequency in KHz
} else if (set_frequency_mhz) {
moduleFrequency = (unsigned long)counter * 1000000; // Set frequency in MHz
}
// Display the selected waveform and apply it
if (waveSelect == "SIN") {
display.println("SIN");
gen.ApplySignal(SINE_WAVE, REG0, moduleFrequency);
Serial.print(F("Applied SINE_WAVE at "));
Serial.print(moduleFrequency);
Serial.println(F(" Hz."));
} else if (waveSelect == "SQR") {
display.println("SQR");
gen.ApplySignal(SQUARE_WAVE, REG0, moduleFrequency);
Serial.print(F("Applied SQUARE_WAVE at "));
Serial.print(moduleFrequency);
Serial.println(F(" Hz."));
} else if (waveSelect == "TRI") {
display.println("TRI");
gen.ApplySignal(TRIANGLE_WAVE, REG0, moduleFrequency);
Serial.print(F("Applied TRIANGLE_WAVE at "));
Serial.print(moduleFrequency);
Serial.println(F(" Hz."));
}
// Display the counter value
display.setCursor(45, 20);
display.println(counter);
// Display the frequency unit
display.setCursor(90, 20);
if (set_frequency_hz) {
display.println("Hz");
Serial.println(F("Current frequency unit: Hz."));
} else if (set_frequency_khz) {
display.println("KHz");
Serial.println(F("Current frequency unit: KHz."));
} else if (set_frequency_mhz) {
display.println("MHz");
Serial.println(F("Current frequency unit: MHz."));
}
display.display(); // Update the display
}
Here is the link of circuit testing video which gives idea
https://drive.google.com/file/d/1R3gvzJiKtvYJPjrsShcqQZHU0daT0JZn/view?usp=drive_link