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!

Update on Inductance Meter

It seems I may have been incorrect with my math.  The resonant frequency from the formula for a damped oscillator I was using does not match the frequency the circuit rings at.  I did improve the code a little though, by using timer1 directly instead of micros().  This significantly improves the resolution of the measurement.

 

//this is based on a measurement technique from
//reibot.org, the parts count has been reduced by using the avr internal comparator


double pulse, frequency, capacitance, inductance;
bool detected = false;
long timeStamp[4];
unsigned int tcnt[4];
int sample = 0;


void setup(){
Serial.begin(115200);
pinMode(11, INPUT);
pinMode(13, OUTPUT);
Serial.println("Why hello!");
delay(200);

//set up the comparator and the interrupts for it
ADCSRB = 0;           // (Disable) ACME: Analog Comparator Multiplexer Enable
  ACSR =  bit (ACI)     // (Clear) Analog Comparator Interrupt Flag
        | bit (ACIE)    // Analog Comparator Interrupt Enable
        | bit (ACIS1);  // ACIS1, ACIS0: Analog Comparator Interrupt Mode Select (trigger on falling edge) AIN0 is D6 AIN1 is D7 

//set up timer1 instead of using micros();
TCCR1A = 0; //this kills some PWM pins, but it allows timer1 to count all the way to 65535
TCCR1B = bit (CS10);

}
ISR(ANALOG_COMP_vect )
{
  timeStamp[sample] = micros();
  tcnt[sample] = TCNT1;
  if(sample < 3)
  {
    sample++;
    }
}
void loop(){
digitalWrite(13, HIGH);
delay(5);//give some time to charge inductor.
digitalWrite(13,LOW);






///comparator stuff here

pulse = 0;

 sample = 0;
 delay(500);
 if(sample < 1)
 {
  Serial.print("time out\n");
  return;
  }
 pulse = (tcnt[1]-tcnt[0])/16.0;
 Serial.println(timeStamp[0]);
  Serial.println(timeStamp[1]);
   Serial.println(tcnt[0]);
    Serial.println(tcnt[1]);

//end comparator stuff
  
capacitance = 2.2E-6; //insert capacitance here im calibrating to a known inductor, the .95 is my fudge factor. 
frequency = 1.E6/(pulse);
inductance = 1./(capacitance*frequency*frequency*4.*3.14159*3.14159);
inductance *= 1E6; //note that this is the same as saying inductance = inductance*1E6
Serial.print("High for uS:");
Serial.print( pulse );
Serial.print("\tfrequency Hz:");
Serial.print( frequency );
Serial.print("\tinductance uH:");
Serial.println( inductance );
delay(20);
}

Frequency of a Damped Oscillator (RLC Circuit)

In my last post I mentioned that the frequency of a damped oscillator is not actually the same as of an undamped oscillator.  That makes the assumptions for measuring inductance I used sadly incorrect.  I wanted to briefly run down the math on how to do the calculation correctly:

Frequency of an undamped (perfect) LC oscillator: \omega_0=\sqrt{\frac{1}{LC}}

Frequency of a damped oscillator:

Wikipedia page  informs us the formula for the frequency of a tank circuit taking into account the resistance of the coil is:

\omega = \sqrt{\frac{1}{LC}-(\frac{R}{L})^2}

I’m too lazy to solve equations since grad school.  So I typed this into my TI-89. I got:

L=\frac{\sqrt{1-4C^2R^2\omega^2}+1}{2C\omega^2}

 

In order to use this we can pulse through the resistor and measure how much voltage is dropped through the tank circuit.  At DC the capacitor is an open, so that will tell us the resistance of the inductor, which should be the only non-negligible part of this.  My R1 is 150 ohms.  I measured one of my 1/4 Watt inductors at 20 ohms.  So, I expect to measure around .6 mV, certainly not more than a volt or so.  That means I’ll do better using the internal voltage reference on the arduino.

I’ll code this up and modify the circuit and we’ll try again in the next post.

How to Measure Inductance With an Arduino

Circuit

I recently found myself wanting to wind my own toroidal inductor.  Unfortunately I had no datasheet on the toroid cores I had purchased from Amazon: uxcell 22mm x 14mm x 8mm Power Transformer Ferrite Toroid Cores Green 10 Pcs

A while back I had tried to measure an air conditioner capacitor and ended up doing it with an Arduino, so I thought maybe a similar trick might work for inductors.  It turns out it is slightly more complicated with an inductor.  I based my work off of this blog post:  https://reibot.org/2011/07/19/measuring-inductance/

The comments stated that it may work with the built in comparator of the Arduino instead of the LM339.  My variant is as follows:

R1 is 150 ohms, but the value isn’t necessarily critical.

Powered over USB and outputs to the serial terminal.  It only takes a few minutes to put together and the only parts required are a resistor, a diode, and a 2.2 uF cap.  You can use another value if you want and the range of measurement will change.  You will also have to edit the source code to match.

Code


//this is based on a measurement technique from
//reibot.org, the parts count has been reduced by using the avr internal comparator

double pulse, frequency, capacitance, inductance;
bool detected = false;
long timeStamp[4];
int sample = 0;
void setup(){
Serial.begin(115200);
pinMode(11, INPUT);
pinMode(13, OUTPUT);
Serial.println(“Why hello!”);
delay(200);
ADCSRB = 0; // (Disable) ACME: Analog Comparator Multiplexer Enable
ACSR = bit (ACI) // (Clear) Analog Comparator Interrupt Flag
| bit (ACIE) // Analog Comparator Interrupt Enable
| bit (ACIS1); // ACIS1, ACIS0: Analog Comparator Interrupt Mode Select (trigger on falling edge) AIN0 is D6 AIN1 is D7

}
ISR(ANALOG_COMP_vect )
{
timeStamp[sample] = micros();
if(sample < 3)
{
sample++;
}
}
void loop(){
digitalWrite(13, HIGH);
delay(5);//give some time to charge inductor.
digitalWrite(13,LOW);

///comparator stuff here

pulse = 0;

sample = 0;
delay(500);
if(sample < 2)
{
Serial.print(“time out\n”);
return;
}
pulse = (timeStamp[1]-timeStamp[0]);

//end comparator stuff

capacitance = 2.2E-6*.92; //insert capacitance here im calibrating to a known inductor, the .95 is my fudge factor.
frequency = 1.E6/(pulse);
inductance = 1./(capacitance*frequency*frequency*4.*3.14159*3.14159);
inductance *= 1E6; //note that this is the same as saying inductance = inductance*1E6
Serial.print(“High for uS:”);
Serial.print( pulse );
Serial.print(“\tfrequency Hz:”);
Serial.print( frequency );
Serial.print(“\tinductance uH:”);
Serial.println( inductance );
delay(20);
}

Theory

The capacitor and the inductor in parallel form a resonant circuit.  When a pulse of current goes through this, part of the energy goes into making the circuit oscillate or “ring”.  I took a photo of what this looks like on my low cost oscilloscope:

The code sends a pulse through the resonant circuit.  Using the comparator interrupt, it gets a time stamp with micros() on the next 3 falling edges.  The time difference between the first 2 falling edges is one period, or 1/f.  Using the formula for resonance of a harmonic oscillator it calculates the inductance.

The blog post I used as a reference for this incorrectly states that the frequency stays the same regardless of the resistance of the inductor.  Unfortunately, a damped harmonic oscillator does not resonate at the same frequency as a perfect one.  If there is any interest I might make a version of this circuit that measures resistance first and corrects for this.  Otherwise this is close enough for most purposes, especially if you have a good, low resistance, inductor.

 

Tesla Coil Build

I’d like to walk through the build of a musical tesla coil.  Over all I would give this kit a 9 out of 10 rating.

The instructions were only in Chinese, but the schematic and the image were clear enough that I got it built anyway.  I put a link to purchase a very similar kit on amazon below.  I hope you’ll give it a go.  You can also find the kit on aliexpress for significantly cheaper if you are patient and cheap.

Here is a photo of the schematic it came with:

I buzzed out some points and found the schematic is actually completely wrong though. For one, LED1 isn’t there, it goes from the base of Q2 to ground.  I’m pretty sure it is supposed to go the other way as well, to protect the base from large negative voltages.  I tried to create a correct schematic but I should have started before assembly. The board is pretty simple, but with all the parts soldered on already it’s a bit hard to create the correct schematic.

This is the finished item. The coil just sits there, so you will want to glue it on with something. Over all it’s a great kit and it really plays sound, though somewhat terribly.  Plasma speakers are usually only used for the high end though, so you might actually integrate one of these into a speaker box as a tweeter for fun.

The main problems were the instructions, and the schematic being incorrect.  It came with a small neon bulb you can watch light up when you hold it close.  That was definitely fun to play with. It does burn about 15 Watts for almost no sound output, but it’s a novelty anyway.

You can see the arc at the top pretty clearly.  This has really got me thinking and I think I’m going to try to construct a small tesla coil without the kit at some point just to understand the schematic better.

Check out my video as well:

Negative volts in arduino

The simplest charge pump

If you read my last post you know how to get fast PWM off pin 11 (or pin 3) without messing up your millis() and delay() functions.  Keep in mind this is still using up one of your timers, so pin 3 and 11 should not be used for analogWrite() if you use this method.

I promised a quick and easy answer to the question “how do I generate a negative voltage.  Here it is:

Use cheap electrolytics, and run PWM with about 50% duty cycle on pin 11.  You will only be able to pull a few milliamps off your negative voltage, but that can be enough for some things.

How it works

The square wave is passed through the C1.  When output is VCC, the other side of C1 grounds through D1.  The voltage at the negative terminal of C1 is now equal to the diode drop (.7 volts for the shown 1N4004).  Pin 11 goes to ground, and the voltage at the negative terminal is reduced by 5 volts.  it is now -5+.7=4.3 V.  This is pulled through D2, and charges C2.  The voltage across C2 will be -5 V + twice the diode drop.  That means for the configuration shown it will be about -3.6 V.  The big problem with this is the 1.4 V drop through the two diodes.  We can reduce that by using Schottky diodes, which will only drop around half the voltage.

Arduino Fast PWM

The usual way to do PWM on an arduino is using analogWrite().  This works for a lot of purposes, but is very slow.  PWM done this way operates around 500 Hz.  That’s fine if you are dimming a single LED, but PWM can be used for so much more.

Common uses for PWM include:

  • motor speed controllers
  • switch mode power supplies
  • waveform generation, including audio output

There are arduino libraries available for some of these, and shields and modules for others.  But it’s worth knowing how to do fast PWM anyway.

On any of the mega88/168/328 based arduinos (I like to use nanos) the following simple sketch will work:

 


void setup() {
// put your setup code here, to run once:
pinMode(11, OUTPUT);
TCCR2A = _BV(COM2A1) | _BV(WGM21) | _BV(WGM20);
TCCR2B = _BV(CS20); //see table for clock select
OCR2A = 180; //this value from 0-255 is the duty cycle
}


void loop() {
// put your main code here, to run repeatedly:
OCR2A = (OCR2A+1)%256;
delay(10);
}

This outputs PWM on digital pin 11 at 62500 Hz.  There are much more detailed instructions here: https://www.arduino.cc/en/Tutorial/SecretsOfArduinoPWM, but I’m going somewhere with this.  I noticed a question the other day.  It was “How do I make a negative voltage with an arduino?”.  In my next post I’ll have two answers to this, one with inductors, diodes, and capacitors, and one with only capacitors and diodes.  That is going to lead into another post and video about fundamentals of switch mode power supplies.  That can be a daunting thing to get into, but once we experiment a little you’ll find all sorts of uses in your projects.