Use a DAC to Adjust a Supply's Vout With an Arduino and Excel

by Rick-ecircuit in Circuits > Arduino

75 Views, 0 Favorites, 0 Comments

Use a DAC to Adjust a Supply's Vout With an Arduino and Excel

cover-pic.PNG

Why adjust your power supply output?

  1. Trim a supply output to a precise level
  2. Compensate for the voltage drop along conductors to a load
  3. Track power rails to an ampifier's output for reduced device heat

How can you adjust your fixed supply output with a DAC? The output is typically set by two resistors R1 and R2. However, by adding a third resistor R3, you can use an external DAC voltage to adjust Vout. The method applies to many Linear Regulators as well as Switch-Mode Power Suppies (SMPS) such as Buck, Boost, etc.

We'l use an Arduino UNO's DAC output (0V to 5V) to adjust the Vout of a Buck-Boost Converter from Sparkfun. By simply adding R3 to the PCB, you can adjust the Converter across it's output range (3V to 9V). Because the Arduino's DAC output is a switching PWM signal, a low-pass filter is applied to create a low-ripple DC signal.

The Code calculates the Vdac for a desired output Vout, writes the value to the DAC and then measures the Vout using an analog input channel to the ADC.

You can customize the adjustment range or apply the method to a different supply using the Excel Design Calculator. Dive in deeper to see how the resistor equations were derived.

Schematic and Overview

schematic1.PNG


Basic Operation

With R1=68.1k, R2=620k, R3=510k and Vref=0.8V, the DAC output Vdac adjusts the supply output according to

Vout = Vdac*m + b

where m = -1.2 and b = 9.0. The circuit Scales (m) and Shifts (b) the input Vdac = 0V to 5V to produce Vout = 9V to 3V. The equation provides you with a handy way to calculate the Vdac needed for a desired Vout.

Vdac = (Vout - b) / m


How It Works (Intuitively)

  1. With R1 and R2 only - The supply's control loop raises Vout until Vfb = Vref. Because of the R1, R2 divider action, Vout must be higher than Vref predicted by Vout = Vref*(R1+R2)/R2
  2. Adding R3 and Vdac - In this case, Vdac also contributes to Vfb through R3. Now Vout needs to rise to a lesser voltage to achieve Vfb = Vref.

Essentially, the higher the Vdac value, the lower the Vout value needed for Vfb = Vref.


Buck-Boost Converter

The DC/DC Converter from Sparkfun takes a Vin of anywhere from 3-16V and regulates to a Vout between 2.5-9V. We'll feed the Arduino's +5V into the converter's Vin. With a mechanical switch, you can set a Vout of 3.3V or 5V. There's also a custom setting that allows you to solder a resistor based on your specific voltage needs. We'll take an advandage of this! The three resistors of our circuit can be easily implemented as

  1. R1 = 68.1k - Already exisits on PCB (done!)
  2. R2 = 620k - Install in custom resistor location. Move switch to CUST position.
  3. R3 = 500k - Solder onto thru-hole pad of R2. (See Built It below).


DAC Output and Low-Pass Filter

The Arduino provides a Digital-to-Analog Converter (DAC) output via a Pulse-Width-Modulated (PWM) digital signal. The Low-Pass Filter transforms the 0V to 5V PWM digital signal into an DC analog signal. To do this we split R3 = 510k into RLP = 10k and R3 = 500k so that the total DC resistance is 510k. Components RLP = 10k and CLP = 1uF create a low-pass filter that reduces signals above the cutoff frequency.

fc = 1 / (2 * pi * RLP * CLP ) = 15.9 Hz

Ideally, we prefer the PWM frequency to be much higher than fc to reduce the ripple as much as possible. So we'll raise the default PWM frequency of D3 from 490 Hz to 31 kHz by setting a variable in the code.


Voltage Monitor (Vout)

We'll use the Arduino's Analog-to-Digital Converter (ADC) to get a sanity check on the output voltage. But the analog inputs can only handle 5V max, so we'll place a resistor divider (R4=R5=10k) from Vout to Vout1.

Kdiv = Vout1 / Vout = R5 / (R4 + R5)

= 1/2

This reduces our max voltage by 1/2 from 9V to 4.5V. We just need to take our raw ADC reading and multiply it by 2.0 to reflect the actual voltage at the output.


Output Enable

The Converter provides an EN pin that's pulled HIGH (thru a 10k resistor to Vcc). This instantly enables Vout to 9V at power up because D3 (Vdac) initializes to a high impedance state. Now if (for example) you're supplying power to +5V devices at the time, then an output at 9V could damage these devices!

For safety, we install a 1k resistor from EN to GND to bring the Enable voltage below the ON threshold. Then, by using Digital output D5, we can enable the supply Vout, AFTER Vdac is set.

Parts List

Feel free to select alternate components for preference / availability / cost.

Arduino

  1. 1 Arduino Uno Rev3 Microcontroller Board A000066
  2. 1 USB Cable Type A/B (generic)

ProtoBoard

  1. 1 Solderless Breadboard, SparkFun Electronics PRT-12002
  2. 1 Pkg Jumper Wires, Various Lengths, M to M, Adafruit Industries

Components

  1. 1 (PCB1) Sparkfun Buck-Boost Converter, COM-15208
  2. 1 (RLP,R4,R5) RES 10k OHM 1%, ≥1/10W
  3. 1 (R3) RES 499k OHM 1%, ≥1/10W
  4. 1 (R2) RES 620k OHM 1%, ≥1/10W
  5. 1 (R6) RES 1k OHM 5%, ≥1/10W
  6. 1 (CLP) CAP CER 1UF ≥15V, ≤20%

Build It - Arduino + Protoboard + Converter

proto-pic-1.PNG

Please note, the diagram above is only a suggestion. Arrange parts and wire the circuit anyway you prefer!

Buck-Boost Modifications

Two quick mods for the Sparkfun Converter

  1. Install R2 into the available through-hole leads marked CUST on the silkscreen.
  2. Install R3 as a flying component soldering one lead to R2's pad as shown above (this is the Vfb signal). Solder the other lead to a wire that connects to the Vdac signal at Low-Pass Filter's output.

Move the Slide Switch to the Custom position (same end as the CUST silk screen near the switch).

NOTE: If having Vout = 9V during power-up or software upload is not a concern, you can leave out the EN pull-down R6 and D5 wiring.

Solder 5 wires (3-5 inches) to VIN, GND, VOUT, EN and R3 to connect the Converter to the Prototype Board.

Code 1 - Set Vdac for Desired Vout

Set your desired output Vout in the loop() routine. The C code calculates the required Vdac for the desired Vout and writes the value to the PWM output pin. You can add two lines of code to step through voltages 3V to 9V in 1V increments. Or modify the code for any Vout range you wish.


/*
DAC Adjusts Power Supply Vout

DAC drives R3 added to gain resistors R2, R1.
*/

int ADCword0 = 0; // ADC value (counts)

float Vout = 0; // voltage (V)
float Vdac = 0;
float Vout_meas = 0; // measure VO via input A0

float R4 = 10000; // R divider for Vout Monitor
float R5 = 10000;
float Kdiv = 0.5;

float m = 1; // scale and shift of linear function: Vo = Vdac*m + b
float b = 0;

const int PWMout = 3; // Analog PWM Output pin
const int ENout = 5; // Digital EN pin for power supply

// the setup routine runs once *****************************
void setup() {
// initialize serial communication at 9600 bits per second:
Serial.begin(9600);

// digital output for PS enable
pinMode(ENout, OUTPUT);
digitalWrite(ENout, LOW); // DISABLE supply

// PWM digital pin for supply adjust
pinMode(PWMout, OUTPUT);
// pin 3 for PWM of 31372.55 Hz
TCCR2B = TCCR2B & B11111000 | B00000001;
// For SAFETY - avoid power-up voltages Vout_MAX
// write PWM out for Vdac_MAX for Vout_MIN
Vdac = 5;
analogWrite(PWMout, Vdac * 255 / 5.0);
delay(100); // delay (ms) for PWM settling

// ENABLE Supply
digitalWrite(ENout, HIGH);
delay(100); // delay (ms) for EN settling

// set coeff scale (m) and shift (b) for line equation Vo = Vdac*m + b
m = -1.216;
b = 9.056;

// set initial Vout
Vout = 3.0;

// R divider for Vout monitor
R4 = 10000;
R5 = 10000;
Kdiv = R5 / (R4 + R5);

}


// the loop routine runs continuously **********************
void loop() {

// step through Vout from 3V to 9V
Vout = Vout + 1.0;
if(Vout > 9.001) Vout = 3.0;

// select Vout and calc Vdac needed for desired Vout
Vout = 6;
Vdac = (Vout - b) / m;
// write analog PWM out
analogWrite(PWMout, Vdac * 255 / 5.0);
// wait for PWM and Supply settling
delay(1000); // delay (ms) for settling

// read analog input at pin A0
ADCword0 = analogRead(A0);

// convert to counts to volts: Vin = ADCvalue * Vref/2^N * 1/Kdiv
Vout_meas = ADCword0 * (5.0 / 1024.0) * 1/Kdiv;
// print out value to computer as ASCII
if(1){
Serial.print("Vo,Vdac,Vout_meas\t");
Serial.print(Vout,3);
Serial.print("\t");
Serial.print(Vdac,3);
Serial.print("\t");
Serial.println(Vout_meas,3);

}

}

DAC (PWM) Output

In setup(), you need to configure D3 as digital output and set the clock for a higher PWM frequency.

// configure digital pin as PWM output

pinMode(PWMout0, OUTPUT);

// pin 3 for PWM of 31372.55 Hz

TCCR2B = TCCR2B & B11111000 | B00000001;


Specify Vdac

In setup(), initialize the Scale (m) and Shift (b) values. (Get values from Excel Calculator.)

m = -1.216;

b = 9.056;

In loop(), you specify Vout, calculate Vdac needed for Vout and then write the value to the DAC.

// select Vout and calc Vdac needed for desired Vout

Vout = 6.0;

Vdac = (Vout - b) / m;

analogWrite(PWMout0, Vdac);


Monitor Vout

In setup(), enter the resistor divider used for Vout monitoring and calulate the gain.

R4 = 10000;

R5 = 10000;

Kdiv = R5 / (R4+R5);


In loop(), read the analog voltage at input A0 and convert the ADC counts into a voltage. Note: The R4, R5 divider gain (Kdiv) must be included to scale the reading to the actual voltage at Vout.

// read analog input at pin A0

ADCword0 = analogRead(A0);

// convert to counts to volts

Vout_meas = ADCword0 * (5.0 / 1024.0) * 1 / Kdiv;


Loop Through Voltages

If interested, you can add code to step through Vout from 3V to 9V. Comment out fixed Vout = 6.0;

Vout = Vout + 1.0;

if(Vdac > 9.001) Vout = 3.0;

// Vout = 6.0


Output Enable

The goal here is to avoid an output of 9V during power-up or sketch upload. Initially, the supply is Disabled by keeping EN = LOW with pull-down resistor. We'll first set Vdac to MAX for Vout MIN, then bring EN = HIGH.

In the setup() routine

// write PWM out for Vdac_MAX for Vout_MIN

Vdac = 5;

analogWrite(PWMout, Vdac * 255 / 5.0);

delay(100); // delay (ms) for PWM settling


// ENABLE Supply

digitalWrite(ENout, HIGH);

delay(100); // delay (ms) for EN settling

Test It!

scope-steps.jpg

Single Voltage Level

Let's test our adjustable supply at the lower range.

  1. Open the sketch "DAC-adjust-PS-1.ino"
  2. Set Vout = 3.0
  3. Hit Verify and Upload into the Arduino.
  4. Connect a Digital Volt Meter (DVM) leads to the Vout and GND.
  5. Does the DVM reading get close to 3.0V?
  6. The LED on the Converter PCB should be dimly lit.

Try the max voltage.

  1. Set Vout = 9V and hit Upload.
  2. Does the DVM reading get close to 9.0V?
  3. Does Converter LED get brighter.


Step Multiple Levels

Try looping through voltages 3V to 9V by 1V.

  1. Add the following lines of code before the Vdac = (Vout - b) / m statement
  2. Vout = Vout + 1.0;
  3. if(Vdac > 9.001) Vout = 3.0;
  4. Connect a DVM or Oscilloscope to Vout. Do the readings increment by 1V from 3V to 9V?
  5. Does the the LED get successively brighter?
  6. Do the Vdac print statements run the range from 5V to 0V?

You can loop over a smaller voltage or time range if you wish.

  1. Modify the following lines
  2. Vout = Vout + 0.1;
  3. if(Vdac > 5.501) Vout = 4.5;
  4. Change the loop delay from 1000 (ms) to 750, 500 or 250.
  5. delay(1000);

Calculate R1, R2, R3 - Excel

excel1.PNG

Download a handy Excel Calculator from eCircuitCenter. Apply it, modify it, try different values, customize for your own circuits!

STEP 1. Enter your desired Vdac and Vout input / output pairs that define the adjustment range.

  1. Vdac0 = 0V Vout0 = 9V
  2. Vdac1 = 5V Vout1 = 3V


STEP 2. Calculate Resistors

Choose R3 = 100k and then Excel calculates R2 and R1.

  1. R2 = (Vout0 - Vout1 ) / (( Vdac1 - Vdac0)/R3 )
  2. = 120 k
  3. R1 = Vref / ( Vout0/R2 + Vdac0/R3 - Vref/R2 - Vref / R3)
  4. = 13.26 k


STEP 3. Scale all resistors (optional) and select standard or available values.

  1. For example, Enter R1 = 68.1k, which is already on the PCB.
  2. Spreadsheet scales R2 and R3 by 68.1k / 13.26k.
  3. Lastly, enter nearest standard or available resistors R2 = 620k and R3 = 510k


STEP 4. Calculate ACTUAL m and b (equations above).

This allows you to calculate (in the code) the required Vdac for a desired Vout: Vdac = (Vout - b)/m.

  1. m = -1.216
  2. b = 9.056

Explore More!

Learn more from an article DAC Adjusts Vout on eCircuit Center. You can...

Run an LTSPICE Simulation.

  1. Learn how to model and run a SPICE simulation.
  2. Play in the sandbox - change values, see what happens, customize for your own design.


Understand how the equations for the R's were derived.

  1. I was surprised how a simple 3 resistor network presented a real analysis challenge.


Try a new application: How can you make a circuit that takes Vdac = 1V to 4V to adjust Vout = 12V to 5V (with Vref = 1.25V.)

  1. Use the Excel Calculator and LTSPICE file to create a solution.