Ever wanted a powersupply that you can use on the go, even without a wall outlet nearby?
And wouldn't it be cool if it was also very precise, digital, and controllable via PC?

In this instructable I will show you how to build exactly that: a digital battery operated powersupply, which is arduino compatible and can be controlled via the PC over USB.

A while back I built a powersupply from an old ATX PSU, and while it works great, I wanted to step up my game with a digital powersupply. As already said, it is powered by batteries (2 lithium cells to be precise), and it can deliver a maximum of 20 V at 1 A; which is plenty for most of my projects that require a precise powersupply.

I will show the whole design process, and all project files can be found on my GitHub page: https://github.com/ThomasVDD/SmartSupply

Let's get started!

Step 1: Features & Cost


  • Constant voltage and constant current modes
  • Uses a low noise linear regulator, preceded by a tracking preregulator to minimize power dissipation
  • Use of handsolderable components to keep the project accessible
  • Powered by ATMEGA328P, programmed with Arduino IDE
  • PC communication via Java application over micro USB
  • Powered by 2 protected 18650 Lithium Ion cells
  • 18 mm spaced banana plugs for compatibility with BNC adapters


  • 0 - 1A, steps of 1 mA (10 bit DAC)
  • 0 - 20V, steps of 20 mV (10 bit DAC) (true 0V operation)
  • Voltage measurement: 20 mV resolution (10 bit ADC)
  • Current measurement:
    • < 40mA: 10uA resolution (ina219)
    • < 80mA: 20uA resolution (ina219)
    • < 160mA: 40uA resolution (ina219)
    • < 320mA: 80uA resolution (ina219)
    • > 320mA: 1mA resolution (10 bit ADC)


The complete powersupply costed me around $135, with all one-off components. The batteries are the most expensive part ($30 for 2 cells), since they are protected 18650 lithium cells.
It is possible to lower the cost significantly if no battery operation is needed. By omitting the batteries and the charging circuitry, the price drops to about $100.
While this may seem expensive, powersupplies with far less performance and features often cost more than this.

If you don't mind ordering your components from ebay or aliexpress, the price with batteries would drop to $100, and $70 without. It takes longer for the parts to come in, but it's a viable option.

Step 2: Schematic & Theory of Operation

To understand the operation of the circuit, we will have to look at the schematic. I divided it into functional blocks, such that it is easier to understand; I will thus also explain the operation step by step.
This part is quite in depth and requires a good electronics knowledge. If you just want to know how to build the circuit, you can skip to the next step.

Main block

The operation is based around the LT3080 chip: it's a linear voltage regulator, which can step down voltages, based on a control signal. This control signal will be generated by a microcontroller; how this is done, will be explained in detail later.

Voltage setting

The circuitry around the LT3080 generates the appropriate control signals. First, we will take a look at how the voltage is set. The voltage setting from the microcontroller is a PWM signal (PWM_Vset), which is filtered by a lowpass filter (C9 & R26). This produces an analog voltage - between 0 and 5 V - proportional to the wanted output voltage. Since our output range is 0 - 20 V, we will have to amplify this signal with a factor of 4. This is done by the non inverting opamp configuration of U3C. The gain to the set pin is determined by R23//R24//R25 and R34. These resistors are 0.1% tolerant, to minimize errors. R39 and R36 don't matter here, as they are part of the feedback loop.

Current setting

This set pin can also be used for the second setting: current mode. We want to measure the current draw, and turn the output off when this exceeds the wanted current. Therefore, we start again by a PWM signal (PWM_Iset), generated by the microcontroller, which is now lowpass filtered and attenuated to go from a 0 - 5 V range to a 0 - 2 V range. This voltage is now compared to the voltage drop across the current sense resistor (ADC_Iout, see below) by the comparator configuration of opamp U3D. If the current is too high, this will turn on an led, and also pull the set line of the LT3080 to ground (via Q2), thus turning off the output. The measurement of the current, and the generation of the signal ADC_Iout is done as follows. The output current flows through resistors R7 - R16. These total 1 ohm; the reason for not using 1R in the first place is twofold: 1 resistor would need to have a higher power rating (it needs to dissipate at least 1 W), and by using 10 1% resistors in parallel, we get a higher precision than with a single 1 % resistor. A good video about why this works can be found here: https://www.youtube.com/watch?v=1WAhTdWErrU&t=1s When current flows through these resistors, it creates a voltage drop, which we can measure, and it is placed before the LT3080, since the voltage drop across it should not influence the output voltage. The voltage drop is measured with a differential amplifier (U3B) with a gain of 2. This results in a voltage range of 0 - 2 V (more on that later), hence the voltage divider at the PWM signal of the current. The buffer (U3A) is there to make sure that the current flowing into resistors R21, R32 and R33 is not going through the current sense resistor, which would influence it's reading. Also note that this should be a rail-to-rail opamp, because the input voltage at the positive input equals the supply voltage. The non inverting amplifier is only for the course measurement though, for very precise measurements, we have the INA219 chip on board. This chip allows us to measure very small currents, and is addressed via I2C.

Additional things

At the output of the LT3080, we have some more stuff. First of all, there is a current sink (LM334). This draws a constant current of 677 uA (set by resistor R41), to stabilize the LT3080. It is however not connected to ground, but to VEE, a negative voltage. This is needed to allow the LT3080 to operate down to 0 V. When connected to ground, the lowest voltage would be about 0.7 V. This seems low enough, but keep in mind that this prevents us from turning the powersupply completely off. The zener diode D3 is used to clamp the output voltage if it goes above 22 V, and the resistor divider drops the output voltage range from 0 - 20 V to 0 - 2 V (ADC_Vout). Unfortunately, these circuits are at the output off the LT3080, which means their current will contribute to the output current we want to measure. Fortunately, these currents are constant if the voltage stays constant; so we can calibrate the current when the load is disconnected first.

Charge pump

The negative voltage that we mentioned before is generated by a curious little circuit: the charge pump. For it's operation, I would refer to here: https://www.youtube.com/watch?v=1WAhTdWErrU&t=1s It is fed by a 50% PWM of the microcontroller (PWM)

Boost Converter

Let's now take a look at the input voltage of our main block: Vboost. We see that it is 8 - 24V, but wait, 2 lithium cells in series gives a maximum of 8.4 V? Indeed, and that's why we need to boost the voltage, with a so called boost converter. We could always boost the voltage to 24 V, no matter what output we want; however, this would waste a lot of power in the LT3080 and things would get toasty hot! So instead of doing that, we will boost the voltage to a bit more than the output voltage. About 2.5 V higher is appropriate, to account for the voltage drop in the current sense resistor and the dropout voltage of the LT3080. The voltage is set by resistors on the output signal of the boost converter. To change this voltage on the fly, we use a digital potentiometer, the MCP41010, which is controlled via SPI.

Battery Charging

This leads us to the real input voltage: the batteries! Since we use protected cells, we simply need to put them in series and we're done! It is important to use protected cells here, to avoid overcurrent or overdischarge, and thus damaging, of the cells. Again, we use a voltage divider for measuring the battery voltage, and dropping it down to a usable range. Now on to the interesting part: the charging circuitry. We use the BQ2057WSN chip for this purpose: in combination with the TIP32CG, it basically forms a linear powersupply itself. This chip charges the cells via an appropriate CV CC trajectory. Since my batteries don't have a temperature probe, this input should be tied to half the battery voltage. This concludes the voltage regulation part of the powersupply.

5V regulator

The 5 V supply voltage of the arduino is made with this simple voltage regulator. It is not the most precise 5 V output however, but this will be solved below.

2.048 V voltage reference

This little chip provides a very accurate 2.048 V voltage reference. This is used as a reference for the analog signals ADC_Vout, ADC_Iout, ADC_Vbatt. That's why we needed voltage dividers to bring these signals down to 2 V. Microcontroller The brain of this project is the ATMEGA328P, this is the same chip that is used in the Arduino Uno. We already went over most control signals, but there are some interesting additions nonetheless. The rotary encoders are connected to the 2 only external interrupt pins of the arduino: PD2 and PD3. This is needed for a reliable software implementation. The switches underneath use an internal pullup resistor. Then there is this strange voltage divider on the chip select line of the potentiometer (Pot). A voltage divider on an output, what's that good for; you might say. As mentioned before, the 5 V supply is not teribbly accurate. It would thus be good to measure this accurately, and adjust the duty cycle of the PWM signal accordingly. But since I had no more free inputs, I had to make a pin pull double duty. When the powersupply boots, this pin is first set as an input: it measures the supply rail and calibrates itself. Next, it is set as an output and it can drive the chip select line.

Display Driver

For the display, I wanted a commonly available - and cheap - hitachi lcd screen. They are driven by 6 pins, but since I had no pins left, I needed another solution. A shift register to the rescue! The 74HC595 allows me to use the SPI line to control the display, thus only needing 1 additional chip select line.


The last part of this powersupply is the connection with the cruel, outside world. For this, we need to convert the serial signals into USB signals. This is done by an FTDI chip, which is connected to a micro USB port for easy connection.

And that's all there is to it!

Step 3: PCB & Electronics

Now that we understand how the circuit works, we can start building it! You can simply order the PCB online from your favorite manufacturer (mine cost around $10), the gerber files can be found on my GitHub, together with the bill of materials. Assembling the PCB is then basically a matter of soldering the components in place according to the silkscreen and the bill of materials.

The first step is soldering the SMD components. Most of them are easy to do by hand, except from the FTDI chip and the micro USB connector. Therefore, you can avoid soldering those 2 components yourself, and use an FTDI breakout board instead. I provided header pins where this can be soldered on.

When the SMD work is done, you can move on to all through hole components. These are very straightforward.
For the chips, you might want to use sockets instead of soldering them directly to the board.
It is preferable to use an ATMEGA328P with Arduino bootloader, otherwise you will have to upload it using the ICSP header (shown here).

The only part that needs a bit more attention is the lcd screen, since it needs to be mounted at an angle. Solder some male angled headers onto it, with the plastic piece facing the underside of the screen. This will allow for a good placement of the screen on the pcb. After that, it can be soldered in place just like any other throughhole component.

The only thing left to do is to add 2 wires, which will connect to the banana terminals on the front plate.

Step 4: Case & Assembly

With the pcb made, we can move on to the case. I specifically designed the PCB around this hammond case, so using another case is not recommended. However, you could always 3D print a case with the same dimensions.

The first step is to prepare the end-panel. We will need to drill some holes for screws, switches, etc.
I did this by hand, but if you have access to a CNC that would be a more accurate option. I made the holes according to the schematic and tapped the screw holes.

It is a good idea to add some silk pads now, and hold them in place with a small drop of super glue. These will isolate the LT3080 and TIP32 from the backplate, while still allowing heat transfer. Don't forget them!
When screwing the chips to the backpanel, use a mica washer to ensure isolation!

We can now focus on the front panel, which just slides in place. We can now add the banana jacks and the knobs for the rotary encoders.

With both panels in place we can now insert the assembly into the case, add the batteries and close it all up. Make sure you use protected batteries, you don't want the cells to explode!

At this point the hardware is done, now all that's left is to blow some life into it with the software!

Step 5: Arduino Code

The brain of this project is the ATMEGA328P, which we will program with the Arduino IDE.
In this section, I will go through the basic operation of the code, the details can be found as comments inside the code.

The code basically loops through these steps:

  1. Read serial data from java
  2. Poll buttons
  3. Measure voltage
  4. Measure current
  5. Measure current with INA219
  6. Send serial data to java
  7. Configure boostconvertor
  8. Get battery charge
  9. Update screen

The rotary encoders are handled by an interrupt service routine to have them as responsive as possible.

The code can now be uploaded to the board through the micro USB port (if the chip has a bootloader).
Board: Arduino pro or pro mini

Now we can take a look at the interaction between the Arduino and the PC.

Step 6: Java Code

For logging data and controlling the powersupply via the PC, I made a java application. This allows us to easily control the board through a GUI. Like with the Arduino code, I won't go into all details, but give an overview.

We start by making a window with buttons, textfields etc; basic GUI stuff.

Now comes the fun part: adding the USB ports, for which I used the jSerialComm library. Once a port is selected, java will listen for any incoming data. We can also send data to the device.

Furthermore, all incoming data is saved to a csv file, for later data treatment.

When running the .jar file, we should first choose the right port from the dropdown menu. After connecting data will start coming in, and we can send our settings to the powersupply.

While the program is pretty basic, it can be very useful to control it via a PC and log it's data.

Step 7: Success!

After all this work, we now have a fully functional powersupply!

I must also thank some people for their support:

  • The project was based on EEVBLOG's uSupply project and his Rev C schematic. So a special thanks to David L. Jones for releasing his schematics under an open source license and sharing all his knowledge.
  • A huge thanks to Johan Pattyn for producing the prototypes of this project.
  • Also Cedric Busschots and Hans Ingelberts deserve credit for the help with troubleshooting.

We can now enjoy our own home made powersupply, which will come in handy while working on other awesome projects! And most importantly: we have learned many things along the way.

If you liked this project, please vote for me in the powersupply contest, I would really appreciate it!

<p>Nice work, dude. When I first saw this, I thought &quot;Wait a minute. This looks familiar.&quot; Sure enough it was. I've been trying to do a paired-down version of the best bits of Rev A,B and C but without the uController because I'm not comfortable with the programming. But since you have made it and published the code, I'm compelled to build this. </p><p>I see that you also didn't &quot;guild the lily&quot; with the uCurrent parts. Also nice work with the charge pump setup. I don't know why Dave Jones didn't try that initially with his version since he was trying to go to 0 volts!</p><p>Thanks for doing this. It looks really good.</p><p>Jon </p>
<p>Thanks man! <br>I tried to include as many features as possible, but didn't want them to be overkill :P The INA219 basically replaces the uCurrent circuitry, that's also what Dave did in his rev B and C. I also didn't understand Dave's decision there, I found it also very annoying because it made it impossible to disable the output (without adding a mosfet in series). </p><p>Let me know if you make one! :)</p>
<p>What do you think of this?</p><p><a href="http://www.ebay.de/itm/302159020184?_trksid=p2057872.m2749.l2649&ssPageName=STRK%3AMEBIDX%3AIT" rel="nofollow">http://www.ebay.de/itm/302159020184?_trksid=p20578...</a></p>
<p>Well, it will probably do what it claims, but I wouldn't expect high precision. If you don't have the time to make something yourself, it's surely an option (but a boring one :P ). </p>
<p>But Its cheap and useful. I dont know it exactly but I think the voltage and Current is pretty exact. I built a battery powered variable power supply with this and a boost up converter.</p>
<p>Love that you did the faceplace from a PCB. Hate that people are nit-picking your BOM pricing on a one-off hobby build. The fact that you can build it yourself, priceless.</p>
<p>I'm sorry for living in a country with average monthly salary of $250. That kinda makes you look at every single not optimally spent dollar.</p>
Didn't mean to offend. My point is that there is quite a difference between building one and building a thousand.
<p>That's why I'm writing all of this. It would be great to see 2nd version, improved, not just end up with only one of a kind.</p>
<p>Thank you so much! I'm indeed happy about how the faceplate turned out, it's cheap and you can customize it like you want. They did charge a bit extra for having 2 designs on 1 PCB though, but that's not a big deal. </p>
<p>Great effort! But $150 is still quite a lot, I believe it's possible to cut cost using following changes:<br>1. single LiPo cell instead of two. It puts somewhat more load on boost converter, but gets battery protection and charging into a single easily available module based on TP4056 (~$0.3 / module).<br>2. stm32F1 or F0 family microcontroller instead of atmega328 - for additional $0.5 in price, you get built-in USB support, so no FTDI chip required, plus more precise ADC and DAC. That also eliminates display driver.<br>2b. stm32 cuts cost but increases complexity, instead already assembled Arduino board can be used (like arduino Nano for $4), with only proper headers installed on the PCB.<br>3. Still don't really see how you got it to $150 - seems more like $80 to me, can you list some most expensive parts, besides battery?<br><br>Also, have you measured output noise? How stable it is in constant voltage, constant current modes? If you have equipment, maybe you can also analyse noise spectrum?<br><br>And again - this is a great effort, there is a huge need in fully controllable yet price friendly power supply, and you made a big step in this direction. I'm asking questions only because I want to make it even better :)</p>
<p>Thanks!<br>You can check the BOM for the complete parts list with prices :) The individual components are not terribly expensive, but there are a lot of them. Also, all parts where bought at farnell/element14. I could have gone a lot cheaper when using Ebay to source components. I will check what the cost would drop down to if I do that, wouldn't be a bad idea.</p><p>I considered using 2 cheaper cells in parallel, since it would indeed allow me to use a cheap charger. However, the boost converter is not able to boost this voltage - 3 V or so when the batteries are low - to 20 V. So going with 2 cells in series was basically the only option. </p><p>I used an atmega328p to have the option op programming it with arduino, since this keeps it more accessible. Concerning the Arduino nano, this doesn't save a whole lot, and I prefer to have everything on board. Furthermore, this would mean I cannot place the USB port wherever I want. The space around the backpanel is already pretty crowded with components which need heatsinking. </p><p>I did measure the output noise, it's lower then 10mV, which is pretty normal for a linear regulator output stage. </p><p>Thanks for the feedback :)</p>
<p>Checked your BOM - yes, now I see...<br>Resistors for $0.7 per unit! On aliexpress, for $4 you can get 600 pcs - 30 different values, 20 pcs per value.<br>Or you can use smd ones and get similar set for $2.<br>So -$12 on resistors comparing to your BOM.<br><br>LT1370 is sold for ~$2, that's -$8 of your BOM price.<br><br>atmega328 can be found at $1.1, minus another $2.</p><p>74HC595 cost $1.8 per 50 units, or $0.64 per 10 units, so that's minus $1.1 (you need only one for this project, but you want them for others projects too, so buying 10 or even 50 pcs isn't a waste of money).<br>With other minor optimizations maybe additional $3-5 can be saved.<br><br>So overall, even without parts optimization, just by buying at lower prices, it can be made for ~$60.<br><br>Also, LT1370 can operate safely starting from 2.7V - much more than 3.4V at which single cell should be turned off to prevent damage. So it is possible to use a single LiPo cell instead of two with the same approach in general. That gets battery price down a lot - you can use any 18650 cell with TP4056 protection/charging module. With this approach, price with battery can be made probably around $80. Still not ideal, but seems better than 150 :)</p>
<p>I appreciate your enthusiasm, but please take a bit more time before making conclusions next time.</p><p>Those resistors are 0.1% precise, no way you are going to get them for those prices. As I said, it can be much cheaper to buy the parts on ebay or aliexpress instead, no need to convince me there :p</p><p>Also, my first prototype used a single lipo cell, and it did not work. The chip indeed works at this low voltage, but NOT for the full rated current. It had no trouble boosting the voltage to 10 V, but when drawing more than half an amp (at 10 V), the voltage dropped. So it is not possible to do this, trust me. </p>
<p>I checked aliexpress for prices and added them to the BOM. $100 now (incl. PCB), which is indeed a lot cheaper. I also added this in the instructable, maybe it encourages more people to give it a try :)</p>
<p>Do you really need 0.1% for most places? Precision that is provided by 10 parallel 0.1% resistors is great, yet you can get the same result by putting some very approximate cut of nichrome wire instead, and calibrating current once using some reliable amp meter.<br>Although I'm not sure if this approach is good for instructable - but it definitely is cheaper in production.<br><br>As for 2 cells - it's a pity that one isn't enough, but I trust you completely, boost at high amps is always tricky.</p>
<p>I think you didn't check the schematic properly, I only use 0.1% on places where it is really needed. </p><p>Those 10 resistors in parallel are 1%, to achieve the same result as a 0.1% resistor. So this is already done to keep it cheap.</p><p>On all other places where I use 0.1% resistors, they are mandatory for a precise operation. </p>
Really awesome work!
<p>Thank you! Hope you enjoyed it :)</p>
very useful and informative.

About This Instructable




Bio: I study (civil) electronics engineering at the VUB in Belgium. I have a passion for making things, both useful and cool.
More by ThomasVDD:Huge POV Display Digital Battery Operated Powersupply DIY Breadboard 
Add instructable to: