Digital to Analog converter with DAC5311, Any suggestion?

Hello!
I made my DAC code with DAC5311 and Arduino Uno.
I think it has no problem, but it doesn’t work well. Just print 0.
I don’t know where has the problem. Please give me any suggestion.

#include <SPI.h>
#include <math.h>
#define pin_CS 10
#define pin_MOSI 11 
#define pin_SCLK 13
#define max_VOLT 5


void setVoltage(float voltage){
  if (voltage < 0) voltage = 0;
  if (voltage > max_VOLT) voltage = max_VOLT;
  uint16_t temp = int(voltage * pow(2, 8) / max_VOLT);
  temp = temp << 6;
  uint8_t upper = temp >> 8;
  uint8_t lower = (temp & 0xff);
  digitalWrite(pin_CS, LOW);
  SPI.transfer(upper);
  SPI.transfer(lower);
  digitalWrite(pin_CS, HIGH); 
}

void setup() {
  Serial.begin(9600);
  pinMode(pin_CS,OUTPUT);
  pinMode(pin_MOSI,OUTPUT);
  pinMode(pin_SCLK,OUTPUT);              
  SPI.begin();
  SPI.setBitOrder(MSBFIRST);
  SPI.setDataMode(SPI_MODE0);
  digitalWrite(pin_CS,HIGH);
  
  delay(1000);
  setVoltage(5);

}

void loop() {

}

That program doesn't print anything, so it would be better to post the sketch that does print 0, in case other code was also omitted. The problem could be almost anywhere in the code.

aarg:
That program doesn't print anything, so it would be better to post the sketch that does print 0, in case other code was also omitted. The problem could be almost anywhere in the code.

Oops, I check the analog output using oscilloscope and still print 0 voltage.

1. Do you need Mode-0 or Mode-1 option of SPI Port for the operation of your DAC5311? Look at the following diagram and choose the correct mode.
spiModeDAC5311.png
Figure-1: SPI Mode of DAC5311

SpiMode1-3.png
Figure-2: SPI Mode of ATmega328P of UNO

2. Upload the following sketch and check that you have found approx. Vout = 5*127/256 = 2.4 Volt.

//just functioal test
#include <SPI.h>

void setup()
{
  Serial.begin(9600);
  SPI.begin();       //MOSI, SS are outputs
  SPI.setDataMode(SPI_MODE1);  //data capture at falling edge of SCK
  SPI.setClockDivider(SPI_CLOCK_DIV16); //1 Mbits/sec; default 4 Mbits
  delay(100);
  //--------------
  digitalWrite(SS, LOW);
  delay(10);
  //-------------
  SPI.transfer(0x7F);  //0x7F = 127 to producr ~2.4 Volt
  delayMicroseconds (50);   //transfer delay of 1 frame
  SPI.transfer(0x00);
  delayMicroseconds (50);
  //------------
  digitalWrite(SS, HIGH);
}

void loop()
{

}

spiModeDAC5311.png

SpiMode0-2.png

SpiMode1-3.png

beginner863:
Hello!
I made my DAC code with DAC5311 and Arduino Uno.
I think it has no problem, but it doesn’t work well. Just print 0.
I don’t know where has the problem. Please give me any suggestion.

just another suggestion! :slight_smile:

looking at the datasheet for the chip, it seems to me that you are doing the right operations to get and transfer the values to the chip.

I’ll added some serial.prints to your code to that you can monitor what actual values are calculated to be transferred.

//DAC5311 demo code

#include <SPI.h>

#define PD_00 0x00 //normal mode
#define PD_01 0x40 //Output 1k to GND
#define PD_10 0x80 //Output 100k to GND
#define PD_11 0xC0 //Hi-Z

#define max_VOLT 5

#define pin_CS 10

void setVoltage(float voltage) {
  if (voltage < 0) voltage = 0;
  else if (voltage >= max_VOLT) voltage = max_VOLT;

  uint16_t temp = (voltage/ max_VOLT) *  255 ; //8bit input data register. max value = 2^8 -1 = 255

  temp = temp << 6;

  //for debugging
  Serial.print("temp<<6: ");
  Serial.println(temp, HEX);
  //

  uint8_t upper = (temp >> 8) | PD_00; //normal mode
  uint8_t lower = (temp & 0xff);

  //for debugging
  Serial.print("upper: ");
  Serial.println(upper, HEX);
  Serial.print("lower: ");
  Serial.println(lower, HEX);
  //

  digitalWrite(pin_CS, LOW);
  SPI.transfer(upper);
  SPI.transfer(lower);
  digitalWrite(pin_CS, HIGH);
}

void setup() {
  Serial.begin(9600);
  SPI.beginTransaction(SPISettings(10000000, MSBFIRST, SPI_MODE1));
  pinMode(pin_CS, OUTPUT);
  digitalWrite(pin_CS, HIGH);

  delay(1000);
  Serial.println("Setting DAC output to 5V");
  setVoltage(5);

  delay(1000);
  Serial.println("Setting DAC output to 2.5V");
  setVoltage(2.5);

}

void loop() {

}

hope that helps.

sherzaad:
looking at the datasheet for the chip, it seems to me that you are doing the right operations to get and transfer the values to the chip.

You want to say that the ADC5311 captures data 'not at the middle of SCK (Mode-1)'?

The default bit rate is 4 Mbits/sec. So, you need to insert at least this amount of time: 2 us after a SPI.transfer() execution. In your code there is nothing.

The OP has selected Mode-0 and you have selected Mode-3. This is Mode-3 timing of UNO (Fig-1); where, data is being seen to be captured at RISING edge of SCK which does not agree with Mode-0 (Fig-2) of DAC5311.

SpiMode1-3.png
Figure-1:

spiModeDAC5311.png
Figure-2:

SpiMode1-3.png

spiModeDAC5311.png

GolamMostafa:
1. Do you need Mode-0 or Mode-1 option of SPI Port for the operation of your DAC5311? Look at the following diagram and choose the correct mode.
spiModeDAC5311.png
Figure-1: SPI Mode of DAC5311

SpiMode1-3.png
Figure-2: SPI Mode of ATmega328P of UNO

2. Upload the following sketch and check that you have found approx. Vout = 5*127/256 = 2.4 Volt.

//just functioal test

#include <SPI.h>

void setup()
{
  Serial.begin(9600);
  SPI.begin();      //MOSI, SS are outputs
  SPI.setDataMode(SPI_MODE1);  //data capture at falling edge of SCK
  SPI.setClockDivider(SPI_CLOCK_DIV16); //1 Mbits/sec; default 4 Mbits
  delay(100);
  //--------------
  digitalWrite(SS, LOW);
  delay(10);
  //-------------
  SPI.transfer(0x7F);  //0x7F = 127 to producr ~2.4 Volt
  delayMicroseconds (50);  //transfer delay of 1 frame
  SPI.transfer(0x00);
  delayMicroseconds (50);
  //------------
  digitalWrite(SS, HIGH);
}

void loop()
{

}





Thanks to your suggestion. But it is still not working.

sherzaad:
just another suggestion! :slight_smile:

looking at the datasheet for the chip, it seems to me that you are doing the right operations to get and transfer the values to the chip.

I’ll added some serial.prints to your code to that you can monitor what actual values are calculated to be transferred.

//DAC5311 demo code

#include <SPI.h>

#define PD_00 0x00 //normal mode
#define PD_01 0x40 //Output 1k to GND
#define PD_10 0x80 //Output 100k to GND
#define PD_11 0xC0 //Hi-Z

#define max_VOLT 5

#define pin_CS 10

void setVoltage(float voltage) {
 if (voltage < 0) voltage = 0;
 else if (voltage >= max_VOLT) voltage = max_VOLT;

uint16_t temp = (voltage/ max_VOLT) *  255 ; //8bit input data register. max value = 2^8 -1 = 255

temp = temp << 6;

//for debugging
 Serial.print("temp<<6: ");
 Serial.println(temp, HEX);
 //

uint8_t upper = (temp >> 8) | PD_00; //normal mode
 uint8_t lower = (temp & 0xff);

//for debugging
 Serial.print("upper: ");
 Serial.println(upper, HEX);
 Serial.print("lower: ");
 Serial.println(lower, HEX);
 //

digitalWrite(pin_CS, LOW);
 SPI.transfer(upper);
 SPI.transfer(lower);
 digitalWrite(pin_CS, HIGH);
}

void setup() {
 Serial.begin(9600);
 SPI.beginTransaction(SPISettings(10000000, MSBFIRST, SPI_MODE1));
 pinMode(pin_CS, OUTPUT);
 digitalWrite(pin_CS, HIGH);

delay(1000);
 Serial.println(“Setting DAC output to 5V”);
 setVoltage(5);

delay(1000);
 Serial.println(“Setting DAC output to 2.5V”);
 setVoltage(2.5);

}

void loop() {

}




hope that helps.

Thanks to your suggestion. But It stops between SPI.transfer(upper)and SPI.transfer(lower)

beginner863:
Thanks to your suggestion. But It stops between SPI.transfer(upper)and SPI.transfer(lower)

What does that even mean???

You seem to be saying you have a oscilloscope on the SPI pins (how else would you be able to confirm that!). Is that the case?

also just to re-confirm, is this the DAC you are using?

If it is this chip and SPI is truely failing to perform your task, shiftOut() could be a viable alternative in this instance IMHO.