Introduction: Make a Microcontroller-based Boost Converter

For a recent project, I needed to boost the output from a USB (high ampage charging) port from 5V up to 18V to power an amplified speaker. I decided to try rolling my own boost converter (mainly because playing with big inductors sounded cool). My first attempt was a dismal failure (it could only source about 10mA and I needed 600mA!) but, after reading TI's guide to calculating components, I managed to get it working pretty well. (I also converted the calculations in that guide into a spreadsheet to make it easier to work through it.)

It turns out that component selection is a reasonably big deal for a converter or this type. Even after you've got the right "headline" value for a component, there are other factors you need to worry about too...

Step 1: Basic Principle

Wikipedia has a good explanation of the principle but here's a quick guide:
  • The boost converter rapidly switches a switch on and off.  (My design runs at 65kHz.)
  • When the switch is closed (first diagram), it connects an inductor across the input supply while the diode blocks any current from flowing back from the output side.
  • The inductor charges up.  (Although it seems like shorting a coiled piece of wire across the input should waste a lot of power, the inductor actually stores up the energy in its core.)
  • When the switch opens, the inductor resists any change in current (and, shorting it across the supply means it has a lot of current going through it).  Since the output side has a much higher resistance than the switch, the inductor has to raise its voltage to keep the current flowing.  (Resisting change in current by changing their voltage is the magical property of inductors.)
  • The output capacitor charges up from the inductor plus the power supply at the higher voltage.
  • When the switch turns on again, the capacitor is charged at the higher voltage and powers the load until the next cycle.  Since power is only ever applied to the output side part of the time, there will always be a ripple on the output voltage.
  • If the switch is on for a relatively longer time in each cycle (it's duty cycle is higher) then the inductor stores up more energy, resulting in a higher output voltage when the switch turns off.  Controlling the duty cycle lets you adjust the voltage.
So much for the principle, how do you turn that into a real circuit?

Step 2: Choosing the Key Components

For exact values, I've put together a template Google spreadsheet that does the calculations from the TI guide. Below, I've tried to sum up the rules of thumb that I gleaned after reading that document and searching around.

Inductor
The inductor is the most important part of the circuit.

  • It's headline value is its inductance, measured in Henrys. The spreadsheet will help you calculate the right value. I recommend going for 1.5-2x the calculated value so you have some headroom.
  • You also need to check out:
    • The current rating, this needs to be enough to handle the peak current in the inductor (as calculated by the spreadsheet).
    • Shape: I went for a toroid because they're supposed to have low EMF interference. One source that I read said that bobbin inductors were the best bang for buck if you weren't worried about interference.
    • The core material, you want one that's suitable for a power inductor. I went for a toroid that was marketed as a power inductor. I believe it has a ferrite core.

I used this 150uH inductor.

Switch
This is the second most important piece of the circuit, and where I made a mistake first time around. A MOSFET is a good choice because it's easy to drive with a microcontroller. You need to look out for:

  • Rds(on) This is crucial, it's the resistance of the switch when it's turned on. My first attempt was scuppered by having a too-high value here. <10mOhm is ideal. If this is too high then the inductor won't be able to draw enough current and you'll waste power in the switch.
  • The Vgs(th) value, this is the voltage you have to apply to the gate of the transistor to turn it on. If you're using a 5V microcontroller, this needs to be 1-2V.
  • Vds(max), this is the maximum voltage the transistor can handle, go for the output voltage plus some safety margin.
  • Ids(max), the maximum current that the switch can handle. This needs to be bigger than the peak current according to the spreadsheet.

I used this switch.

Capacitors
The spreadsheet should calculate the minimum values for the capacitors in the circuit. I found that, powering an audio amp, I needed a much bigger output cap than was specified.

  • The capacitors in the output stage need to have a low ESR value for efficiency.

I chose a large, electrolytic capacitor with low ESR and then put in parallel with a 22uF ceramic capacitor in the hope of filtering the output further.

On the input side, I used the same setup.

Diode
The diode is fairly easy, just go for a Schottky diode that can handle the average current and has a low forward voltage (450mV seems to be the limit for non-exotic parts).

Microcontroller
I went for an ATTiny84A because it's available in through-hole packaging, it's not too big and the AVR GCC toolchain is pretty good. I followed this tutorial from Lady Ada to get the toolchain up and running and I used AVR Eclipse to develop the code. I needed fairly precise control of the hardware to get the PWM running at 65kHz so it might have been difficult with the more-abstract Arduino IDE.

Step 3:

Here's the circuit I came up with.

  • At its heart, the microcontroller (code to follow...) uses its PWM output to control the switch.
  • It monitors the output voltage using its ADC, via the feedback potentiometer.
    • If the voltage drops below the target, it increases the duty cycle of the PWM, increasing the current in the inductor and hence the output voltage.
    • If the voltage goes over the target, it decreases the duty- cycle.
    • the voltage can be adjusted by adjusting the pot.
  • The 440 ohm resistor on the output ensures that there's always some load on the converter. I found that value by trial and error. My input 5V power supply would shut down if I didn't draw enough load from it. You might be able to get away with a much larger resistance. It's essential to load the output though; with no load, the converter will become unstable and the inductor will put out a very large voltage.
  • The small capacitors in parallel with the large ones are filter capacitors. Large electrolytics have a relatively high resistance so putting a small ceramic or polymer cap in parallel helps to deal with transient spikes.
  • The 0.1uF cap on the ADC input is simply a filter.

Apologies for the poor-quality photos! I was so excited that it worked that I sealed it inside my project before taking a good shot.

Step 4: Microcontroller Code

I've put my working code up on Github.  It has a few parts:

These #defines and const declarations do compile-time calculations so that the code only needs to do simple uint8_t comparisons rather than floating point which is not feasible in a microcontroller.  Using const encourages the compiler to do the calculation at compile time and forces the type of the result to uint8_t.

#define PWM_FREQ 62500
#define PWM_RESOLUTION (F_CPU / PWM_FREQ)
#define MIN_DUTY_CYCLE 0.40
#define MAX_DUTY_CYCLE 0.80
const uint8_t MIN_PWM_LEVEL = PWM_RESOLUTION * MIN_DUTY_CYCLE;
const uint8_t MAX_PWM_LEVEL = PWM_RESOLUTION * MAX_DUTY_CYCLE;

#define VREF 1.1
#define DESIRED_VOUT 20.0
#define DIVIDER_RATIO 30.0
#define DESIRED_ADC_IN_V (DESIRED_VOUT / DIVIDER_RATIO)

const uint8_t DESIRED_ADC_RESULT = 255 * DESIRED_ADC_IN_V / VREF;

These define some useful utility macros so that the code is easier to follow:

#define DUTY_CYCLE_REG OCR0B

#define ADC_ENABLE() (ADCSRA |= _BV(ADEN))
#define ADC_START_CONVERSION() (ADCSRA |= _BV(ADSC))

The main function has an initial setup phase where it turns on the various peripherals that we'll need:

int main(void) {
    /* Set A7 as an output.  (Needed for PWM.) */
    DDRA |= _BV(DD7);
    PORTA = 0;

    /* Let input power stabilize... */
    _delay_ms(500);

    /*
     * Configure Timer0 as a fast PWM.  It will
     * - turn on the output pin at the start of each cycle
     * - turn it off when the value hits DUTY_CYCLE_REG
     * - wrap to 0 when it hits OCR0A
     */
    TCCR0A = _BV(COM0B1) | _BV(WGM01) | _BV(WGM00);
    OCR0A = PWM_RESOLUTION;
    /* Start with 40% duty cycle and ramp up to avoid inrush. */
    DUTY_CYCLE_REG = (uint8_t)(PWM_RESOLUTION * 0.40);
    /* Set Timer0 clock source to be main oscillator. This enables the timer. */
    TCCR0B = _BV(CS00) | _BV(WGM02);

    /*
     * Turn on the ADC,
     * - use internal voltage ref.
     * - configure ADC0 as our source
     * - left-adjust the result, 8-bits is enough for us
     * - disable digital input buffer on pin
     * - enable the ADC.
     */
    ADMUX = /* REF = */ _BV(REFS1) | /* INPUT = */ 0;
    ADCSRA |= /* PRESCALER = 16 = 2^ */ 4;
    ADCSRB |= /* LEFT-ADJUST */ _BV(ADLAR);
    DDRA &= ~_BV(DD0);
    DIDR0 |= _BV(ADC0D);
    ADC_ENABLE();
    _delay_ms(1);

Then, it simply loops, reading the analog value from the potentiometer and comparing it to its target:

while (1) {
      /* Wait for the Timer0 to overflow... */
      loop_until_bit_is_set(TIFR0, TOV0);
      /* End of our OFF period, should be peak voltage... */
      TIFR0 |= _BV(TOV0);  /* Clear the flag. */

      /* Check the output voltage. */
      ADC_START_CONVERSION();
      loop_until_bit_is_clear(ADCSRA, ADSC);
      uint8_t adc_result = ADCH;

      if (adc_result < DESIRED_ADC_RESULT &&
          DUTY_CYCLE_REG < MAX_PWM_LEVEL) {
        DUTY_CYCLE_REG++;
      }
      else if (adc_result > DESIRED_ADC_RESULT &&
               DUTY_CYCLE_REG > MIN_PWM_LEVEL) {
        DUTY_CYCLE_REG--;
      }
    }
}

Step 5: Final Thoughts/next Steps

Caveat emptor: I'm not SMPS expert, and I've only built one.  I welcome any feedback from experienced engineers.

One weakness in my current design is that it has no inrush current protection.  I actually had to add a 0.2ohm resistor in series with Vin to avoid tripping the protection circuit in the USB charger.

I had a go at measuring the efficiency of my circuit by adding a shunt resistor to the input supply and loading the output with a high wattage resistor.  The absolute limit seems to be putting out about 25V, where the efficiency drops to about 50%.  At 18V, I get a respectable 75% and at 12V it's more like 80%+.  

Comments

author
hanlin_y (author)2016-03-28

Great idea! I made a boost LED driver version of it for my bike light. When you have a strobe light, it extends the battery life and lets you use a smaller battery pack. Using boost lets you use a smaller circuit board too

If you want to use smaller inductors and capacitors you should use a 16 MHz or 20 MHz oscillator. It will increase the switching frequency.

In some of my prototypes, for some reason, the microcontroller shuts down whenever the boost converter turns on even at its minimum duty cycle. It might be caused by noises by improper layout. Once it worked perfectly on a bread board but shuts down on a prototyping board.

You could experiment with buck converters or making four voltage rails because the ATtiny84 has four PWM channels.

author
fasaxc (author)hanlin_y2017-04-07

Thanks for the tip; when I started out, I didn't realise how important the high frequency would be and I was too lazy to add a crystal :-)

author
hugojtc (author)2017-03-29

I have tried to make a step up to 32 or 36 volts. What do you advise me? Or a power supply from 220 to 36 volts.

author
fasaxc (author)hugojtc2017-04-07

The efficiency drops off the higher you try to boost it. 18V worked for me 5V to 36V might be too much.

This circuit isn't appropriate for reducing voltage. A transformer-based power supply would probably be better of 220->36V. Dealing with 220V is dangerous; you should consult an expert (or become one!).

author
guluva (author)2017-03-04

Does anyone have a code for this? Preferably for ATtiny85?

author
fasaxc (author)guluva2017-03-05

The code is in the instructable with a link to the github page. It's for an ATTiny84, which is pretty close to an 85.

author
RajeshR56 (author)2016-06-12

I am trying to build the same thing using an Arduino Uno, could you give me some preliminary tips on how to proceed ? I am a student and this would aid in my final year project.

author
fasaxc (author)RajeshR562016-06-12

My number one recommendation is to start simple. Break the problem down into a few pieces and solve each one separately then think about how to combine them.

You might want to start by reading a voltage using an analog input and writing that to the serial console.

Then try the other half of the circuit, try outputting a pulsed signal at a fixed rate.

Then put that together with the analog part of the circuit; you should be able to adjust the output voltage by changing the pulse rate.

Then start to put those pieces together and control the rate from the analog input.

One note: my code is for a more basic chip. It should be a lot easier to program an Arduino to do PWN and to read the input. Look up analogRead and analogWrite.

author
RajeshR56 (author)fasaxc2016-08-29

@fasaxc : I have managed to build up the circuit for a 19v input, 48v output circuit with current and voltage measurement. Could you get on a Skype call sometime since I need some clarifications on understanding how the PWM and duty cycle settings vary in the MPPT algorithm...

author
lindom2 (author)2016-03-31

what did you use to upload the code to the microcontroller. Will the usbasp programmer work?

author
SiewY (author)2015-12-02

Hi, this is a great project! But I have a confusion, how do you do the PWM frequency at 65kHz? Are you using any code or hardware to do that? I want to know how do you do that... Sorry if it is a silly question. I am doing a project and want to output a PWM but it is only 32kHz. I want to make it higher.

author
fasaxc (author)SiewY2015-12-03

Step 4 explains how to set the hardware PWM in fast PWM mode. The full code is on github. Note: you'll need to use the same chip and fuse settings to use my code or the register settings may be different.

author
RuthlessKarma (author)2015-09-16

This is an extremely useful project you have completed. Good Work. I am interested integrating this into a project of my own. Would you be willing to help me adjust the code to work with a standard Arduino (UNO)? I need additional functionality beyond the ATtiny and sketch writing is already a weak area for me.

author
fasaxc (author)RuthlessKarma2015-09-16

What's the project, are you sure you need a custom boost converter?

author
RuthlessKarma (author)fasaxc2015-09-17

Thank you for responding so quickly. It is appreciated. I feel that the boost converter is the best solution. The project is portable, (wearable in fact) and charging via USB is really the only practical solution. The only other option I have considered is developing a circuit that will break a series battery pack into parallel cells for charging and then back into series to drive the load. This solution is less elegant. Higher weight, more parts, more power loss, and the danger of shorting LiPos is simply unacceptable for a wearable project. I think keeping the batteries in their typical configuration is best while finding a method to charge them via USB. Thank you for your time and consideration.

author
DangerousTim (author)2015-04-30

should I be using a high wattage inductor?

author
fasaxc (author)DangerousTim2015-04-30

Inductors are usually rated by maximum current. You need an inductor that can handle the current you calculate.

author
Mayur Balwani (author)2014-12-17

Thank you very much for replying in such a short time and considering my request. I have opened the spreadsheet and plugged in the values of my supply voltage and calculated the values and now I am going to simulate it and see whether output is desired or not.

I'll request you to give me your email id so that I can contact you via email. I have a serious need of the help because I have a project pending in which I need this converter. So, please give me your email id. My email id is myrbalwani@gmail.com

I again appreciate you for your help. Thank you very much Sir !
Have a nice day !

author
Mayur Balwani (author)2014-12-17

I tried entering the values in a spreadsheet but the TI link seems to have expired and hence I am not getting the values. Would you please help me to design such converter for the input voltage of 3 volts and the output voltage of 5V and 500 mA ?

I am asking you to help me which inductor and capacitor values should I choose in order to get the regulated supply of 5V. My demands are Vmin 2.8 Volt and Vmax 3.2 volts for input and output voltage, as I mentioned, is 5V and output current is 500mA.

author
fasaxc (author)Mayur Balwani2014-12-17

Try this new spreadsheet link: https://drive.google.com/previewtemplate?id=1nVU-krZEd3Ta0ClVpX9M2rn8w1aDyzJ1ZLGZT4d1YG8&mode=public

author
fasaxc (author)Mayur Balwani2014-12-17

The boost converter article has moved to http://www.ti.com/lit/an/slva372c/slva372c.pdf. Afraid the spreadsheet seems to be broken. The custom formula I used to calculate SI prefixes is not working. I'm not sure how to fix it right now. You could try replacing the contents of the cells in column C: Where it says siToNum(<something>) replace it with <something> and same for column F, where it says formatSi(...)

author
Mayur Balwani (author)2014-12-17

I tried entering the values in a spreadsheet but the TI link seems to have expired and hence I am not getting the values. Would you please help me to design such converter for the input voltage of 3 volts and the output voltage of 5V and 500 mA ?

I am asking you to help me which inductor and capacitor values should I choose in order to get the regulated supply of 5V. My demands are Vmin 2.8 Volt and Vmax 3.2 volts for input and output voltage, as I mentioned, is 5V and output current is 500mA.

author
Mayur Balwani (author)2014-12-17

I tried entering the values in a spreadsheet but the TI link seems to have expired and hence I am not getting the values. Would you please help me to design such converter for the input voltage of 3 volts and the output voltage of 5V and 500 mA ?

I am asking you to help me which inductor and capacitor values should I choose in order to get the regulated supply of 5V. My demands are Vmin 2.8 Volt and Vmax 3.2 volts for input and output voltage, as I mentioned, is 5V and output current is 500mA.

author
daniel212 (author)2014-04-16

Hi guys, need some help Using pic16f88 )
I have already created a basic pwm on flowcode but need to add some ADC function which will then vary the pwm depending on ADC output value.

I intend adding a voltage divider to the output section of a converter,
which will be fed to the analogue input of the PIC16f88 pin (eg AN1).

the microcontroller should increase the duty cycle of the PWM
whenever the input to the AN1 is less than 3V hence to compensate for
any output voltage sag. And should decrease the duty cycle of the PWM
whenever the input to the AN1 is greater than 3V.
Am a novice at programming PIC Any help or advise will be appreciated.

author
kuk1n (author)2013-11-17

Hello, this is an excellent tutorial. This is exactly what i need but my application is very space limited. Would it be possible for you to create the code for ATTINY85 as well? I would port it myself, but I am struggling to understand it.

Thank you

author
fasaxc (author)kuk1n2013-11-17

Anything in particular I can help you understand? To make it work on the '85 you'd probably need to change the pin assignments. E.g. the OC0A pin is shared with PB0 instead of PA7 so "DDRA |= _BV(DD7);" should be "DDRB |= _BV(DD0);". I think the timer code should all work as-is because the peripherals are usually very similar.

author
kuk1n (author)fasaxc2013-11-18

Thank you for fast reply!
Well to be honest I did not get AVR-C in general, but I have done some homework and I should get it working in some time.

For anyone struggling with this as well I recommend excellent tutorials by humanHardDrive on youtube. First episode available at: http://www.youtube.com/watch?v=9ADxPRjZI4Q

Thank you again :)

author
ro0ter (author)2013-10-01

Quite nice calculator you`ve put out there!

The efficiency is calculated as a ratio between the provided power and the maximum consumed power: (18V * 0.4A) / (5V * 2.1A) = 7.2 / 10.5 = 68.57..%. Yet, this cannot be simply calculated, one has to effectively measure the consumed input power for a required output power.

Again, excellent spreadsheet!

author
fasaxc (author)ro0ter2013-11-17

Those entries were just a quick back-of envelope. The efficiency does vary with the load.

author
ro0ter (author)2013-10-01

This is a nice tutorial, just accidentally started reading it :).

Please perform the following modifications:

- original text:
"The output capacitor charges up from the inductor at the higher voltage."
- modified text:
"The output capacitor charges up from the inductor PLUS THE POWER SUPPLY at the higher voltage."

That`s the reason why buck boost converters work: the inductor stores energy in form of a magnetic field (while it`s in parallel with the power supply) and when the switch opens, the inductor will be in series with the power supply unleashing its stored energy "in series with the initial power source".

About This Instructable

48,387views

64favorites

License:

More by fasaxc:Playable Giant Gameboy CostumeHardwood combCrumpets
Add instructable to: