Power Electronics

Digital Feedback Controls Supply Voltage Accurately

An 8051-compatible microcontroller, an ADC and a DAC implement a digital feedback loop that controls the output of a stepdown regulator, while correcting for offsets, drifts and changing loads.

For the PDF version of this article, click here.

The goal of this project was to design and build an efficient power supply system whose output voltage (VOUT) could be accurately set to a digitally selected value. To ensure an accurate VOUT, our system uses digital closed-loop feedback. This feedback corrects for offsets and drifts in the power supply, as well as for changing loads — up to 600 mA in this case — on its output. In addition to an adjustable stepdown regulator, the power supply system comprises an analog-to-digital converter (ADC), a digital-to-analog converter (DAC), a voltage reference and a microcontroller (µC).

In most adjustable dc-dc converters, a resistor network on the FB pin adjusts the regulator's VOUT (Fig. 1). In our system, the DAC voltage (VDAC) changes the bias of this resistor network to adjust the regulator's VOUT. The ADC monitors VOUT and communicates the sampled meas-urements to the µC. The µC controls the feedback loop by reading the digitized version of VOUT supplied by the ADC and varying VDAC to obtain the desired VOUT. To keep the system as simple as possible, the desired VOUT value is sent to the µC over an RS-232 bus (i.e., sent from a PC's serial port).

This system is useful in any number of embedded system applications requiring a controlled VOUT. A specific example is a power supply for an application-specific integrated circuit (ASIC), a digital signal processor (DSP) or a µC where a known supply voltage is needed to run the processor at a desired speed. Adjusting the supply voltage to the minimum required voltage for a given speed reduces the processor's power consumption and keeps the device cooler.

Our system also replaces the power supply circuit shown in Fig. 2, which uses an analog switch to select between possible VOUT values. Switch settings resulting in a higher VOUT could allow a processor to run at full speed, while switch settings resulting in a lower VOUT could allow a processor to run in sleep or standby modes. Due to regulator offsets and component tolerances, VOUT in conventional regulators is usually set higher than required by the system it is powering to guarantee VOUT is above the minimum voltage needed. Our system's digital feedback loop eliminates the need for this VOUT margin.

Bill of Materials and Development Tools

For our system's main power supply, we chose a low-quiescent current, 1.25-V to 5.5-V adjustable stepdown regulator, the MAX1692, which is capable of delivering output currents up to 600 mA. The evaluation kit for this stepdown regulator provides a tested layout and suggested components for the input capacitor, output capacitor and power inductor.

To bias the resistor network on the stepdown regulator's feedback pin, we chose a low-power, 12-bit DAC, the MAX5302, capable of driving loads up to 2.5 mA. The DAC's reference is supplied by a 2.5-V source. The regulator's output voltage is read using a low-power, 12-bit ADC, the MAX1286, with an auto-shutdown feature that reduces power consumption between conversions. The ADC's reference is supplied by a high-accuracy, 5-V voltage reference, the MAX6126. Both the ADC and DAC communicate via an SPI interface.

The high-accuracy voltage reference includes output-sense and ground-sense pins that we routed to the ADC's reference and ground pins. Routing the sense pins in this manner ensures that the ADC has the highest accuracy reference voltage, which is important.

The µC we selected, the DS89C420 from Maxim/Dallas Semiconductor, is a high-speed, 8051-compatible µC clocked using a 32-MHz crystal. Most of the instructions performed by this µC require only one instruction cycle, giving our processor the ability to run at nearly 32 MIPS. The µC is in-circuit programmable through J1 (Fig. 3). The DS89C420/430/440/450 family's user guide describes how to add in-circuit programmability to a design that allows firmware to be downloaded into the µC using any PC serial communication software (i.e., Microsoft HyperTerminal). The firmware for the C was written in µC and compiles using the free Small Devices C Compiler (SDCC) development tool available from Sourceforge at http://sdcc.sourceforge.net.

Analog Circuit Design

To calculate the values of R1, R2 and R3 (Fig. 4) needed for the resistor network, we began by assuming that the current into the FB pin (IFB) was negligible — specified as 50 nA maximum in the MAX1692 data sheet. Next, we set R2 to 49.9 kΩ. With the voltage at the FB pin being 1.25 V, the current I2 is 25 µA — well above 50 nA — thus justifying the decision to treat IFB as negligible. Finally, we calculated R1 and R3 as follows:

I2 = I1 + I3

When the VDAC is equal to its maximum, 2.5 V, the stepdown regulator's VOUT should be equal to its minimum, 1.25 V. Substituting these values in Eq. 1 gives:

The R1 term disappears and we easily calculate R3 to be 50 kΩ. When VDAC is equal to its minimum, 0 V, VOUT should be equal to its maximum, 5 V. Substituting these values as well as the calculated value for R3 into Eq. 1 gives:

Solving for R1 gives a value of 75 kΩ.

The ADC samples VOUT and communicates this sampled voltage to the µC using its SPI interface. This operation closes the digital feedback loop.

Accuracy Versus Precision

The digital feedback loop in our power supply system presents an interesting case of accuracy versus precision. In engineering (or at least in this article), accuracy refers to the ability to obtain a correct measurement while precision refers to the ability to obtain repeatable measurements.

Because the µC will vary VDAC in response to the ADC's samples of VOUT, the circuit does not require a DAC with a good integral nonlinearity (INL) rating, nor does it require low-tolerance resistors for the FB pin's resistor network. What the circuit must have, however, is a DAC with a good differential nonlinearity (DNL) rating, allowing it to increment and decrement its VOUT in fine steps. Both the DAC and the resistor network must therefore be high-precision devices, but not necessarily high accuracy. An ADC that demonstrates high accuracy as well as high precision is necessary, however, because it is measuring the output voltage of the system and using this voltage as the feedback source. Excellent INL and DNL ratings are therefore a must for the ADC.

The INL of an ADC or a DAC is the deviation of the values on an actual transfer function from a straight line representing the ideal transfer function. The DNL is the difference between an actual step width and the ideal value of 1 least significant bit (LSB). Having a DNL less than 1 LSB guarantees no missing codes and a monotonic transfer function.

An ADC or DAC is monotonic when its digital output code always increases/decreases as the analog value increases/decreases. Using both a DAC and ADC that are monotonic is crucial to preventing oscillations in the stepdown regulator's VOUT.

Digital Circuit Design

“Bit-banging” refers to a technique in which a specified group of I/O pins are programmed to collectively function as a serial interface. The DAC and ADC communicate with the µC using a bit-banged SPI bus (Listing 1). On the SPI bus, the µC is the master and the DAC and ADC are the slaves. Five of the C's pins are used to represent SPI clock (SCLK), master out/slave in (MOSI), master in/slave out (MISO), ADC chip select (CSADC) and DAC chip select (CSDAC). All three ICs on the bus share the SCLK line. To maximize communication speed, when possible, a 32-MHz crystal feeds the µC's system clock.

The µC firmware receives the desired level of VOUT from a PC's serial port. An RS-232 transceiver (MAX3311) converts the serial messages from RS-232 levels to TTL/CMOS levels.

Layout Considerations

The system was carefully designed to minimize errors due to pc board layout. Wide copper traces connect all passive components — the bypass capacitor, compensation capacitor, input capacitor, output capacitor and power inductor — to the stepdown regulator. These passives, as well as the resistor network connected to the FB pin, were placed as close to the stepdown regulator as possible. This reduces pc board trace impedance and noise. A large ground plane on the top and bottom layers of the regulator keep the IC cool when driving heavy loads. The evaluation kit for the MAX1692 may be used as a template.

For signal integrity reasons, it was important to run the analog and digital lines as far away from each other as possible. To achieve this, we placed the DAC and ADC close to the stepdown regulator and used short lines for all analog connections. The digital lines were then safely routed in the other direction toward the µC. We placed the voltage reference as close to the ADC as possible. The sense lines, which provide voltage feedback for the voltage reference, were routed using short isolated traces to the REF and GND pins of the ADC. This was particularly important because our system requires the ADC, more than any other device, to have the highest accuracy.

Significant effort was taken to make certain that no high-speed traces were routed under the µC. Also, the 32-MHz clock circuit was placed close to the µC's crystal input pins with short traces for all connections. As with all pc board layouts, care was taken not to allow 90-degree bends in traces, and every IC was bypassed with a 0.1-µF ceramic capacitor placed as close as possible to their supply pins. We minimized the number of vias on digital signal lines whenever possible and eliminated the vias on the analog signal lines altogether. Finally, we chose surface-mount packages for all components.


The µC firmware for this system receives the desired VOUT from a PC's serial port. This desired VOUT corresponds to the stepdown regulator's VOUT as sampled from the ADC. Since the byte sent to the µC is 8 bits and the ADC has 12-bit resolution, the byte is shifted to the left by 4 bits (equivalent to multiplying by 16). The 4 LSBs created by the shift are set at zero. This simple hack simulates a real system that would transfer an actual 12-bit value to the µC.

We wrote the firmware in C. Its “main” function is shown in Listing 2. When the µC powers on, the firmware initializes the pins used for the bit-banged SPI interface. Following this, the firmware initializes the serial port, allowing it to generate an interrupt after it receives a byte from the PC.

After initialization, the firmware enters the program loop, which is repeated continuously. The first step in the program loop calls the function that receives a sample from the ADC using the bit-banged SPI interface (Listing 1). Next, the µC compares the ADC sample with the desired ADC result. If the measured result is lower than the desired result, the DAC output variable is decremented by one. And if the measured result is higher than the desired result, the DAC output variable is incremented by one. Before the program loop restarts, the µC transfers the value of the DAC output variable to the DAC (Listing 1), again using the bit-banged SPI port.

Bit-banging the SPI interface to the ADC is not as straightforward as just sampling bits from the MISO pin. As with many ADCs, the interface is responsible for the sample conversion timing, and thus the µC holds the SPI chip-select line high for 1.4 µs (sample acquisition) and then low for 3.7 µs (sample conversion), as shown in Listing 1.

The firmware for this project was written to be simple and portable. Ways to optimize the firmware are given later in this article.


Even at full load, our system was able to accurately control the regulator's output voltage within 1% of the desired voltage. Feedback from the ADC allows the system to account for load, offsets and drift on the output voltage, thus enabling this level of accuracy.

Figs. 5a and 5b show the results of our adjustable-voltage power supply with a 1-mA load on VOUT. Fig. 5a shows VOUT and VDAC during a 4.5-V to 1.5-V transition on VOUT, while Fig. 5b shows VOUT and VDAC during a 1.5-V to 4.5-V transition on VOUT. These two graphs indicate that VOUT decreases at a much lower rate than VOUT increases. This is caused by the discharging of the high value output capacitor (Fig. 4) at the stepdown regulator's output. The regulator is able to supply current to charge the capacitor quickly, but the load is unable to discharge the capacitor at a rapid rate.

Figs. 6a and 6b show the same transitions as in Fig. 5, but with a 350-mA load on VOUT. Note that the rates are much closer because the 350-mA load is large enough to quickly discharge the stepdown regulator's output capacitor. Therefore, having a sufficient load on the regulator's output voltage allows VOUT to increase and decrease at a similar rate.

Even though voltage is accurately controlled, the graphs reveal certain problems with our system. Fig. 5a shows that the feedback system can cause overshoots and undershoots. This happens because of the speed of the program loop in the firmware. Fig. 5a shows that VDAC increases to its maximum value before VOUT reaches its desired value. When VOUT finally does reach its desired value, VDAC must decrease; the time it takes to decrease this voltage causes a slight undershoot on VOUT. Ideally, VDAC would increase at the same rate VOUT decreases (and settles). However, as demonstrated earlier, low output loading will reduce the rate at which VOUT decreases, preventing it from compensating for rapid successive increases in VDAC.

The system also requires more than 100 ms to make large voltage changes on the regulator's output. This occurs because the firmware increases and decreases VDAC by a single LSB after every ADC sample. To change VOUT from 5 V to 1.25 V, the µC must instruct the 12-bit DAC to increment its output voltage 4095 times and must also sample VOUT 4095 times (each sample requiring acquisition and conversion time for the ADC).

Numerous books have been written about control systems and how to implement them in firmware. The following section describes some simple ways to better control the digital feedback loop.

Customizing the System

If the 1.25-V to 5-V range of this system doesn't meet your design requirements, you can use most types of adjustable dc-dc converters while employing the same design methodology and calculations. For example, replacing the adjustable stepdown regulator used here with an adjustable stepup regulator would allow a maximum voltage higher than the supply voltage (although the lower limit would be VIN). Choosing a stepdown dc-dc converter with a lower internal reference at the FB pin comparator (Fig. 1) would allow a lower minimum voltage.

In the previous section, we discussed problems caused by the firmware-controlled digital feedback loop (Listing 2). You can reduce the effect of these problems by controlling the speed of the digital feedback loop. A simple way of slowing down the system is to insert firmware delays in the program loop. These delays can be added inside each “if” statement in the program loop (Listing 2), allowing the firmware to use one delay when increasing VDAC and another when decreasing VDAC.

Speeding up the feedback loop allows the system to react more quickly to changes on VOUT. The three following techniques can easily improve the firmware speed. First, if the desired ADC input is much higher or much lower than the sampled ADC input, the DAC can adjust VDAC by more than 1 LSB. Second, when a new desired ADC input is received by the system, the µC can set VDAC to a calculated value (using either a lookup table or a mathematical expression) that is known to produce a VOUT close to the desired value. Then the digital feedback loop uses its normal operation (Listing 2) to adjust the accuracy of VOUT. Finally, the program loop can be made more efficient by using bit-addressable variables for the “dacVout” and “adcVinActual” variables in the C firmware (Listing 1). All 8051-compatible µCs allow a small amount of internal RAM to be bit-addressable, and the use of this RAM reduces the time to execute the expressions for reading and writing to the MISO and MOSI pins. Note, however, that the SDCC compiler does not directly support bit-addressable variables (except with special function registers).

A more drastic method to increasing the speed of the feedback loop, such as using a successive-approximation register (SAR) approach, could also be implemented. But using this method would require careful control of the speed of the feedback loop and could get complicated if loads vary.

Whenever experimenting with the feedback loop, keep in mind that you are trying to keep the speed of the loop the same as the settling time of the stepdown regulator's output voltage. A system that is too fast or too slow leads to instability, oscillations or sloppy accuracy at the output.

Editor's Note

For all software and firmware for this article, please e-mail [email protected].

Listing 1

This portion of the C firmware sends and receives data via the bit-banged SPI interface. The “writeDacVout” function outputs a 16-bit value to the DAC. The “readAdcVin” function receives a 16-bit value from the ADC. The “SCLK_SET” and “SCLK_CLR” commands are macros that set and clear the SPI clock line. The “no operation” (nop) delays are included to ensure that the C does not exceed the maximum communication speed of the DAC or the ADC.


unsigned int dacVout = 0×0FFF; // Current DAC output code

unsigned int adcVin = 0×0000; // Desired ADC voltage

unsigned int adcVinActual; // Actual ADC voltage


sbit at 0×A5 DAC_CS;

sbit at 0×A2 ADC_CS;

sbit at 0×A3 SCLK;

sbit at 0×A4 MOSI;

sbit at 0×A1 MISO;


#define PAUSE _asm nop nop nop _endasm;





* writeDacVout - bit bang the DAC Vout value to the

* DAC's SPI port. Assumes SCLK and MOSI are low


void writeDacVout()

{DAC_CS=0; // Init DAC SPI

MOSI=(dacVout&0×0800)!=0; SCLK_SET; SCLK_CLR; // Bit 11

MOSI=(dacVout&0×0400)!=0; SCLK_SET; SCLK_CLR; // Bit 10

MOSI=(dacVout&0×0200)!=0; SCLK_SET; SCLK_CLR; // Bit 9

MOSI=(dacVout&0×0100)!=0; SCLK_SET; SCLK_CLR; // Bit 8

MOSI=(dacVout&0×0080)!=0; SCLK_SET; SCLK_CLR; // Bit 7

MOSI=(dacVout&0×0040)!=0; SCLK_SET; SCLK_CLR; // Bit 6

MOSI=(dacVout&0×0020)!=0; SCLK_SET; SCLK_CLR; // Bit 5

MOSI=(dacVout&0×0010)!=0; SCLK_SET; SCLK_CLR; // Bit 4

MOSI=(dacVout&0×0008)!=0; SCLK_SET; SCLK_CLR; // Bit 3

MOSI=(dacVout&0×0004)!=0; SCLK_SET; SCLK_CLR; // Bit 2

MOSI=(dacVout&0×0002)!=0; SCLK_SET; SCLK_CLR; // Bit 1

MOSI=(dacVout&0×0001)!=0; SCLK_SET; SCLK_CLR; // Bit 0


DAC_CS=1; // Reset DAC SPI}


* readAdcVin - bit bang the ADC Vin value from the ADC's

* SPI port using the MISO pin and save it as adcVinActual.

* Assumes SCLK and ADC_CS have been low for tmin.


void readAdcVin()


SCLK_SET; adcVinActual =MISO?0×0800:0; SCLK_CLR; // BIT 11
SCLK_SET; adcVinActual|=MISO?0×0400:0; SCLK_CLR; // BIT 10
SCLK_SET; adcVinActual|=MISO?0×0200:0; SCLK_CLR; // BIT 9
SCLK_SET; adcVinActual|=MISO?0×0100:0; SCLK_CLR; // BIT 8
SCLK_SET; adcVinActual|=MISO?0×0080:0; SCLK_CLR; // BIT 7
SCLK_SET; adcVinActual|=MISO?0×0040:0; SCLK_CLR; // BIT 6
SCLK_SET; adcVinActual|=MISO?0×0020:0; SCLK_CLR; // BIT 5
SCLK_SET; adcVinActual|=MISO?0×0010:0; SCLK_CLR; // BIT 4
SCLK_SET; adcVinActual|=MISO?0×0008:0; SCLK_CLR; // BIT 3
SCLK_SET; adcVinActual|=MISO?0×0004:0; SCLK_CLR; // BIT 2
SCLK_SET; adcVinActual|=MISO?0×0002:0; SCLK_CLR; // BIT 1
SCLK_SET; adcVinActual|=MISO?0×0001:0; SCLK_CLR; // BIT 0}

Listing 2

This portion of the power supply's C firmware, written in C, provides the “main” function for the firmware. The function initializes the system and runs the program loop, which is responsible for controlling the output voltage of a stepdown regulator.


void main(void)

{ // 1. Init I/O and variables
SCLK = 1;
MOSI = 0;
MISO = 1;
ADC_CS = 0;
DAC_CS = 1;
// 2. Init Serial Port
EA = 0; // Enable global interrupt mask
SCON1 = 0×50; // Set SCI_1 to 8N1, Rx enabled
TMOD |= 0×20; // Set Timer 1 as Mode 2
TH1 = 0×DD; // Set SCI_1 for 2400 baud
TR1 = 1; // Enable Timer 1
ES1 = 1; // Enable interrupts for SCI_1
EA = 1; // Disable global interrupt mask
// 3. Program loop…
while (1){ // 3.1 Read ADC to get actual ADC Vin

// 3.2 If actual ADC vin < desired ADC Vin
if ((adcVinActual < adcVin) && (dacVout!=0×0000))
dacVout--; // Increase Stepdown voltage
// 3.3 If actual ADC vin > desired ADC Vin
else if ((adcVinActual > adcVin) &&

dacVout++; // Decrease Stepdown voltage
// 3.4 Output DAC Vout voltage
writeDacVout(); } }

Hide comments


  • Allowed HTML tags: <em> <strong> <blockquote> <br> <p>

Plain text

  • No HTML tags allowed.
  • Web page addresses and e-mail addresses turn into links automatically.
  • Lines and paragraphs break automatically.