ad9833 waveform generator "pulsing when added mode switch.

I’m gradually building up my retro waveform generator using ad9833 module with digital pot.
Had it working with “hardcoded values and reuploading script each time to change setings. next step was adding a waveform switch.
Now it"pulses” showing the selected waveform for a second, flatlines (on the scope) for a second. switch works correctly. but the waveform should be continuous. (yet to add frequency controls).
Below is the code with the switch added.

/*
AD9833 Waveform Module vwlowen.co.uk
*/

#include <SPI.h>

const int SINE = 0x2000;                    // Define AD9833's waveform register value.
const int SQUARE = 0x2028;                  // When we update the frequency, we need to
const int TRIANGLE = 0x2002;                // define the waveform when we end writing.    

int wave = 0;
int waveType = TRIANGLE;
int wavePin = 2;

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;
const int CS = 9;

const int sinePin = 6;                      // waveform selecter switch input
const int triPin = 7;
const int squarePin = 8;

// digital pot values for differant wave forms to maintain constant output level
const int TRPOT = 254;            
const int SQPOT = 29;              
const int  SIPOT = 254;

int potMode = SIPOT;                        // potmode for determining digipot setting
int potVal = 210;

unsigned long freq = 1000
;               // Set initial frequency.

void setup() {
 Serial.begin(9600);                //for debugging output to serial terminal
   pinMode (CS, OUTPUT);
  pinMode (sinePin, INPUT);
  digitalWrite (sinePin, HIGH);
  pinMode (triPin, INPUT);
    digitalWrite (triPin, HIGH);
  pinMode (squarePin, INPUT);
    digitalWrite (squarePin, HIGH);
   // Can't set SPI MODE here because the display and the AD9833 use different MODES.
  SPI.begin();
  
  AD9833reset();                                   // Reset AD9833 module after power-up.
  delay(50);
  AD9833setFrequency(freq, waveType);                  // Set the frequency and wave type
 }



void loop() {
  if (digitalRead(triPin) == LOW)
      {waveType = TRIANGLE;
      }
      else if (digitalRead(squarePin) == LOW)
      {waveType = SQUARE;
      }
      else if (digitalRead(sinePin) == LOW)
      {waveType = SINE;
      }
     
  // delay(50);
       AD9833setFrequency(freq, waveType);                  // Set the frequency and wave type

}
    
// AD9833 documentation advises a 'Reset' on first applying power.
void AD9833reset() {
  WriteRegister(0x100);   // Write '1' to AD9833 Control register bit D8.
  delay(10);
}

// Set the frequency and waveform registers in the AD9833.
void AD9833setFrequency(long 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(0x2100);  
  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.
  SPI.setDataMode(SPI_MODE2);      
  
  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
  digipot();
}
void MCP41010Write(byte value) 
{
  // Note that the integer vale passed to this subroutine
  // is cast to a byte
  
  digitalWrite(CS,LOW);
   delayMicroseconds(10);
  SPI.transfer(B00010001); // This tells the chip to set the pot
  SPI.transfer(value);     // This tells it the pot position
  delay (500);
  digitalWrite(CS,HIGH); 
}
void digipot ()
{ 
   Serial.print("waveType = " );                     
    Serial.println(waveType); 
  
  if (waveType == SINE)
        {
          (potVal = (SIPOT));
        }
   if (waveType == TRIANGLE)
       {
         (potVal = (TRPOT));
       }
   if (waveType == SQUARE)
       {
         (potVal = (SQPOT));
       }
    //      Serial.print("potVal = " );                     
   // Serial.println(potVal); 
 MCP41010Write (potVal);
}

You seem to have a delay(500) for no reason - I think you might have a conflict on the SPI bus too, since the AD9833 isn't actually SPI, it responds always to the clock/data

The code "broke" when i populated the loop segment. The code worked before that sending the "hard coded" frequency and wavetype and setting the digital pot (part of the ad9833 module) to the specified value based on wavetype. This was based on merging sample code for the digital pot and ad9833 and adding the code to determing digital pot settings.

After confirming that worked, all i then did was add the code for the selector switch and move the instruction transmit code into the loop function. When i get home from work i will add a conditional statement to check if wavetype has changed then send instruction if it has and see if that makes a differance. (on train going to work at the moment).

I went back to my previous version and grafted the waveType
switch in. As there is nothing in loop the only way to change wave type is to “reset” the arduino. The waves play smoothly (not in pulses). Code provided below.
However i need to be able to manipulate the controls “live”

Before that I even tried adding to loop, a if (waveType != oldwaveType)
{invoke the functions to write to ad9833 and digipot} with appropriate variables defined and a line at end of loop to set oldwaveType = wavetype.
this was to see if it was because of writing to ad9833 but made no differance to what was going on on my scope.

EDIT - I changed the timebase on my scope then varied the delay in the loop in my original code. the flatline didn’t vary in length(time) but the period of signal did vary relating to the length of delay. it appears the flatline is either the beginning of the loop function or the arduino talking to the ad9833. Which would explain why it didn’t happen when loop function was empty.

/*
AD9833 Waveform Module vwlowen.co.uk
*/

#include <SPI.h>

const int SINE = 0x2000;                    // Define AD9833's waveform register value.
const int SQUARE = 0x2028;                  // When we update the frequency, we need to
const int TRIANGLE = 0x2002;                // define the waveform when we end writing.    

int wave = 0;
int waveType = SINE;
int wavePin = 2;


const int sinePin = 6;                      // waveform selecter switch input
const int triPin = 7;
const int squarePin = 8;


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;
const int CS = 9;

// digital pot values for differant wave forms to maintain constant output level
const int TRPOT = 254;            
const int SQPOT = 29;              
const int  SIPOT = 254;

int potMode = SIPOT;                        // potmode for determining digipot setting
int potVal = 210;

unsigned long freq = 1000
;               // Set initial frequency.

void setup() {
 Serial.begin(9600);                //for debugging output to serial terminal
   pinMode (CS, OUTPUT);
  
  pinMode (sinePin, INPUT);
  digitalWrite (sinePin, HIGH);
  pinMode (triPin, INPUT);
    digitalWrite (triPin, HIGH);
  pinMode (squarePin, INPUT);
    digitalWrite (squarePin, HIGH);
    
     if (digitalRead(triPin) == LOW)
      {waveType = TRIANGLE;
      }
      else if (digitalRead(squarePin) == LOW)
      {waveType = SQUARE;
      }
      else if (digitalRead(sinePin) == LOW)
      {waveType = SINE;
      }
   // Can't set SPI MODE here because the display and the AD9833 use different MODES.
  SPI.begin();
  
  AD9833reset();                                   // Reset AD9833 module after power-up.
  delay(50);
  AD9833setFrequency(freq, waveType);                  // Set the frequency and wave type
 }



void loop() {
  
}
    
// AD9833 documentation advises a 'Reset' on first applying power.
void AD9833reset() {
  WriteRegister(0x100);   // Write '1' to AD9833 Control register bit D8.
  delay(10);
}

// Set the frequency and waveform registers in the AD9833.
void AD9833setFrequency(long 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(0x2100);  
  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.
  SPI.setDataMode(SPI_MODE2);      
  
  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
  digipot();
}
void MCP41010Write(byte value) 
{
  // Note that the integer vale passed to this subroutine
  // is cast to a byte
  
  digitalWrite(CS,LOW);
   delayMicroseconds(10);
  SPI.transfer(B00010001); // This tells the chip to set the pot
  SPI.transfer(value);     // This tells it the pot position
  delay (500);
  digitalWrite(CS,HIGH); 
}
void digipot ()
{ 
   Serial.print("waveType = " );                     
    Serial.println(waveType); 
  
  if (waveType == SINE)
        {
          (potVal = (SIPOT));
        }
   if (waveType == TRIANGLE)
       {
         (potVal = (TRPOT));
       }
   if (waveType == SQUARE)
       {
         (potVal = (SQPOT));
       }
          Serial.print("potVal = " );                     
    Serial.println(potVal); 
 MCP41010Write (potVal);
}

I just found out where the issue is.

Using a series of "test points" - serial print "markers" printing to the serial terminal at selected points in the code and my oscilloscope, I had determined that the "flat line" was when data was being written to the module.

As I am using if statements, I got it so i was only writing to the module when I change wave type. I then commented out the mcp41010 digital pot write (that adjusts output level so all signals same strength) and re-ran my script. No "flatline" almost seamless switching of wave type.

So it looks like I will have to: if waveType has changed write to mcp41010 after writing to ad9833, if waveType has NOT changed, write only to ad9833. Hopefully the next part to be built - the frequency dials will also be seamless (they are analog read inputs).

If I get the blanking transient "flatline" only when switching wave Type - I can live with that. The mcp41010 digital pot is part of the AD9833 module I have and is used to adjust the signal strength. I have set its values so the signal strength is consistant regardless of which wave type you have selected as a square wave is considerably stronger than sine or triangle due to the way they are generated by the AD9833 dds chip.

You haven't got rid of that delay(500) yet. That's your problem surely?

On my latest iteration I have changed the value in the MCP41010 function from 500 to 50. Apart from a few delay commands amidst diagnostic serial print statements (so i can read them), I have shortened most of the delay commands I have. The diagnostic serial print lines will be removed after the next addition has been grafted on.

There are a few delay commands elsewhere in the program that I may remove to speed up the responsiveness of the inputs, however both changing that particular delay value and placing the command to change the wave type inside a "if" statement means the "flatline" only briefly occurs when i change the wave type. This means it does not occur if i am simply changing the frequency.

Why are you calling delay at all?

I am also having a problem with the continuity of the frequency. Using similar code just as you used. Between frequency change there will always be a flatline signal for a moment before the new frequency is generated.

Can you share with me the code line which you have altered to solve the flatline issue?