Tag Archives: circuit

Experimenting with Buck Converters

If you’re like me, the first thing you do when wiring up a new circuit is to connect the power and ground rails (with the power source initially turned off… maybe).  And you’ve probably got at least one power supply that’ll do the job.  But what if you didn’t have the supply you needed?  Perhaps all you’ve got is a 12V battery, and you’re in need of a 3.3V source.  Well, if you’ve finished your chores, I hear Tosche Station will sell you some power converters.  Failing that, you could always build your own.  A simple buck converter will likely do the trick:

The Standard Buck Converter (via Microchip)

The buck converter takes a DC input voltage and reduces it by a controllable amount, much like a resistive voltage divider.  But unlike your average voltage divider, the buck converter can efficiently supply a substantial output current.  In fact, this circuit’s output current should be greater than its input current (on average).  And no, that doesn’t violate any laws of physics; the converter’s output power will still be less than its average input power because its output voltage is lower than the voltage at its input.  In mathematical terms, (PIN = VINIIN) > (POUT = VOUTIOUT), where IOUT = ILOAD above.  Make sense?

Now clearly this isn’t your typical linear regulator.  Not with that inductor sitting there anyways.  So just how does it work then?  Well, the key is in the switching action of the p-channel MOSFET – a fact that leads us to call such circuits switching regulators.

Think of the FET as a simple switch.  When this switch is on (conducting), the current through the inductor (L1) will  ramp up (since VIN > VOUT), as will the voltage at the output capacitor.  But we don’t want the output voltage to go as high as the input voltage.  So, after a very brief on-time, we turn the switch off again.  But once the FET stops conducting, the inductor’s current has to go somewhere.  Well fortunately we have diode D1 available – it provides a path for current to continue to circulate (out to the load, back to ground, up through the diode and back to the inductor).

Here’s the trick though: this on-off switching cycle happens over and over again, many thousands of times per second.  In fact, the more frequently we switch, the smoother our output voltage will become.  This is because we have an output capacitor picking up the slack (so to speak).  During the switch-off periods, as the inductor’s current drops, COUT supplies the bulk of the output current (ILOAD).  Once the FET is switched on again, the inductor’s current ramps back up and recharges the output capacitor.  Thus, we maintain a constant ILOAD while the capacitor absorbs the ripple current (IRIPPLE).

Now as you may have already guessed, the ratio of the input to the output voltage is determined based on the relative lengths of the switch’s on and off periods.  This is a method known as pulse-width modulation (and it’s used in tons of other circuits):

Typical PWM Waveforms

If the switch were turned on 100% of the time, the output voltage would eventually equal the input voltage.  On the other hand, if the switch were on 0% of the time, the output voltage would be zero.  So it makes sense then that the output voltage is equal to our duty cycle (the percent on-time) times our input voltage.  In other words, if the switch is on for 50% of a cycle, in theory VOUT = (50%)(VIN).  Now in practice, non-ideal components will cause the required duty cycle to be higher than expected, but we’ll get to that later.

By the way, if you’re wondering how to go about picking component values for your own buck converter, there are equations for that.  But instead of going into all of the details here, I’m going to refer you to this excellent guide (and video) from Microchip.  It’ll walk you through an example design for a 12V to 5V, 2A buck converter.

The Experiments

So this past Sunday I was in my “lab” (aka the table in my basement) and decided to see how efficiently I could build myself a buck converter with the parts I had on hand:

yay for protoboards!

I’ve laid out my circuit almost exactly as shown in the schematic above (ignoring the four ceramic filtering capacitors connected across the four parallel supply rails).  On the left is my p-channel MOSFET, followed by diode D1.  The large green and black thing is, you guessed it, the inductor (which I scavenged from a broken battery charger).  To the right of the inductor are three capacitors in parallel (I’ve done this to get better output filtering characteristics at high frequencies).  The white and black wires you see leaving the right side of the board are connected to my resistive load.  The circuit is configured like so:

  • VIN = 10V
  • PFET = IRF9540
  • D1 = 1N4004
  • L1 = 100uH
  • COUT = 270uF (effective)
  • FSWITCHING = 52kHz
  • D = 62%
  • VOUT = 5V

I should also note that these component values were chosen based on an expected load current of 1A and a ripple current of 0.3A.  I only had the one good inductor to play with, so I computed my switching frequency based on its value.

Experiment #1 (Bad Diode)

For this first test, utilizing the 1N4004 general purpose diode, I measured the following:

  • PIN = 8.7W
  • POUT = 5.1W
  • Efficiency = 59%
  • TPFET = 120°F
  • TDIODE = 149°F
  • TINDUCTOR = 82°F

Alright, so while an efficiency of 59% isn’t terrible (particularly by comparison to the 50% you’d achieve using a linear regulator), it’s not great either.  Simple buck converters are typically 80-90% efficient.  So unless my measurements are way off, clearly something’s not right here.  Based on the temperatures I measured using my Kintrex IR thermometer, I suspect the diode may be our efficiency bottleneck (since it’s the warmest component).  To find out, let’s measure a few voltage waveforms while the circuit operates:

Buck Converter Test #1 Scope Trace

The top waveform, in pink, is our measured 5V output, shown at 5V/div.  Below that, in green, is the voltage measured at the connection between D1, L1, and the FET, shown at 10V/div.  At the very bottom, in yellow, is our gate drive signal.  When this signal hits 10V, the p-channel FET will be off; when it’s at 0V, the FET will be conducting.  Note that because of this inverse relationship, the duty cycle calculated by the scope (~38%) is incorrect; we need to subtract this value from 100% to get our true duty cycle (~62%).

So as I suspected, the diode is clearly having some issues.  See that big (~25V) negative voltage spike across the diode each time the FET turns off?  Yea, that’s not so good.  It means our diode isn’t turning on as quickly as it should.  This puts additional stress on the FET.  But when the diode finally does turn on, it’s showing a voltage drop of just over 0.9V.  During the switch-off period of a cycle, the diode has to conduct, on average, the full load current of 1A.  Since our duty cycle is 62%, the diode will be conducting 38% of the time, meaning it conducts an average current of 0.38A.  Using P = IV, we can determine that the diode is dissipating at least (0.38)(0.9) = 0.34W.  The diode’s turn-on delay probably accounts for more loss, but I’m not entirely sure how to calculate that.

Experiment #2 (Schottky Diode)

Well let’s just see what happens when we substitute a much better Schottky diode (15TQ060) in place of that lousy 1N4004 rectifier.  Here’s the data from test #2:

  • PIN = 5.5W
  • POUT = 5.1W
  • Efficiency = 93%
  • TPFET = 81°F
  • TDIODE = 81°F
  • TINDUCTOR = 80°F

Wow, that’s quite a difference in efficiency (from 59% to 93%)!  And it’s all thanks to the minimal (<0.3V) forward voltage of that Schottky diode, as well as its fast turn-on time.  Our waveforms are starting to look a lot cleaner as well:

Buck Converter Test #2 Scope Trace

Experiment #3 (More Current!)

So what happens if we now decide to turn up the heat a little?  What if we suddenly decide to supply a 2A load instead of 1A?  Well, I tried just that.  Here’s what happened:

  • PIN = 12.8W
  • POUT = 10.5W
  • Efficiency = 82%
  • TPFET = 96°F
  • TDIODE = 85°F
  • TINDUCTOR = 81°F

Hmm, it seems our efficiency has dropped again.  But not unexpectedly.  Based on the temperatures of the components, it seems like our FET may now be the limiting factor.  And no surprise; the p-channel device I’ve chosen has an on-state resistance of ~0.2Ω.  Using P = IV = I2R, and multiplying by the duty cycle (the switch on-time), I get:

P = I2RD = (22)(0.2)(0.62) = 0.50W

And even at 0.3V, the diode is still dissipating substantial power as well:

P = IV(1-D) = (2)(0.3)(1-0.62) = 0.23W

Now unfortunately, I don’t have a better p-channel MOSFET to try out at the moment.  So I’m just going to have to accept those losses for now (shame on me).  However, there is a way to nearly eliminate the losses of the diode: replace it with another FET!

The Synchronous Buck Converter (via Microchip)

This time I’ll be using an n-channel MOSFET which, as you may know, contains it’s own diode (called the body diode; the p-channel FET contains one as well, but I’ve omitted it in the diagrams above).  But we won’t be relying on that diode to handle any current.  Instead, we’re going to switch on the n-channel FET whenever the p-channel FET turns off (they’ll be complimentary).  In doing so, we’ll create a low resistance path (<0.1Ω) through which the ripple current can continue to flow during the P-FET’s switch-off period.

Sadly, I can’t claim credit for this brilliant idea.  I’m not sure who first thought it up, but it’s called the synchronous buck converter (as opposed to the asynchronous, or standard, buck converter).  I imagine this is because you have to operate the two FETs in sync with one another.  This makes life a little tricky, as you don’t want to accidentally turn on both transistors at once (thus creating a short from power to ground).  But it’s not bad.

Here’s a scope trace showing the n-channel FET’s additional gate drive signal (in purple):

Buck Converter Test #4 Scope Trace

Experiment #4 (More Current, More FET!)

Well I’m sure you’re just dying to know how much of an efficiency improvement this synchronous converter will provide.  Well fear not, here are the results of my last test:

  • PIN = 12.0W
  • POUT = 10.4W
  • Efficiency = 87%
  • TPFET = 96°F
  • TNFET = 84°F
  • TINDUCTOR = 82°F

Indeed, this is an improvement!  We’re not quite back to the 93% efficiency we saw at a load current of 1A, but 87% is still better than 82%, no?

So, lessons learned?  Use quality components.  That means FETs with as low an on-resistance as possible.  And if you don’t want to go with the synchronous converter, make sure you pick a fast diode with low forward voltage.

By the way, although I haven’t done it here, you’ll probably want to wrap your buck converter in a controller of some kind (unless your load current will be fairly constant).  If you don’t, with a constant duty cycle, variations in load will cause your output voltage to change by a fair amount.  Fortunately, If you look around the interwebs, you’ll find a number of ICs that provide buck converter control.  But if you’re clever, you could whip up your own op-amp control circuit.  Or just program an AVR to do the job for you – they’re great at PWM.  Give it a shot and let me know how you make out.

One last thing: if you’ve been counting, you’ll notice that the losses I’ve calculated don’t add up to the difference between input and output power.  Lest we forget, there are still resistive losses in the inductor and output capacitor, as well as switching losses on the transistor(s).  This switching loss has to do with the power dissipated in the FET’s gate capacitance, as well as resistive losses as the transistor ramps between on and off states (nothing happens instantly you know).  The solution?  Again, buy better parts. 🙂

Questions, comments, suggestions, requests?  Feel free to leave them below.  Thanks!

The Great [Volume] Leveler (AVR Audio Compressor)

Like many people, I have fairly diverse taste in music.  My media library holds tracks from Bach, Beethoven, Billy Joel, Bonobo, Brent Lamb, Brahms, Brian Hughes, and the Bee Gees (to name just the “B” section).  I love variety.  The trouble is, all of these different genres tend to require slightly different volume settings.  Worse still, in the case of some classical music, you can get quite a wide range of volumes within a single piece (e.g. O Fortuna).  So if I hook up my BlackBerry and set it to shuffle, I find myself having to continually adjust the volume knob – either because I can hardly hear the current track, or because my neighbors are about to come banging on my door.

Well, I’m not the first one to have this problem.  Nor am I the only one to attempt to solve it.  In fact, it’s already been solved.  As you may know, there are plenty of software solutions out there for so-called volume leveling.  But before the advent of the BlackBerry, or the personal computer, there was the analog compressor.

The Buzzaudio SOC-1.1 Compressor

The sole purpose of such a device is to compress the dynamic range of an incoming audio signal: amplifying the soft parts and reducing the volume of the loud parts (thus decreasing, or compressing, the range of the track’s volume).  It’s quite a simple thing, really.  And you can buy one of these units for between $100 and $200.  But why buy something when you can build it from spare parts? 🙂

Now for all of you comp-sci majors out there who are planning on commenting on any one of a million different audio leveling programs out there, don’t worry, I know they exist.  The trouble is, even if I leveled every single MP3 I possess, what about internet radio?  Specifically, the Pandora app for my BlackBerry?  Alright, maybe there’s a software-only solution for that too (although I haven’t found it), but you know what?  Just for the fun of it, I’m going with hardware this time.  Well, mostly.  Actually, it’s going to be a mix of analog hardware and an 8-bit Atmel AVR running some embedded C code.  Sound good?  Alright, then let’s get started!

First Prototype: Powered by LabVIEW

As frequent readers of my blog will know, I’m a big fan of the LabVIEW programming language.  I can use it to whip up fairly complex data acquisition and processing applications in a matter of minutes (examples).  Much faster than writing code for an MCU.  So I decided to use it, along with my handy Mobile Studio IOBoard and Bus Pirate, for my first compressor prototype.  Before we get into the brains though, let’s talk about the guts (and by that I mean let’s talk about the analog circuitry which will be common between the LabVIEW and the MCU prototypes).

First off, we need some way of detecting the volume of our incoming audio signal.  To do this, you could simply connect your left and right audio channels directly to your ADC inputs.  Two problems with this though.  First, unless you’ve really cranked up your source’s volume, you may only see peak signals of around 100mV.  Such small voltages will mean poor resolution.  In other words, without some type of amplification, we won’t be able to detect fine changes in the input’s volume.

To counter this, I have added two operational amplifiers (op-amps, U1) which connect, via high-pass filters, to our incoming left and right audio signals.  Each op-amp increases the amplitude of its respective signal by about 50x (click to enlarge):

Audio Compressor: Analog Stage Schematic (click to enlarge)

The purpose of those two AC-coupling high-pass filters is to remove any DC offset from the input signals.  Without these filters, we would also be amplifying that offset, such that even a 0.1V bias would saturate this first set of op-amps (which are supplied by +5V and -5V).

Once amplified, there is one more thing we need to consider.  Since audio waveforms change rapidly, and swing between positive and negative voltages, our input signal may appear to change wildly between ADC samples.  What we need then is a circuit that can smoothly follow the peak amplitude of our input signal.  Kindof like an old VU meter.

Peak Hold Circuit Results (Blue = Input Audio, Green = Output)

The amplified input audio signal is shown above in blue, while the output from our “peak hold” circuit is shown in green (this plot displays 1V/div vertically, 50ms/div horizontally).  Just how does this work, you ask?  Well, scroll back up to my earlier schematic.  The key is the two sets of diodes (D1 and D2) and 10uF capacitors (C3 and C4) you see just past the first amplifier stage.  Diodes only allow current to flow in one direction (from left to right, in this case).  Thus, when the left channel amplifier’s output is greater than the voltage across C4 plus 0.35V (due to the voltage drop across the diode), C4 will be charged to a higher voltage.  Once the op-amp’s output drops, the diode D2 prevents C4 from discharging.  Thus, it “holds” the op-amp’s peak voltage.  However, because we don’t want C4 to hold this voltage indefinitely, I’ve added resistor R15 (R14 on the right channel), which gives C4 a path through which it may slowly (kindof) discharge.  The result is the scope plot above.

Now at this point, I could’ve stopped and wired both peak voltage outputs directly to my ADCs.  However, I would then have needed to read and average two voltages within my leveling program.  Since I’m on a hardware kick, I decided to simply sum the two using an inverting summing amplifier configuration (R7, R8, R9, U2).  Because this circuit’s output is inverted (negated), I then passed the signal through a unity gain (1x), inverting amplifier (R10, R11, U2).  Now we’re ready for measurements!  By the way, in case you have as much trouble as I do remembering what all of these op-amp circuits look like, you should download or bookmark this nifty guide from TI.  I use it all the time.

Audio Compressor First Prototype (Click to enlarge)

Before I move onto the brains of the device, I should explain how I intend to digitally control volume.  Recently, I acquired a Bus Pirate and a few SPI digital potentiometers.  My plan here is to use these potentiometers (P/N MCP42010), as 256-position voltage dividers.  They will be wired in-line with each audio channel.  You can see one of them (one IC containing two pots) shown as a green box in my earlier schematic.  The output from each pot will be fed into a buffer op-amp in order to keep the outputs strong (capable of driving headphones or line inputs).  For my initial LabVIEW prototype, I will be communicating with the potentiometers via an RS232 connection to the bus pirate.

LabVIEW Audio Compressor VI

Alright, so onto the brains!  [Insert zombie joke here]  The image above is a screenshot of my VI (virtual instrument, also known as a LabVIEW program).  As you might expect, it is quite simple.  I have a control for the potentiometers’ wiper positions, as well as indicators for the instantaneous and filtered ADC inputs.  The analog input is being provided by my old friend, the RPI IOBoard.  Its interface consists of just a few blocks on the diagram (for those of you unfamiliar with LabVIEW, what you see here is equivalent to written code):

LabVIEW Audio Compressor Block Diagram (Click to enlarge)

I have divided the program into two while loops (the large grey-border rectangles), each running at a 50ms rate.  The top loop handles communication with the bus pirate (initial bus pirate configuration I perform once, by hand, through the terminal).  This communication is quite simple, and consists of just two bytes.  The first byte is a command which tells the potentiometers to write the second byte to their wiper position registers.

The bottom loop is responsible for determining the appropriate wiper position, based on the incoming voltage measurements.  My logic is quite simple.  Perhaps you can determine it from the diagram alone?  Basically, I compute a difference between the current (instantaneous) voltage measurement and our last filtered value.  Then, if the current measurement is greater than the filtered measurement, I divide the difference by 40 and add it to the filtered measurement.  If the current measurement is less than the filtered measurement, I divide the difference (which is negative) by 240 and add it to the filtered measurement.  The result of this is that for loud sounds, the filtered measurement increases fairly quickly (within a second or two).  However, if the input volume drops, the filter will take perhaps five times longer to respond.

Once the filtered measurement has been computed, the appropriate wiper position is determined via a look-up table.  That table, when plotted, looks something like this:

Look-Up Table Graph

These values were determined empirically.  I simply listened to the circuit’s output for various inputs and adjusted the wiper position manually to achieve the best sound.  However, as you can see, it implements a log(x) function, as you might expect with an audio signal.  But rather than attempting to determine a precise formula for this function, as I am designing this for use on an 8-bit MCU, I chose the look-up table approach.

With my VI wired and ready to go, I proceeded to tune my filtering algorithm to provide leveling over the whole musical spectrum.  The results sounded pretty good.  But before I demonstrate anything, let’s talk about the final implementation using the ATMega328.

Second Prototype: Powered by Atmel

For my embedded prototype, I again chose an AVR microcontroller.  I’ve long been a fan of these chips.  They’re just so easy to work with, and quite powerful.  Implementing the SPI interface required just a few simple commands, since the protocol is natively supported by the ATMega’s hardware.  This particular chip also has a built-in, six-channel ADC, so that was no big deal either.  And since I’d already developed the algorithm and settings in LabVIEW, the most time-consuming part of this whole process was wiring up this lovely 10-segment LED bar graph.  Now I need more resistors…

AVR-Powered Audio Compressor (Limiter)

Although I would have liked two bar graph displays, I had only enough IO to fully support one of them.  So rather than just hard-coding the chip to display one value, I added a small button (you’ll notice it just to the left of the MCU, the largest IC) which allows you to select between displaying the instantaneous voltage input (VU meter mode) and the current wiper position.  This proved very helpful in debugging.

For simplicity, I’ve chosen to use the ATMega’s internally 8Mhz RC oscillator.  Timing isn’t very critical for this application, so I coded up a simple delay routine which works based on repeating an operation for a calibrated number of iterations.  I probably could’ve done a better (more generically useful) job on the look-up table too, but with only a few datapoints, I didn’t feel like spending much time on it.  Lazy me.  Anybody out there have some good code written for interpolating look-up tables? 🙂 Well, what I do have, you may download via the links at the bottom of this post.

Results

In order to demonstrate the performance of my device, I created an MP3 containing about 90 seconds of audio (music) at different volumes.  This file was played back on my laptop, whose volume setting was adjusted until the loudest sound produced just barely hit the maximum  input of the ADC.  The Audacity screens you see below show the original waveforms on the top and the “leveled” waveforms on the bottom (recorded via my laptop’s microphone input jack).  Enjoy:

As you can see and, hopefully, hear (sorry about my lousy sound card – the signal is much clearer than it sounds here) in the video above, the soft parts in the original track were amplified somewhat, while the loud parts were reduced in volume.  If not aurally obvious, I suspect the results are pretty easy to see in this screenshot from Audacity:

Audacity Demo Waveforms

Final Thoughts

Overall I think this project turned out alright.  I particularly liked the method of first prototyping with LabVIEW, the bus pirate, and my IOBoard.  This definitely sped up development of the final application and made debugging easier.  The only thing I wish is that I could use my VI to generate code for the AVR.  Such a thing is available, but only for 32-bit processors.  Oh well, maybe it’s time for me to upgrade by a few bits.

In the future, I may try amplifying the audio outputs.  Obviously, potentiometers by themselves can only reduce signals.  And that’s fine, as long as my input source is sufficiently loud on even the soft songs (because we can always cut the volume of the loud pieces).  But for even greater range, amplification would be nice.

You may wonder why I didn’t include any other adjustments, like an additional volume control, or knobs to adjust the filtering speed (these would be the attack and release knobs, which, by the way, are awesome names).  Well frankly, I wanted to keep things simple.  The point of this project was to reduce the amount of knob-turning I do.  If I left things adjustable, I’d probably be tweaking stuff all the time.  It’s just a compulsion.

Anyway, I hope you’ve enjoyed this project as much as I have.  As always, if you have questions, comments, or want help building something like this, please leave a comment!

List of Parts Used, with Prices  (Excluding Passives)

  • Bus Pirate ($29.95)
  • IOBoard (not readily for sale; you might be able to buy one off an RPI/Rose-Hulman student who doesn’t understand/care about the value of what the have)
  • MCP42010 Digital Potentiometer ($2.40)
  • TLC2272, 2.25Mhz, Rail-to-Rail, Dual Op-Amps ($1.83)
  • ATMega328 ($3.93)
  • LED Bar Graph, SSA-LXB10IW-GF/LP ($3.33)
  • LT1054, for generating the -5VDC rail ($1.62)

Downloads

Pure Analog Servo Control

A Standard Hobby ServoHobby servos, such as the one pictured at right, are wonderfully useful little devices.  You’ll find them moving control surfaces on model planes, in steering linkages on RC cars, and even in the feeding mechanism of an automatic ping-pong ball launcher (one of my simpler college design projects).

Anytime you need something to rotate to a specific position, think of the hobby servo.  They’re fairly low cost, and come in a variety of torque sizes, from tens to hundreds of ounce-inches.

So let’s say you’ve bought yourself a servo from Tower Hobbies (or wherever).  How are you going to control it?  Well, you could purchase a radio and receiver, but if you’re not planning on building your servo into a vehicle of some sort, that’s really overkill (and expensive).  You could program a microcontroller to generate the control signals, but that could get complicated if you’ve never worked with MCUs before.  Instead, what I’d like to discuss today is a purely analog circuit for PWM servo control.

First, let me give you a little background information.  Hobby servos are typically connected by three wires: power (red), ground (black), and signal (yellow/white).   The power and ground lines are typically hooked directly to your battery or power supply.  The signal line, however, is used to command the servo to move to a specific angular position.  This signaling is normally accomplished via pulse-width modulation (PWM).  That is, a digital pulse is sent to the servo on a routine basis (e.g. at 100Hz, or 100 times per second).  The width or duration of this pulse determines the position of the servo’s horn. For instance, a pulse width of 1ms commands a fully clockwise rotation, a width of 2ms commands a fully counter-clockwise rotation, and a width of 1.5ms will center the horn.

Now the question is, how do we generate such a signal?  Why, we simply use the following pulse-width modulator circuit (adapted from Maxim Application Note 3201):

PWM Generator SchematicAlright, so maybe you’re thinking, “Dude, that’s a big circuit.”  Well yea, it sortof is.

But then again, those three op-amps could actually all be housed inside a single 14-pin DIP/SOIC package.  And beyond that, all you need are eight resistors, one capacitor, and one potentiometer (a variable resistor).  So while this may be physically more complex than just plopping down a microcontroller, there’s no software required.

So just how does this circuit create our PWM signal?  Well let’s start with the “Integrator” section.  This group of components (R1, C1, and U1) mathematically integrate or sum the voltage wired into the left terminal of R1 (line label #5).  Put simply, the capacitor C1 is summing up this input voltage over time.  To see how this happens, let’s start by analyzing the node between R1 and C1 (label #2).  Now assuming all of our op-amps are ideal (a fair assumption in most cases), no current will enter or leave their inverting (-) and non-inverting (+) terminals.  Since the current flowing through a series connection of electrical components (R1 and C1) must be equal, we can write the following:

Integrator Equation Derivation

The first half of this formula may look familiar; it’s ohm’s law (V/R = I).  However, we’ve defined the voltage across R1 as (V5 – 2.5).  Why?  This is because the voltage at the input terminals (+ and -) of our ideal op-amp must be equal since we have a negative feedback path (a connection from output to inverting (-) terminal) through the capacitor.  And we know that the voltage at the non-inverting (+) terminal of the op-amp must be 2.5V because of the voltage divider at node #1.  Thus, since C1 is providing a feedback path for the op-amp, we can safely assume that the inverting terminal is also at 2.5V.  The second half of this equation comes from the I-V relationship for capacitors, I = C*dv/dt.

So if we solve this equation for V3, with an initial capacitor voltage of zero, we get:

Integrator Equation DerivationIf we keep the voltage V5 constant, we’re left with just an equation for a straight line.  Basically, the output V3 starts at 2.5V, then ramps linearly up/down, depending on V5, as time (t) goes on.  If left unchecked, the output of U1 would eventually hit a supply limit (either 0V or 5V). However, the second half of the above circuit, labeled “Oscillator Comparator” ensures that this does not happen by switching V5 between 0V and 5V.

Let’s take a look at U2, the second op-amp pictured above.  You’ll notice there’s no feedback path between its output and its inverting (-) terminal.  So what we’ve got is a comparator.  That is, if the voltage on its non-inverting (+) terminal is greater than that on its inverting (-) terminal, the output of U2 will be roughly 5V (our positive supply voltage). Otherwise, the output will be roughly 0V.  I say “roughly” because this op-amp (TL072) can’t operate “rail-to-rail”, which means its output can’t quite reach our supply voltages.

In order to understand this comparator a little better, let’s take a look at the point at which it switches between its high (5V) and low (0V) output.  Since the inverting terminal of U2 is fixed at 2.5V by the voltage divider at node #1, this switching must take place when node #4 passes 2.5V.  Let’s determine the voltage V3 necessary for this to occur.  To begin, I’ll equate the currents through R2 and R3 (since again, no current flows into the + terminal):

Switching Point DerivationNow don’t be confused about where that 2.5V is coming from.  This is the switching voltage for U2.  We’re not saying that U2’s non-inverting (+) terminal is fixed at 2.5V.  It’s not, because we don’t have negative feedback.  This voltage will vary based on V3 and V5.  Anyway, solving for the switching-point voltage V3 we obtain the following:

Switching Point DerivationSo we’re going to have two switching points, based on the two possible values of V5.  When V5 is 5V, V3 will be decreasing linearly, and a switch will occur at V3 = 1.325V. However, when V5 is 0V, V3 will be increasing linearly, and switching will occur at V3 = 3.675V. So this is how the oscillation happens: V3 ramps linearly in one direction until it reaches a switching threshold, at which point the integration reverses and V3 ramps backwards.  So what does this give you?  A triangle wave, as seen in green in this PSpice simulation:

PSpice Simulation (Red = Threshold, Green = Triangle Wave Oscillation, Blue = Output)

Of course, we can’t just use a triangle wave to signal our servo.  What we need now is a third comparator to generate a PWM signal using this triangle wave and a variable threshold voltage (the red line pictured above).   This is where the components around U5 come into play.  Again, since U5 has no negative feedback path, it operates as a comparator.  Thus, its output can only be 5V or 0V (roughly).  So if we feed our triangle wave into its non-inverting (+) input, and a DC threshold voltage into its inverting (-) input, what we get at the output is a square wave (the blue line) whose pulse width is inversely proportional to our threshold (i.e. a higher threshold yields a shorter pulse).

The last trick here is that we can’t just hook up a potentiometer (pot) between power and ground.  That would give us a threshold voltage variable from 0V to 5V. What we actually need is a threshold voltage that varies from about 3.2V to 3.5V, for a pulse width ranging from 1-2ms (based on the form of triangle wave shown above).  Well in order to accomplish this, I’ve placed two additional resistors (Rx and Ry) in series with the potentiometer (Rpot).  In order to determine appropriate values for these resistors, I’ll start with two voltage divider formulae which are based on the two limits of the potentiometer:

Comparator Threshold Resistance DerivationSo when the pot’s screw is turned fully clockwise, the pot’s entire 10kΩ resistance will be placed between Rx and the inverting (-) input of U5.  This will produce our maximum threshold voltage, VH.   However, when the screw is turned fully counter-clockwise, the pot will act as a short between Rx and U5, yielding our lowest threshold voltage, VL.  If we now combine and solve these two formulae, we can determine values for Rx and Ry:

Comparator Threshold Resistance DerivationNote: To determine resistances for different potentiometer values, you’d just need to replace the 10k in the first set of equations with your updated value and re-solve.

Now of course, all we really need here is a means of controlling the threshold voltage at U5’s inverting (-) terminal.  Back when I was working on my automatic ping-pong ball launcher, I wanted to use my laptop and a DAQ card to control my servo.  The DAQ card I had available at the time didn’t allow me to generate precisely-timed digital signals.  However, it did provide several analog outputs, which I could have connected directly to U5 in order to control this circuit’s pulse width.  But I didn’t know about this circuit back then, so I actually just used a microcontroller programmed to generate the appropriate signals based on an ADC input connected to my DAQ hardware.

Finally, you may also be wondering, how can I calculate the frequency of this PWM signal?  (Or maybe you’re getting sick of all these equations?)  Well, given the above formulae, it’s actually quite simple to calculate.  We just need to set the integration formula equal to the switching voltage formula, like so:

Switching Frequency DerivationWe now solve for the time t, then multiply by four (since this equation gives you the time required by one quarter of a full cycle), and invert to find the frequency:

Switching Frequency DerivationAlright, enough of these crazy formulae.  Pictures of the final circuit?  Yes, please!

Protoboard Closeup

You’ll notice that Rx is actually a series combination of three resistors, while Ry is a series combination of two resistors.  This is because I didn’t have suitable values for Rx and Ry just lying around.  Oh well, it just makes things a little messier!  Here’s the full setup:

Full Protoboard SetupFinally, here’s a screenshot of the IOBoard oscilloscope VI I used to test out my PWM circuitry.  You’ll notice that, as I mentioned earlier, the comparator’s output doesn’t quite reach 0V and 5V because these op-amps (TL072) do not have rail-to-rail outputs:

IOBoard Scope - 2ms Pulse Width

One final note on the schematic above.   The resistance R10 should have been unnecessary. I initially included it because PSpice wouldn’t run my simulation with U5’s output floating.  However, after constructing this circuit I found it necessary for reliably servo operation.  I’m not entirely sure why this was the case; perhaps the voltage levels without R10 were slightly outside of the servo’s acceptable range?  The signal on the screen certainly didn’t appear much different with or without it.  Perhaps if I had a higher frequency/resolution scope I’d see something more telling…  Oh well, it may not be an issue with your servo.

Anyway, if you have any questions on this circuit or would like to make suggestions, feel free to leave a comment.  I’d love to hear about your experience.

Also, please help yourself to my PSpice files (from the Orcad 16.0 student demo).  These were used to create the schematic shown here as well to perform simulations.

PWM Generator Schematic 2

Here’s my final bill of materials (BOM):

  • 2x TL072 Operational Amplifier
  • 1x Hitec HS-81 Servo
  • 1x 4.7uF Capacitor (Can be electrolytic, despite the slight negative voltage)
  • 1x 10kΩ Potentiometer
  • 2x 20kΩ Resistor
  • 2x 1kΩ Resistor
  • 1x 470Ω
  • 1x 119kΩ Resistor
  • 1x 166kΩ Resistor

Update (11/2/2010): It was pointed out that the TL072 may require a minimum supply voltage of 7V, so 5V could be cutting it a little close here.  Now I’ve looked through the datasheet and don’t see a specific limit mentioned, but most of the graphs do only go down to ±3.5V (which I suppose you could interpret as 7V).  Regardless, the circuit works fine with a single 5V supply, although the outputs don’t go rail-to-rail (which is normal operation), as I mentioned earlier.  The real concern with most op-amps is their upper supply limit, as you don’t want to fry anything.  Also, you might be more interested in the TL074 for this project, which contains four op-amps in one package.  I didn’t happen to have a quad op-amp lying around when I built this circuit, hence the two duals.

V5