Introduction: 16 Channel 18650 Lithium Capacity Tester

Picture of 16 Channel 18650 Lithium Capacity Tester

Hello, my name is Cedric and today im introducing you to my Arduino-based capacity tester.

I had a lot of 18650 cells lying around from old laptop batteries. I wanted to test each cell to find out its capacity. So I tried to find a way to test many cells simultaneously. My first instructable was born.

This lithium tester can test 1-16 cells at the same time. It uses resistance wire with circa 20ohm / meter as load, mosfets as switches and an arduino mega as a calculator ;). It is able to display the data on a 1602 or a 2004 LCD Display or via the serial monitor on your computer. The displayed data are "volt" "time" and "capacity". It would be possible to display the current as well, but i don´t need it. I used the internal pull up resistors to have defined levels. Because of this you will see "5000mV" in the Display if no battery is connected. You can use external pull-down resistors (20-50kohm) if you want to get "0mV" displayed if no battery is connected. In this case you have to rewrite the code.

I build mine as a 10 channel tester because I only had 10 mosfets lying around (I destroyed two of them while building-as you can see there are only 8 Mosfets on my PCB). I hope you enjoy my first instructable. If you got any questions, just write a comment. I hope it is easy to understand. Have fun !

Step 1: How to Measure Capacity - Some Basics

The main thing to calculate the capacity is the ohm's law. The formula is U = R * I. If you want to measure the capacity, first you have to calculate the current "I". Then divide the mAh through 3600 (1hour has 3600 seconds) and you have mah per second. Now calculate this value with the past time in seconds and you have the capacity in the past time :).

The calculating code:

totalcurrent[c] = totalcurrent[c] + (((valbat[c] - fetoffset[c]) * 5000 / offset) / load[c] / 3600 * ((premillis[c] - millispassed[c]) / 1000.0));

The simplified formula: Capacity in mAh= (Cell voltage - Mosfet Voltage drop) / load / 3600 * past time in seconds.

Step 2: Tools and Parts

Tools you will need:

  • soldering iron
  • solder
  • hand saw or circular saw
  • screwdriver/allen wrench(hexagon)
  • side cutter
  • stripping plier
  • Ferrule crimping plier

Parts you will need:


  • 1x arduino mega
  • 1x 1602 or 2004 LCD or LCDshield
  • 1x I2C Display adapter and 4-pole female header for the I2C (not necessary, but makes the wiring much easier)
  • 16x IRL540 (5V mosfets with RDS(on) 0.077ohm) ( one for each channel)
  • universal pcb with strip grid
  • a fan (a old Computer fan will work - its for cooling the hot wire)
  • zip ties
  • 2m resistor wire with 0.3 mm and 20ohm per meter (circa 11cm for each channel)
  • 0.5mm² ferrule
  • 16x resistors 1/8watt (200-600) as gate resistor
  • at least 40-50male headers to connect the inputs and outputs to the arduino
  • some 25 AWG (circa 0.25mm²) single wire for the inputs and outputs or an old IDE cable from a computer
  • some 13 AWG (circa 2.5mm²) single wire for connecting the cell with the load

Battery holder for a 10 channel holder (not needed if you already have any kind of battery holders)

  • 6x 5x40 wood screws
  • 10x cylinder screw M8x80mm (only 20mm of thread) ( i used countersunk srews, but i think cylinder srews are better for pulling )
  • 10x self-locking nut M8
  • 8mm drill bit
  • 10x 1x10x40 springs
  • Wood plates: 1x 220x180x20mm 2x 220x30x20mm
  • some 1.5mm² (15 AWG) rigid wire for "+"-pole

Batter holder for a 16 channel holder (not needed if you already have any kind of battery holders)

  • 6x 5x40 wood screws
  • 10x cylinder screw M8x80mm (only 20mm of thread)
  • 10x self-locking nut M8
  • 8mm drill bit
  • 10x 1x10x40 springs
  • Wood plates: 1x 450x180x20mm 2x 450x30x20mm
  • some 1.5mm² (15 AWG) rigid wire for the "+"-pole

Step 3: How to Build the Battery Holder (skip This Step If You Already Have Battery Holders)

Picture of How to Build the Battery Holder (skip This Step If You Already Have Battery Holders)

I forgot to make pictures during the building process of the project, so i have to explain it with the pictures of the finished project.

First cut down the wood to the following dimensions:

10 channel holder : 1x 220x180x20mm 2x 220x30x20mm

16 channel holder : 1x 450x180x20mm 2x 450x30x20mm

Then assemble the smaller strips to the ground plate as shown in the pictures. Drill 8mm holes at a distance of 25mm from center to center at a height of 10mm in one of the small strips as shown in the pictures (here are the M8x80 screws inserted). Drill two 2mm holes per cell close together on the opposite side in the other small strip. Now cut 70mm 1.5mm² rigid wire pieces. Put them through the small holes and solder the 2 ends together. This will be your "+"-pole. Now insert de M8x80 srews in the holes and slide the springs onto the screws. Screw self-locking nuts onto the threads and solder the thread ends a bit. You can also sand the thread ends half-round instead. I have also built a plexiglas plate under the battery holder to attach the electronics.

Now you have a flexible Battery holder which is also compatible with other battery types. Great !

Step 4: How to Build the Electronic Board

Picture of How to Build the Electronic Board

Before you begin building the board, think about the resistor value of your load. If you want a current of 2 ampere at 4V you have to use 2ohm as load (I = U/R --> 2 = 4/2). I used "1.6ohm" loads for my board. The resistance wire you bought has an "ohm per meter" value. Mine had 19.5ohm/m with a 0.3mm diameter, so i cut down 9 cm strips and crimped ferrules at the ends of the 9cm wire strips. This is because you can´t solder the resistance wire, so you have to crimp ferrules on it, then you can solder it. The holes in the PCBmust be drilled to 1.5mm where the ends of the load are pushed through. The resistance wire is a "PTC" which means that the resistance increases as the temperature rises. Your 2ohm load will be about 2.2-2.4 ohm when it´s glowing red. It is important to cool the resistance wire, otherwise the value of your load will fluctuate and you won´t get accurate results. Unfortunately, I have no picture of the fan in action, since i added it later.

I took a 39x8 holes stripgrid PCB and assembled the components as shown. It is important that you connect the "-" of all Cells to "gnd" of your Arduino, otherwise your Arduino will measure not the correct value ! Solder the 0.25mm² cables to the gates of the mosfets and the measure points for measuring the voltage. Solder the other ends to the male headers.

Step 5: Combine the Parts

Picture of Combine the Parts

Now solder 2.5mm² wire to each "+" and "-" pole of the battery holder and connect it to the electronic board like shown in the pictures. Connect the male headers and the additional ground connection to the Arduino board. Connect the Display to the Arduino.

Step 6: The Code

Picture of The Code

Update: I included the "for loop" in the Battery section to shorten the code, as suggested by "Tachyon". Thank you for the hint.

Some explanations:

float batnumber = 16; change the value from 1-16 -- Only the desired cells are displayed on the display

int intervaldisp = 1000; display changing time

int interval = 1000; time between the next calulation process of each battery. Don´t set to low if yo want to hav a smooth running program ;)

int intervalserial = 1500; time between each serial.print command

int disp = 0; here you can choose your Display type : 0 = 16x2 Display 1 = 20x4 Display

int fetoffset[17] = {16,... these values are the voltage drops at the mosfets in mV. Measure the value while discharging between "Drain" and "Source" - should be 16mv at a current of 2A. You can also calculate tat value. The resistance of the IRL540 is 0.077ohm when 5v are present at the gate. So use U = R*I and calculate it ;). For example 1.5A --> U = 0.077*1.5 -> U = 0.1155V. For example 3A --> U = 0.077*3 -> U = 0.231V.

int bat[17] = {A0,... these are the Analog input pins. Normally no changes have to be made here

float load[17] = {1.6,... these are the resistance values of your load. you can set individual values for each cell if you want. My values were 1.6ohm

float offset = 5013; this value is important! Measure the 5V pin and set the value in mV. In my case 5,013V. I will explain this in the next step.

float cutoffmin = 3000; the value in mV at which the measurement is stopped

float cutoffmax = 4300; the maximum voltage of the cell. If the voltage is higher, the code wont recognize a cell.

There are 2 sort of .ino files. One is for an I2C Display and the other one is for a default connected LCD.

If you use the I2C Display you will need the correct library. I found a good explanation and Library here: Download and install the newest library. There is also the code you need to find out the I2C adress called "I2C Address scanner for Arduino". In my case the address was "0x27".

Step 7: Arduino Power Supply

Some facts:

  • The ADC of the Arduino Mega has 10bit which are 1023 steps (0 is counted as a step --> 1024)
  • The default reference voltage is 5V
  • The Arduino "reads" 1023 when 5V is connected to an analog input pin
  • the internal reference depends on the exact value of the Arduino 5V pin


You use an usb-port of your computer to power the Arduino. The USB Volt-value is maybe only 4,8V. You connect the 5V pin of the Arduino to A0 and let the Arduino read A0 and then do "serial.print" to the serial monitor. The serial monitor will display 1023. It´s because the 4.8V at the 5V pin are the default reference of the Arduino . The Arduino now interprets the value 4.8V as 1023. If you connect a cell with 3,7V to A0 and to the same now, the serial monitor will display only 3.552V (3,7/5)*4,8. And since the capacitance measurement is based only on an assumed value of the load (1.6ohm) and the measured voltage, it is important to integrate the reference value with the calculation.

To solve this problem, it is advisable to use the Vin pin instead. Connect a external power supply to the Vin pin with 7-10V. Now the onboard available 7805 voltage regulator produces a relatively constant voltage which won´tbe exact 5V. Therefore, there is the offset value in the code to make sure calculating is correct. So measure the value o the 5V pin and write this value into "float offset = 5013;".

Now its time to start your Arduino and test some cells ;)

Step 8: Future Goals

  • I want to make a 8 cell capacity tester, which uses two analog inputs per cell. This will result in a higher accuracy. It will measure the battery voltage and the voltage drop at the load resistor (the load resistor is used as a shunt). (Vbat Vshunt) / R * Time.
  • rewrite the code to fit in an Arduino nano.
  • rewrite the code to be able to set the current per channel by a pwm output.
  • visualize the data in The Computer screen with the tool called " processing"
  • adding a buzzer


JurisP1 (author)2017-09-25

I wonder, was that eventual modernized 8-cell tester version made, may be can be published? Thank You.

picposter (author)JurisP12017-09-25

Hey JurisP1,

i am sorry, but i had no time to work on on this project. If you have any questions or i can help you out then just write me a private Message.

Will do my best ;)

cotzyca (author)2017-08-13

Hi Cedric,

This is awesome, I'm a beginner in electronics so it's gonna challenge me a lot. Can I use a arduino nano for this as well, or will this require code changes?

picposter (author)cotzyca2017-08-14

Hello cotzyca,

i think it would be possible to use an Arduino Nano. Maybe the Code is to big for the Nano, i didnt tested that yet.

You have to try it :)

FlorianS53 (author)2017-06-17

Hi Cedric

Nice Project!

I have a lot of 18650 and want to built as well a circuit to test them simultaneously

I would like to build up a database, filled with the parameters of each cell (capacity, output impedance, temperature behavior) to show individual characteristic curves of every cell.

I imagine a tester of at least 10 cells parallel, recording capacity, impedance and temperature in my database.

Is an Arduino controller a good choice for databases or should I use something else, e.g. Raspberry Pi

Can somebody help/support me realizing this project?

@all: Your help is much appreciated!

picposter (author)FlorianS532017-06-19

Hey FlorianS53,

an Arduino is imho the best choice for getting sensor values and calculate them. There are also SD-Card shields on the market you could use for the data storage or send the data via usb directly to the computer. Maybe there is a way to store them in a File on the PC, or you use a program which is able to read the values and show a "time/capacity" - graph or something that way. I think processing should be able to do that. There is also another program i tested years ago to display values, but i cant remember the name at the moment.

So I think it is definitely possible to realize your thoughts :)

My code is already measuring the capacity and time. So you would just have to adjust it to save the temperature and impedance as well and then make it possible to save the data or visualize it with processing.

Maybe i have some time to help you.


KennSoft (author)2017-05-26

Very nice project!

I saw some comments about the code being large, so... I downloaded the source code, and looked through it, and removed some more of the duplication, etc (now less than 200 lines). But, the revised code should be tested, and, if helpful and suitable, then made public. And... I don't know the procedure here for making revised code available. I don't see any "attach code" option, etc?

Thank you,

- Mike

jarno.orasmae (author)KennSoft2017-06-04

Hi, you could just add pastebin link to your comment :)

KennSoft (author)jarno.orasmae2017-06-06

Good suggestion, Jarno! It's at:

Few notes: I've not compiled/tested the revised code, because I've not built the tester. I was reluctant to post the untested mods, in case someone might, innocently, assume they were tested! I've inserted some additional comments near the front of the source. I already sent a copy to Cedric, but he is currently too busy to check the mods. Any queries, etc, I'll be glad to respond... Thank you. - Mike

picposter (author)KennSoft2017-06-19

Thanks alot Kennsoft :)

I will test that code if i have time again for my projects.

Thank you very much for your improvement.


offtherails2010 (author)2017-02-24

Fantastic Project !

Well-Done !

I'm definitely building this, collecting parts now lol


Computer Schematic to PCB Software alternative, dont know if you know about this one, is free to use up to a certain size PCB but so much better in my most humble opinion AND seeing how you've grasped the methodology of circuitboard design, i think you'll LOVE this:

Eagle PCB Software

It's quite beautiful, especially when you set a black background in the settings, but white is just as good, treat it to your preference :)

Once again, thanks so much for posting the code and write-up for the whole project, i know wholeheartedly how much effort it takes to do a good write-up, so hats off to ya !!

Keep up the AWESOME Work !!!

Best regards :))

MarcosAsensio9 (author)2017-01-29

it is necessary the resistant wire or i can use a 220 ohm and a 1.5 ohm resistor as in the breadboard image? Thanks! ;)

picposter (author)MarcosAsensio92017-01-30

Hey Marcos,

of course you can also take a 1.5 ohm resistor as load. But you will need a high power resistor for that : 1.5 ohm at about 3.7V are ~2.4A --> 2.4A*3.7V = 8.88 W !

So A 10watt 1.5Ohm resistor would be fine :).

Wrrr 10-G (author)2017-01-18

Whoah.. nice job working with what you had laying about.
Reading the comments, I am really looking forward to your next version, with ADC.

Keep it up bro, and thanks for sharing!

DaveP82 (author)2017-01-17

Also notice that you didn't use a shunt resistor as well. can you explain why maybe? I know it does use one more analog line per cell but doesn't it get you better calculations? Also i think I will redo the code to iterate thru a single loop for each cell :). really nice idea to use the bolts and springs :)

picposter (author)DaveP822017-01-17

Hey DaveP82,
you are right, there is no shunt resistor in this circuit. In this project i used the things i hat lying around. And i didn't want to buy 10 expensive 0.1ohm 0.1% resistors. I wrote the "2 analog inputs per cell" thing already in the "future goals" section ;). I want to make the next tester with a 12 or 16bit ADC and shunts and 2 analog inputs per cell.

I plan to rewrite the code to loop the Battery section as well :)

DaveP82 (author)picposter2017-01-17

Is the shunt really required to be accurate? If not then 16 is better than 8 right?

picposter (author)DaveP822017-01-18

A shunt and 2 analog inputs with 16 or more bit would be required to be really accurate. It is definitely better to test 16 instead of 8 cells at the same time if you want to test many cells ;)

DaveP82 (author)picposter2017-01-18

yeah I have 1000's of cells to test so 16 would be better. so i can skip the shunt and go this way? i dont really care about 100% accuracy but 95% with no shunt would be ok right?

picposter (author)DaveP822017-01-18
Unfortunately I can not make any exact statement about the accuracy of my project. But i think if the values of the resistor load is correct, then you should get a relatively good result. You can calibrate the circuit by measuring the current and the voltage directly at the resistance and then calculate the correct resitance value. For example: you built a 2ohm load and you measure 3.9V and 2.03A, then your correct ohm value is 1.92ohm.
I hope this helps :)
chungey (author)picposter2017-01-18

This is what I talked about, it's cheap and has good accuracy.

You need only a tiny heatsink. Whit this, enough to measure the time, current will be always 1A, no matter if the cell is 4V or 3V. This circuit drops under 2,5V but that is no problem this time.

chungey (author)2017-01-17


You can set a better Vref circuit to Aref with: analogReference(EXTERNAL).

picposter (author)chungey2017-01-17

Hey chungey,
Thank you for the idea, this is absolutely correct. Didn't thought about that. Going to include this soon :)

chungey (author)picposter2017-01-17

A temperature-compensated seems to be useful.

I had to categorize many cells for a battery pack of an electric bike a couple of years ago.

I've made something alike but only for one cell with nano, with lm317 current generator (fixed 1A discharge - better for calculation), charging capable and cell temp. measurement (- especially at charging can the cell overheat itself).

Shunt needed to measure charging current. I've automatised it, put in the cell, it recognized it, started discharge to 3V, at this point wait 1min. and the cell was collecting some power, continue discharging to 3V, wait again 10 min., discharge it again and I could say the cell was empty. Logging this parameter shows the cell's behaviour beside the capacity. Charge it to 4,2V, wait to charge current goes below 50-100ma, then the cell is full. When temperature exceeds 35-40C suspend the process. Wait couple of minutes and discharge-charge the same way.

A buzzer beeps when ready. At the end a 16x2 display shows the capacity, process time, max temp...

chungey (author)chungey2017-01-17

But it was a formatting process too, required 3-6h.

picposter (author)chungey2017-01-18

Absolut stunning idea with the constant current circuit. Indeed this is very exact for calculating! The circuit would be very interesting to me. Are there any documents about that ?

acheide (author)2017-01-15


picposter (author)acheide2017-01-16

Thanks :)

Mjtrinihobby (author)2017-01-14


picposter (author)Mjtrinihobby2017-01-16

Thank you :)

Tachyon (author)2017-01-16

Hey this looks great. I think it's going on my projects to do list.

One question. Have you tested it against a commercial battery charger/tester (eg. the image B6)?
I'm curious how it compares. Especially the capacity rating.

Oh and for anyone looking to build this. You can get 18650 battery holders all over ebay for next to nothing. It would save the work of building your own.

picposter (author)Tachyon2017-01-16

hey Tachyon,
thanks for the positive respond.
I did not do it, but I can test it. I have a B6 here. I will add this to the instructable Ehen im done with testing;)

Tachyon (author)2017-01-16

Can I ask why you repeat the battery code section for every battery?
Why not use 'c' as a loop counter and run the function through a loop? Would save a lot of code space.

As for your plans to migrate this to a Nano, I don't think you'll have enough pins. Look on ebay or Sparkfun for a
CD74HC4067 16 channel multiplexer.
With that you can do 16 channels from one pin.
If you go that route you could skip the Nano and migrate to an ESP8266 board like a Wemos D1 Mini and go wireless for the monitoring. Have it display info for all 16 batteries on a simple Web page accessible from a browser on a PC or phone.

Just some thoughts I had.

picposter (author)Tachyon2017-01-16

Hey Tachyon,
i have no idea why i didn't do that. Thank you for the great idea. This would shorten the code very much.

I know the pins of the nano won't be enough. I already thought about a 4051 Analog mux but the 4067 is also a good idea as it has 16 channels. I also thought about a Max127, a I2C based 12bit 8channel ADC chip.
Then i could do everything via I2C, including the display.
The wifi Version would also be a nice continuation :)

Thanks for all the Ideas

DIY Hacks and How Tos (author)2017-01-14

That is a really clever way to make a multi-battery holder.

Thank you ;)

Mjtrinihobby (author)2017-01-14

Nice work.

About This Instructable




More by picposter:How to Convert a 200W Halogenrod Lamp With a R7S Socket Into a Energysaving 25W Led Version16 Channel 18650 Lithium Capacity Tester
Add instructable to: