I am trying to run AD9833 frequency generator to have a smooth continuous frequency change. I have run AD9833 module as in here using the code below as found in internet and it works fine and the waveform and frequency displayed on the oscilloscope are as desired.

    #include <SPI.h>

const int SQUARE = 0x2028;    
const float refFreq = 25000000.0;           // On-board crystal reference frequency

const int FSYNC = 10;                       // Standard SPI pins for the AD9833 waveform generator.
const int CLK = 13;                         // CLK and DATA pins are shared with the TFT display.
const int DATA = 11;

void setup() { 

void loop() {
  Serial.println("Serial is available");

  float freq = Serial.parseFloat();
  Serial.print("value to specify : ");
 AD9833setFrequency(freq, SQUARE);

// Set the frequency and waveform registers in the AD9833.
void AD9833setFrequency(float frequency, int Waveform) {
  long FreqWord = (frequency * pow(2, 28)) / refFreq;

  int MSB = (int)((FreqWord & 0xFFFC000) >> 14);    //Only lower 14 bits are used for data
  int LSB = (int)(FreqWord & 0x3FFF);

  //Set control bits 15 ande 14 to 0 and 1, respectively, for frequency register 0
  LSB |= 0x4000;
  MSB |= 0x4000; 

  WriteRegister(LSB);                  // Write lower 16 bits to AD9833 registers
  WriteRegister(MSB);                  // Write upper 16 bits to AD9833 registers.
  WriteRegister(0xC000);               // Phase register
  WriteRegister(Waveform);             // Exit & Reset to SINE, SQUARE or TRIANGLE


void WriteRegister(int dat) { 

  // Display and AD9833 use different SPI MODES so it has to be set for the AD9833 here.

  digitalWrite(FSYNC, LOW);           // Set FSYNC low before writing to AD9833 registers
  delayMicroseconds(10);              // Give AD9833 time to get ready to receive data.

  SPI.transfer(highByte(dat));        // Each AD9833 register is 32 bits wide and each 16
  SPI.transfer(lowByte(dat));         // bits has to be transferred as 2 x 8-bit bytes.

  digitalWrite(FSYNC, HIGH);          //Write done. Set FSYNC high

But everytime as I was trying to change the frequency value, the oscilloscope reading shows a 'flatlines' between every frequency changes. As I was inserting the frequecny value of 111.11Hz, it shows an acceptable value of 111.13Hz. But the problem is when I was trying to change the frequency to let say, 222.22Hz, the oscilloscope showed a 'flatline' a moment before it shows the waveform of 222.24Hz. If I input 333.33Hz, it 'flatlines' as well before showing frequency of the desired 333.33Hz. My desired is without the 'flatline', the frequency change smoothly from 111.11Hz, 222.22Hz and 333.33 Hz.

Is my desired ofr continuous smooth frequency change is can be done or the flatline is hard-coded and cannot be done?


I think that the behavior you see is the result of writing to all registers for each change and/or writing:

WriteRegister(Waveform); // Exit & Reset to SINE, SQUARE or TRIANGLE

If you would only write to the register setting the frequency then perhaps you would get a smooth frequency change you want.

I would make a copy of the AD9833setFrequency procedure, change its name and adapt it such that it only writes to the registers which actually need to change.


AD9833 has two channels. Setting frequency on the 2nd channel and then switching to it produces seamless waveform for a sine wave.

  AD.setFrequency(MD_AD9833::channel_t(chan), freq);
  chan ^= 1;

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.