MCP4725 12 bit DAC and SZBK07 DC-DC converter

In this video I show you how I utilize the MCP4725 12 bit digital to analog converter. This is a very nice circuit which allows me to control the SZBK07 DC-DC converter on a very fine scale. In this demonstration I use the DAC to change the output voltage of the SZBK07 between ~0-20 V. The device behaves linear on the full scale. I am glad about this circuit because it allows me to replace the 8 bit MCP41100 and have a more precise temperature control in my digital thermostat for Peltier coolers.

MCP4725 datasheet



Wiring diagram

Both the 16x2 LCD and the MCP4725 are connected to the microcontroller via i2C. One of the pins of the rotary encoder is connected to an interrupt pin (this is more important for Arduinos). The MCP4725 is connected to +5 V which also serves as a ref…

Both the 16x2 LCD and the MCP4725 are connected to the microcontroller via i2C. One of the pins of the rotary encoder is connected to an interrupt pin (this is more important for Arduinos). The MCP4725 is connected to +5 V which also serves as a reference voltage, so it is a good idea to measure the real voltage of the +5 V rail if you want to calculate the output voltage precisely. The output of the MCP4725 is connected to a 10 kOhm resistor which then goes to the pin 2-3 of the CV potentiometer.



Arduino/STM32 source code

//Arduino SDA: A4, SCL: A5
//STM32 SDA: PB7, SCL: PB6
#include <Wire.h> //i2C
#define MCP4725 0x60 //address of device after finding it with the i2C scanner

//16x2 LCD
#include <LiquidCrystal_I2C.h> 
LiquidCrystal_I2C lcd(0x27, 16, 2);

bool writeValueToDAC = false; // can we update the DAC?
float outputVoltage; // calculated value of the Vout
float VREF = 4.869; // The measured 5 V rail voltage value
byte buffer[3]; //buffer for the values to be written on the DAC  
int bitValue = 0; //value of the DAC bit; [0-4095]

//Defining pins
//For Arduino, you can choose pin 2 or pin 3 for interrupts
const int RotaryCLK = PB3; //CLK pin on the rotary encoder
const int RotaryDT = PB4; //DT pin on the rotary encoder

//Statuses
int CLKNow;
int CLKPrevious;

int DTNow;
int DTPrevious;

// Time
float TimeNow1;
float TimeNow2;


void setup()
{

  Serial.begin(9600); //Start the serial
  Wire.begin(); //Start the i2C 
  
	//------------------------------------------------------
	lcd.begin();                      // initialize the lcd 	
	lcd.backlight();
	//------------------------------------------------------
  lcd.setCursor(0,0); //Defining positon to write from first row,first column .
  lcd.print("MCP4725 DAC");
  lcd.setCursor(0,1); //Second row, first column
  lcd.print("Rotary encoder"); //You can write 16 Characters per line .
  delay(3000); //wait 3 sec
  //------------------------------------------------------
   //Rotary encoder pins (CLK, DT)
   pinMode(RotaryCLK, INPUT_PULLUP);
   pinMode(RotaryDT, INPUT_PULLUP);

  //Store states
  CLKPrevious = digitalRead(RotaryCLK);
  DTPrevious = digitalRead(RotaryDT);
    
  attachInterrupt(digitalPinToInterrupt(RotaryCLK), rotate, CHANGE);
  
  TimeNow1 = millis(); //Start time
  lcd.clear(); //Clean startup message
  writeValueToDAC = true; //Allow the value to be refreshed
  bitValue = 0; // Initial value (0: max voltage is the starting value, 4095: min voltage is the starting value)
}


void loop()
{
  TimeNow2 = millis();
  
  if(TimeNow2 - TimeNow1 > 200) //update the LCD at each 200 ms
  {
    printLCD();
    TimeNow1 = millis();
  }
  
  writeDAC();
}

void rotate()
{
  CLKNow = digitalRead(RotaryCLK); //Read the state of the CLK pin
  // If last and current state of CLK are different, then a pulse occurred  
  if (CLKNow != CLKPrevious  && CLKNow == 1)
  {
    // If the DT state is different than the CLK state then    
    if (digitalRead(RotaryDT) != CLKNow) 
    {
      if(bitValue < 4095)
      {
      bitValue++;
      }
      else
      {
        // Don't go beyond the value
      }
      writeValueToDAC = true;      
    }    
    else 
    {
     if(bitValue > 0) 
     {
      bitValue--;    
     }
     else
     {
      //  Don't go below the value
     }
      writeValueToDAC = true;
    }    
  }
  CLKPrevious = CLKNow;  // Store last CLK state

  outputVoltage = (VREF * bitValue)/4096; // updating the calculated voltage value
}


void printLCD()
{ 
    lcd.setCursor(0,0); // 1st line, 1st block
    lcd.print("Value: ");
    lcd.setCursor(7,0);  // 1st line, 8th block
    lcd.print("        ");
    lcd.setCursor(7,0); 
    lcd.print(bitValue);    //Print the value of the rotary encoder
    
    lcd.setCursor(0,1);  // 2nd line, 1st block
    lcd.print("Voltage: ");
    lcd.setCursor(10,1);  // 2nd line, 11th block
    lcd.print("      ");
    lcd.setCursor(10,1); 
    lcd.print(outputVoltage,4);  //Print the nominal voltage; 4 decimals
}

void writeDAC()
{
  if(writeValueToDAC == true)
  {
    //This function sends the value to the DAC  
      
     Serial.println(outputVoltage,4); //print the calculated voltage up to 4 digits.
    
     buffer[0] = 0b01000000;            //Sets the buffer0 with control byte (010-Sets in Write mode)  
     
    /* The buffer is filled up from the left to the right:
     *  [D0    |    ] - [D1D0   |    ] - [D2D1D0  |    ] ... [D7D6D5D4|D3D2D1D0]
     *  This is not OK, so we shit to the right by four bits ( >> 4), so the buffer becomes:
     *  [D11D10D9D8|D7D6D5D4] - This is OK.
     *  
     *  Then we do similar with the buffer[2]. We have the following array in the beginning:
     *  [D7D6D5D4|D3D2D1D0] - but in buffer[2] we have to store the last 4 digits of the binary number
     *  Therefore, we shift the number to the left (<< 4). The result is the following:
     *  [D3D2D1D0|xxxx]
     *  Final result: [D11D10D9D8|D7D6D5D4][D3D2D1D0|xxxx]
     *  See the datasheet Figure 6-2 and the last subfigure in it.
     */
     
     buffer[1] = bitValue >> 4; // D4 - D11 part
     buffer[2] = bitValue << 4; // D3 - D0 part
  
     Wire.beginTransmission(MCP4725); //We can write MCP4725 because of the definition in the beginning of the code    
     Wire.write(buffer[0]); //C2 = 0, C1 = 1, C0 = 0, rest: 00000.
     Wire.write(buffer[1]);  //Sends the first byte 
     Wire.write(buffer[2]);  //Sends the second byte  
     Wire.endTransmission(); //actually sending the data to the DAC
  }
  writeValueToDAC = false;
}


Voltage vs. bit value chart

This chart shows the measured output voltage of the SZBK07 as a function of the bit value applied to the MCP4725 DAC (red dots). The black dots show the measured voltage on the output of the MCP4725 DAC vs the applied but value. Both graphs are fitt…

This chart shows the measured output voltage of the SZBK07 as a function of the bit value applied to the MCP4725 DAC (red dots). The black dots show the measured voltage on the output of the MCP4725 DAC vs the applied but value. Both graphs are fitted with a linear function (dashed lines) and they show a very nice fit which suggests that the behavior of both devices is reasonably linear.


Previous
Previous

Control panel for stepper motors using the Accelstepper library

Next
Next

Dual Arduino solution for smooth and effortless stepper motor control