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.
Wiring diagram
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; }