0.. 5V output from DAC MAX5217

Hallo guys i am controlling my DAC MAX5217 with i2c and it has the address ( 0x1D ) i used the i2c scanner for that. and two rotary enocders to control from 0 to 5V.

Unfourtantly i am not getting error messages in the code but i dont get 5V out of my DAC . i get nothing ( measured with multimeter ), what am doing wrong in my code? i already did the same thing for MCP4725 and it worked out. i just wanted to have better resolution and accuracy.

The connection are also correct am pretty sure its software thing.

here is my code:

#include <Wire.h>
#define MAX5217 0x1D


// Rotary knob state
volatile int old_state = 0;
volatile int state = 0;

// Value to send to DAC
volatile int value = 0;
volatile int new_value = 65000;

// Used to limit the frequency of timer updates to 30 times per sec
int old_time = 0;

// Interrupt handler for rotary encoder
ISR(PCINT2_vect) {
 state = PIND;
 int changes = state ^ old_state;
 // If bit 2, update the value
 if (bitRead(changes, 2)) {
   if (bitRead(state, 2) ^ bitRead(old_state, 3)) {
     new_value++;
   } else {
     new_value--;
   }
 }
 // If bit 4, update the value with a coarse resolution
 if (bitRead(changes, 4)) {
   if (bitRead(state, 4) ^ bitRead(old_state, 5)) {
     new_value += 8;
   } else {
     new_value -= 8;
   }
 }

 // Store the state to compare against next time
 old_state = state;
}

void setup(void) {
 pinMode(13, OUTPUT);     
 digitalWrite(13, HIGH);   // turn the LED on (HIGH is the voltage level)
 delay(1000);               // wait for a second
 digitalWrite(13, LOW);    // turn the LED off by making the voltage LOW
 delay(1000);               // wait for a second
 Wire.begin(0x1D);
 pinMode(2, INPUT);
 digitalWrite(2, HIGH);
 pinMode(3, INPUT);
 digitalWrite(3, HIGH);
 pinMode(4, INPUT);
 digitalWrite(4, HIGH);
 pinMode(5, INPUT);
 digitalWrite(5, HIGH);

 noInterrupts();
 // Pin change interrupt control register
 PCICR |= 0b100;
 
 // Pin change mask registers decide which pins are enabled as triggers
 PCMSK2 |= (_BV(PCINT18) | _BV(PCINT19) | _BV(PCINT20) | _BV(PCINT21));
 interrupts();

}

void loop(void) {
  float dac_expected_output;
 int time = millis();
 // Limit frequency of timer updates to 30 per second
 if (time - old_time < 33) {
   return;
 }
 old_time = time;

 if (value != new_value) {
   digitalWrite(13, HIGH);
   delay(10);
   digitalWrite(13, LOW);
   delay(10);
   value = new_value;
   dac_expected_output = (5.0/65000.0) * value;
 
   if (value > 65000) {
     new_value = value = 65000;
   }
   if (value < 8) {
     new_value = value = 8;
   }

 }
}

On an 8 bit Arduino like Uno.

volatile int new_value = 65000;

This could create a problem. An int data type can store values from -32768 to 32767. An unsigned int can store up to 65535.

Print the value of new_value in setup (before it is changed). Is it 65000?

With the first part you mentioned you are right cause it was 4096 when i was using the 12 bit dac and i changed the number only.

and i just noticed that in the end of the code i had before the function dac.setvoltage(value, False).

and i have to replace that one now for the 16 bit and i dont really know how cause that function was linked with a library. and the max5217 has no library. Do you have any idea for this?

Any help is appreciated?
Thanks all

Hi,
Welcome to the forum.

Please read the first post in any forum entitled how to use this forum.
http://forum.arduino.cc/index.php/topic,148850.0.html then look down to item #7 about how to post your code.
It will be formatted in a scrolling window that makes it easier to read.

Can you please post a copy of your circuit, in CAD or a picture of a hand drawn circuit in jpg, png?

Did you google MAX5217 arduino

If you freeze a frame in this YouTube you can see the short bit of code used.

Tom... :slight_smile:

Hi Tom sorry for the code thing i will try to edit it.

Yes i googled and i saw the link you posted but the guy dont provide any code or anything the video wasnt so good. I saw ur comment also i appreciate the help!! but i cant link my code on his .. it seems that the loop is too short and am complicating it .

it's hard that i take picture of the circuit now but i can tell you the 8 connections of my DAC.

REF connected to external 5v Ref Chip
ADDR to GND
SDA To SDA
SCL To SCL

AUX to GND
GND to GND
VDD to battery supply 5.2 V

Google search for "max5217 arduino example" leads to this page. That page has some setup information and a link to basic example code.

Yep i used this before couldnt reach anywhere.

Anyway thanks guys.

i will try to modify the code i have for the MCP4725 12 Bit. Do you wanna have look on it ?

The MAX5217 has no library. so the function dac.setVoltage is not there.

Here is the Code for the MCP4725:

#include <Wire.h>
#include <Adafruit_MCP4725.h>

Adafruit_MCP4725 dac;

// Rotary knob state
volatile int old_state = 0;
volatile int state = 0;

// Value to send to DAC
volatile int value = 0;
volatile int new_value = 4095;

// Used to limit the frequency of timer updates to 30 times per sec
int old_time = 0;

// Interrupt handler for rotary encoder
ISR(PCINT2_vect) {
 state = PIND;
 int changes = state ^ old_state;
 // If bit 2, update the value
 if (bitRead(changes, 2)) {
   if (bitRead(state, 2) ^ bitRead(old_state, 3)) {
     new_value++;
   } else {
     new_value--;
   }
 }
 // If bit 4, update the value with a coarse resolution
 if (bitRead(changes, 4)) {
   if (bitRead(state, 4) ^ bitRead(old_state, 5)) {
     new_value += 8;
   } else {
     new_value -= 8;
   }
 }

 // Store the state to compare against next time
 old_state = state;
}

void setup(void) {
 pinMode(13, OUTPUT);     
 digitalWrite(13, HIGH);   // turn the LED on (HIGH is the voltage level)
 delay(1000);               // wait for a second
 digitalWrite(13, LOW);    // turn the LED off by making the voltage LOW
 delay(1000);               // wait for a second
 dac.begin(0x60);
 pinMode(2, INPUT);
 digitalWrite(2, HIGH);
 pinMode(3, INPUT);
 digitalWrite(3, HIGH);
 pinMode(4, INPUT);
 digitalWrite(4, HIGH);
 pinMode(5, INPUT);
 digitalWrite(5, HIGH);

 noInterrupts();
 // Pin change interrupt control register
 PCICR |= 0b100;
 
 // Pin change mask registers decide which pins are enabled as triggers
 PCMSK2 |= (_BV(PCINT18) | _BV(PCINT19) | _BV(PCINT20) | _BV(PCINT21));
 interrupts();
}

void loop(void) {
 int time = millis();
 // Limit frequency of timer updates to 30 per second
 if (time - old_time < 33) {
   return;
 }
 old_time = time;

 if (value != new_value) {
   digitalWrite(13, HIGH);
   delay(10);
   digitalWrite(13, LOW);
   delay(10);
   value = new_value;
 
   if (value > 4095) {
     new_value = value = 4095;
   }
   if (value < 8) {
     new_value = value = 8;
   }
 
   dac.setVoltage(value, false);
 }
}

Hi,
Does it work?
Have you got code just to make the DAC go up and down in cycles, forget the encoder etc etc.
Just the DAC.....
START with the basic code to prove I2C comms.

Have you tried the triangle example in the library examples?

Tom... :slight_smile:

Hi Again TOM. no it doesn't work.

i used the i2c scanner this is the first step. i got the 0x1C device address and all good.
i checked all the pins and voltages everything is fine.

but am not producing anything on the output pin :s

let's say now i work only on the DAC and i use the example which groundFungus provided.

I still don't get anything on the output pin

This code what groundFungus provided

#include <Wire.h>
#define MAX5217  0x1C
unsigned int value_16bit = 10;

void setup()
{
 Wire.begin();
 Wire.beginTransmission(0b00011111);
 delayMicroseconds(10);
 Wire.write(0b00001000);
 Wire.write(0x00);
 delayMicroseconds(10);
 Wire.endTransmission();

}
void loop() {

 //  for (int i = 0; i = 65000; i++) {
 //if (value_16bit == 0 ) { value_16bit =10;}
 //      value_16bit = value_16bit - 1;
 value_16bit = 1000;                                     //dac output value
 byte dac_low = byte(value_16bit & 0x00FF);
 byte dac_high = byte((value_16bit & 0xFF00) >> 8);

 Wire.beginTransmission(MAX5217);
 delayMicroseconds(10);
 Wire.write(0x01);
 delayMicroseconds(10);
 Wire.write(dac_high);
 delayMicroseconds(10);
 Wire.write(dac_low);
 delayMicroseconds(10);
 Wire.endTransmission();
 delay(3000);
 
value_16bit = 0;                                         //dac output value
dac_low = byte(value_16bit & 0x00FF);
dac_high = byte((value_16bit & 0xFF00) >> 8);

 Wire.beginTransmission(MAX5217);
 delayMicroseconds(10);
 Wire.write(0x01);
 delayMicroseconds(10);
 Wire.write(dac_high);
 delayMicroseconds(10);
 Wire.write(dac_low);
 delayMicroseconds(10);
 Wire.endTransmission();
 delay(3000);
}

You may try the following setup for quick functional check of MAX5217 DAC (untested due to lack of the DAC chip):

1. Build the following circuit between the UNO and the DAC. (AUX/ function is disabled.)

2. Connect a DVM at Out-pin of the DAC.

3. Upload the following sketch. Bring in the Serial Monitor at 9600 Baud.

#include <Wire.h>

void setup()
{
  Serial.begin(9600);
  Wire.begin();
  pinMode(8, INPUT_PULLUP);    //Dpin-8 is input with internal pull-up resistor
  byte busStatus;
  
  do
  {
    Wire.beginTransmission(0x1D);     //checking the presence of DAC
    busStatus = Wire.endTransmission();    
  }
  while (busStatus !=0x00);  //checking that DAc has aaccepted its address and has sent ACk signal
  Serial.println(busStatus);  //Serial Monitor should show 0
  //--------------------------------
  while(digitalRead(8) != LOW)
    ;                           //wait until K1 is closed
  Wire.beginTransmission(0x1D); //address of DAC 0x1D
  Wire.write(0x08);             //pointing user configurable regsiter
  Wire.write(0x00);             //value for configurable register; AUX/ input is disabled 
  Wire.endTransmission();       //transfer all the above queued data to the ADC
  //--------------------------------
  Wire.beginTransmission(0x1D);   //address of DAC
  Wire.write(0x01);               //address of command byte register/load code and load to DAC 
  Wire.write(0x7F);               //upper 8-bit data for DAC
  Wire.write(0xFF);               //lower 8-bit data for DAC
  Wire.endTransmission();         //transfer all the above queued data
}

void loop() 
{
  
}

4. Check that 0 has appeared on the Serial Monitor.

5. Gently press the K1 switch.

6. Check that the DVM shows about 2.50V DC.

This is the end of simple functional check of the MAX5217 DAC.

GolamMostafa:
You may try the following setup for quick functional check of MAX5217 DAC (untested due to lack of the DAC chip):

1. Build the following circuit between the UNO and the DAC. (AUX/ function is disabled.)

2. Connect a DVM at Out-pin of the DAC.

3. Upload the following sketch. Bring in the Serial Monitor at 9600 Baud.

#include <Wire.h>

void setup()
{
  Serial.begin(9600);
  Wire.begin();
  pinMode(8, INPUT_PULLUP);    //Dpin-8 is input with internal pull-up resistor
  byte busStatus;
 
  do
  {
    Wire.beginTransmission(0x1D);    //checking the presence of DAC
    busStatus = Wire.endTransmission();   
  }
  while (busStatus !=0x00);  //checking that DAc has aaccepted its address and has sent ACk signal
  Serial.println(busStatus);  //Serial Monitor should show 0
  //--------------------------------
  while(digitalRead(8) != LOW)
    ;                          //wait until K1 is closed
  Wire.beginTransmission(0x1D); //address of DAC 0x1D
  Wire.write(0x08);            //pointing user configurable regsiter
  Wire.write(0x00);            //value for configurable register; AUX/ input is disabled
  Wire.endTransmission();      //transfer all the above queued data to the ADC
  //--------------------------------
  Wire.beginTransmission(0x1D);  //address of DAC
  Wire.write(0x01);              //address of command byte register/load code and load to DAC
  Wire.write(0x7F);              //upper 8-bit data for DAC
  Wire.write(0xFF);              //lower 8-bit data for DAC
  Wire.endTransmission();        //transfer all the above queued data
}

void loop()
{
 
}




**4.** Check that **0** has appeared on the Serial Monitor.

**5.** Gently press the K1 switch.

**6.** Check that the DVM shows about 2.50V DC.

This is the end of simple functional check of the MAX5217 DAC.

Thanks alot for your effort.

Till point 4 everything is working fine. I got the 0 on the Serial Monitor. But i didnt get the 2.5 on my DVM. i am still getting 0 Volt. i checked the pins VDD, Vref, SDA, SCL, AUX they all have almost 5V. and didnt connect anything to ADDR. GND is 0 and output is also 0.

Oh the switch i used was damaged now its producing the 2.5V Finally, i changed the switch button.
So Basically the MAX5217 is working :D. Now heading back to the main topic, is there any suggesstions?

i appreciate the help thanks!

1. When you have said that you have got 0 on the Serial Monitor (SM), I was observing Light upon Light in advance -- ; getting 0 on the SM is the proof that the MAX has accepted its address (0x1D) and has sent back the ACK (acknowledgement signal) to the Master.

2. Button K1 is added to give you some control on deciding the start of conversion of the DAC.

3. Check that the DAC works for some other values. For example: DAC upper 8-bit = 0x3F; DAC lower 8-bit = 0xFF; upload the new program and check that DVM reads about 1.25V. Try, using 0x00 and 0x00; DVM should read about 0V. Also try, using 0xFF and 0xFF; DVM should read about 5V.

Have a nice time!

GolamMostafa:
1. When you have said that you have got 0 on the Serial Monitor (SM), I was observing Light upon Light in advance -- ; getting 0 on the SM is the proof that the MAX has accepted its address (0x1D) and has sent back the ACK (acknowledgement signal) to the Master.

2. Button K1 is added to give you some control on deciding the start of conversion of the DAC.

3. Check that the DAC works for some other values. For example: DAC upper 8-bit = 0x3F; DAC lower 8-bit = 0xFF; upload the new program and check that DVM reads about 1.25V. Try, using 0x00 and 0x00; DVM should read about 0V. Also try, using 0xFF and 0xFF; DVM should read about 5V.

Have a nice time!

Thanks alot Man this is brilliant all are working :slight_smile:
now atleast from one side i know its only Software to work on.

i will try to control this with two rotary encoders to adjust 0 .. 5V output voltage.

i think the best way to do this now is to modify my mcp4725 12bit Code with two rotary encoders i provided above to the max5217, what do you think?

It worked out now with the rotary encoders but with a bad resolution 0.04V instead of having 0,0000763 V For each step between 0 .. 65535 (0...5V).

it means am getting at step 1 : 0,04V
Step 2: 0,08 V

The right thing which it should be

Step 1: 0,0000763 V
Step 2: 0,00015259 V

Anyone know how to fix this problem now?

Here is the code:

#include <Wire.h>


// Rotary knob state
volatile unsigned int old_state = 0;
volatile unsigned int state = 0;

// Value to send to DAC
volatile unsigned int value = 0;
volatile unsigned int new_value = 65535;

// Used to limit the frequency of timer updates to 30 times per sec
int old_time = 0;

// Interrupt handler for rotary encoder
ISR(PCINT2_vect) {
  state = PIND;
  int changes = state ^ old_state;
  // If bit 2, update the value
  if (bitRead(changes, 2)) {
    if (bitRead(state, 2) ^ bitRead(old_state, 3)) {
      new_value++;
    } else {
      new_value--;
    }
  }
  // If bit 4, update the value with a coarse resolution
  if (bitRead(changes, 4)) {
    if (bitRead(state, 4) ^ bitRead(old_state, 5)) {
      new_value += 8;
    } else {
      new_value -= 8;
    }
  }

  // Store the state to compare against next time
  old_state = state;
}

void setup(void) {
  Serial.begin(9600);
  pinMode(13, OUTPUT);     
  digitalWrite(13, HIGH);   // turn the LED on (HIGH is the voltage level)
  delay(1000);               // wait for a second
  digitalWrite(13, LOW);    // turn the LED off by making the voltage LOW
  delay(1000);               // wait for a second
  Wire.begin();
  Wire.beginTransmission(0x1D); //address of DAC 0x1D
  Wire.write(0x08);             //pointing user configurable regsiter
  Wire.write(0x00);             //value for configurable register; AUX/ input is disabled 
  Wire.endTransmission();       //transfer all the above queued data to the ADC
  pinMode(2, INPUT);
  digitalWrite(2, HIGH);
  pinMode(3, INPUT);
  digitalWrite(3, HIGH);
  pinMode(4, INPUT);
  digitalWrite(4, HIGH);
  pinMode(5, INPUT);
  digitalWrite(5, HIGH);

  noInterrupts();
  // Pin change interrupt control register
  PCICR |= 0b100;
  
  // Pin change mask registers decide which pins are enabled as triggers
  PCMSK2 |= (_BV(PCINT18) | _BV(PCINT19) | _BV(PCINT20) | _BV(PCINT21));
  interrupts();
}

void loop(void) {
  int time = millis();
  // Limit frequency of timer updates to 30 per second
  if (time - old_time < 33) {
    return;
  }
  old_time = time;

  if (value != new_value) {
    digitalWrite(13, HIGH);
    delay(10);
    digitalWrite(13, LOW);
    delay(10);
    value = new_value;
  
    if (value > 65535) {
      new_value = value = 65535;
    }
    if (value < 8) {
      new_value = value = 8;
    }
  
  Wire.beginTransmission(0x1D);   //address of DAC
  Wire.write(0x01);               //address of command byte register/load code and load to DAC 
  Wire.write(value);               //upper 8-bit data for DAC
  Wire.write(value);               //lower 8-bit data for DAC

  Wire.endTransmission();         //transfer all the above queued data
Serial.println(value);
  }
}

Wire.beginTransmission(0x1D); //address of DAC
Wire.write(0x01); //address of command byte register/load code and load to DAC
Wire.write(value); //upper 8-bit data for DAC
Wire.write(value); //lower 8-bit data for DAC
Wire.endTransmission(); //transfer all the above queued data

Something is not in the right way in the above instructions.
(a) value is a 16-bit unsigned number (0x0000 - 0xFFFF).
(b) Upper 8-bit of value should enter into the upper part of the DAC. Lower 8-bit of value should enter into lower 8-bit of DAC. So, the instructions should be:

Wire.beginTransmission(0x1D);   //address of DAC
  Wire.write(0x01);                        //address of command byte register/load code and load to DAC 
  Wire.write(highByte(value));        /upper 8-bit data for DAC
  Wire.write(lowByte(value));               //lower 8-bit data for DAC
  Wire.endTransmission();         //transfer all the above queued data

The above correction should also solve your resolution problem. The Full Scale of DAC = 5V. It sweeps over 65536 steps. If you feed 0x0001 into DAC, you will get 5/65536 = 0.0000763V at the OUT-pin of the DAC.

Dude you are completly right!!!!
Thanks thousands times!!
its working perfect now :slight_smile: i appreciate your help

Hello GolamMostafa

Do you happen to have the picture of the test setup laying around? I am facing the same issue currently. I managed to get it working at some point but it doesn't work atm.

I have pullup resistors(1K), AUX to GND, VREF to VCC VCC to 5V VREF IC

GolamMostafa:
You may try the following setup for quick functional check of MAX5217 DAC (untested due to lack of the DAC chip):

1. Build the following circuit between the UNO and the DAC. (AUX/ function is disabled.)

2. Connect a DVM at Out-pin of the DAC.

3. Upload the following sketch. Bring in the Serial Monitor at 9600 Baud.

#include <Wire.h>

void setup()
{
  Serial.begin(9600);
  Wire.begin();
  pinMode(8, INPUT_PULLUP);    //Dpin-8 is input with internal pull-up resistor
  byte busStatus;
 
  do
  {
    Wire.beginTransmission(0x1D);    //checking the presence of DAC
    busStatus = Wire.endTransmission();   
  }
  while (busStatus !=0x00);  //checking that DAc has aaccepted its address and has sent ACk signal
  Serial.println(busStatus);  //Serial Monitor should show 0
  //--------------------------------
  while(digitalRead(8) != LOW)
    ;                          //wait until K1 is closed
  Wire.beginTransmission(0x1D); //address of DAC 0x1D
  Wire.write(0x08);            //pointing user configurable regsiter
  Wire.write(0x00);            //value for configurable register; AUX/ input is disabled
  Wire.endTransmission();      //transfer all the above queued data to the ADC
  //--------------------------------
  Wire.beginTransmission(0x1D);  //address of DAC
  Wire.write(0x01);              //address of command byte register/load code and load to DAC
  Wire.write(0x7F);              //upper 8-bit data for DAC
  Wire.write(0xFF);              //lower 8-bit data for DAC
  Wire.endTransmission();        //transfer all the above queued data
}

void loop()
{
 
}




**4.** Check that **0** has appeared on the Serial Monitor.

**5.** Gently press the K1 switch.

**6.** Check that the DVM shows about 2.50V DC.

This is the end of simple functional check of the MAX5217 DAC.