Boost Switch Mode Supply Using Arduino

Introduction

Switch mode power supplies are everywhere.  If you are my age or older you remember that the power supplies that came with toys and small electronics years ago were heavy and underpowered.  Since switch mode took over power supplies are far lighter, more efficient, more powerful, and have less ripple.

The most common kinds of switch mode supply are boost and buck.  Buck lowers a dc voltage to another, lower voltage.  Boost converters, take a low voltage and convert it to a higher one.

Boosting a lower voltage to a higher one is something that can be handy. You may need a higher supply for an op-amp, or maybe you want to drive an N-Channel mosfet and need a small amount of current above your supply voltage.  Another common reason to do this is to drive LEDs in series from a battery.

In the past I had stayed away from this because it seemed difficult.  Winding inductors was a guessing game with no way of measuring them easily (you can check out my post here to solve that part of it, also check out this update for better code).  There are drop in ICs for this as well, but sometimes it’s nice to implement something with what you have lying around.

The Basic Circuit

 

The PWM signal switches T1.  During the “on” portion of the cycle, constant voltage is applied through L1.  Ideally resistance in this circuit is 0, so the current linearly increases at a rate of V/L. When T1 switches off, the energy stored in L1 is dumped through D1 into C1.  Conservation of energy applies, so the usual rules apply, just like with transformers. For example: 2 amps at 5 volts will give you 1 amp at 10 volts, minus losses.

Design Considerations

I’m going to use some cheap little small signal transistors, so I’m not going to drive a lot of amps.  My inductor is about 3.5 mH.  I want to drive about 20 mA at around 10 volts (about 4 of my white leds), so I need about 40 mA average at 5 volts.  if this were 50% duty cycle, and each time the inductor was being fully charged and discharged we would need to ramp linearly from 0 to 160 mA once per cycle.  Lets see how fast our current will rise.

\frac{1}{3.5\cdot 10^-3 \frac{V\cdot s}{A}} \cdot 5V \approx 1400 \frac{A}{s}

\frac{0.160 A}{1400 \frac{A}{s}}=1.14 \cdot 10^-4 s = 100 \mu s

So our “on” time in this case is around 1/10 of a millisecond.  That means we want to be running at at least 5 kHz or so.  We can run faster, then the current in the coil might not start from 0 each time, that should be ok too.   In reality I tried running this circuit at 5 kHz, and the result was a burned out transistor.  I’m not sure exactly why, but I assume turning off the coil at that current was too much for the transistor. More carefully designed circuits have “snubber” circuits around each switching transistor. We’ll run at 62.5 kHz like in my earlier fast PWM example, then the circuit works fine.  We will need to use the PWM registers directly for this.  I have an earlier example of fast PWM on arduino here.

Unless you know the load exactly and it never changes, it’s not possible to calculate exactly what duty cycle will provide the voltage or current you want.  I set up a basic form of this circuit and got about 60 V at the output with no load.

In my led driver circuit I’m going to make a simple constant current supply, by having feedback from a 1 ohm resistor go into the A0 pin.  We’ll use a simple “ramp until we get the voltage we need” algorithm for this.  There are better ways to do this but for the purpose of lighting up a few LEDs this will be fine.

Parts

Circuit

The circuit we are going to build is:

R1 is 10 ohm, but if you use a different value you simply have to change the constants in the source code.  Try to keep it small though, since this will kill efficiency fast. L1 in my case is 3.5 mH.  You’ll want something close to that.  For what it’s worth that was 40 turns on one of my toroids.  Inductance is proportional to turns squared, so 20 turns would be just a little under 1 mH, 80 turns would be about 12 mH.  I couldn’t get it to work right unless I put the battery directly to L1, connecting L1 to the regulator on the Nano didn’t seem to give me enough current.

Here is the source code, feel free to use it for whatever you want, commercial or non-commercial. (CC0 license):

 

float setpoint = .025 , output = 0;
float err =0.0;
float r1 = 10; 
float maxout=170;
float step = 1;
float aveCurrent = 0;
void setup() {
  // put your setup code here, to run once:


  pinMode(A0, INPUT);

  setpoint = setpoint*r1;
 analogReference(INTERNAL);
  
  pinMode(3, OUTPUT);
  pinMode(11, OUTPUT);
  TCCR2A = _BV(COM2A1) | _BV(WGM21) | _BV(WGM20);
  TCCR2B = _BV(CS20); // divide by 8
  OCR2A = 10; //start low

  Serial.begin(115200);
}

void loop() {
  float current = 0;
  for(int i = 0; i<50; i++)
  {
    current += analogRead(1);
    
    }
  current /= 50;
  current = (current*1.1/1024.0);
  aveCurrent = aveCurrent*.9 + .1*current;
  err = (current-setpoint);
  if(err<0) { output += step; } else { if(output>step)
    output -= step;
    }
    if(output > maxout)
    output = maxout;
    
    
  OCR2A = (int)output;
/* Serial.print(aveCurrent*1000);
  Serial.print("  ");
  Serial.print(err*1000);
  Serial.print("  ");
  Serial.println(OCR2A);*/                                                                                                                                                    
}

Conclusion

I hope you get a chance to play with this type of circuit.  It’s something most hobbyists don’t do themselves, but that is in all of our household gadgets.  I think it’s worth getting some hands on design experience just to learn how everything works.  If you do try it, be sure to have plenty of transistors on hand, I burned out a bunch!

Leave a Reply

Your email address will not be published. Required fields are marked *