Introduction: Automatic 18650 Analyzer
Moved Updates to step 2.
I was lucky enough to acquire many dozens of used laptop batteries from a friend who works at a computer store. After charging and discharging few hundred cell 18650 cells with 3 Imax B6 chargers to measure capacities, I decided I need a better way for the next few hundred cells.
The idea behind this project was to create a cost effective device that could automatically charge and discharge multiple 18650 cells while determining the effective capacity of each individual cell. Individual cells can be binned by capacity, so multiple parallel packs with identical capacity can be put in series.
This Instructable will outline my complete design process including, specification development, component selection, circuit design/pcb layout, assembly, and software.
Step 1: Updates
As of Oct 17th this Instructable is a work in progress I will be adding a lot more detail and documentation for all the steps, any feed back is welcome as its my first Instructable, and i probably write like a dyslexic Engineering grad student...
Update 1, Oct 23: Added some code, trying to validate it now make sure it gives repeatable results. little (and big) improvements keep coming to mind I am jotting them down on the last step of this intsructable as they come, i think ill have a go at making version 2 in the new year if I have time. Update 2, Nov 07: Added link to order PCB. I have built and tested 3 analyzers now and charged many cells, calibrating the internal reference is a pain in the ass but the results are pretty consistent. The resistors get very hot without a properly oriented heat sink . With out a heat sink or with the batteries get too hot. I've started a redesign of the PCB in KiCad instead of the Eagle i used for this board. The redesign of the PCB will address many of the issues I identified in the final step, and move components to make it easier to heat sink. I've also thought about adding expansion ports to use external resistors and transistor on bigger batteries. also try to add an LCD either serial or on a 3 cell version. I am also tempted to make a PSoC 4 version because i want to try out those boards.
Update 2, July 7: Home renos, work and general busy happy life stuff have gotten in the way, but I did get a version 2 designed. The first batch of version 2 circuit board had some minor problems I didn't address before I stopped working on it for a few months ago.Today I started modifying the schematic to fix those minor errors, hopefully I will be able to post a major revision to this or make a new Instructable by the end of August and maybe a link to buy a kit.
Step 2: Preliminary Design
The design specification are based around my requirements for the batteries and my ideal work flow.
I will be using the batteries to build 12V aux power packs, replacement power tool batteries, and E-bike batteries. The majority of the 18650 cell I get are 2.2Ah - 2.6Ah nominal capacity, with max continuous discharge rate of 2C, and nominal discharge rate of 1C. When I design packs I treat cells as 2A continuous and 5A peak, so discharge capacity measurement should be done at approximately 2A.
After dissembling a battery pack I put the cells in a 12P cell holder to charge on one of my Imax B6. My Imax charges cells to about 4.10V resting voltage, so the Analyzer will need to be able to accurately top off each cell to a set voltage above this before discharging.
Accuracy of the charger is not critical, but reproducible results are. I need multiple units to give consistent results, over multiple batteries.
The charger should automatically start charge, terminate charge, start discharge and terminate discharge, while monitoring current draw and calculating capacity. This means the charger system needs to monitor voltage and current, as well as be able to activate and deactivate, independent charger and discharge circuits.
The easiest way for me to control the charger was with an Arduino, specifically a ~$2 CH340 Nano from Ebay. I use these for prototyping every thing. It cant get a simple project going faster or cheaper then with these. If your anti-Arduino you don't have to use the arduino IDE, use atmel studio or just command line. I welcome any way to get a socket-able dev board or an ATMEGA328p and usb-serial converter for any cheaper.
The simplest way, I know to discharge a battery and measure current is with a big load resistor, and the simplest way to turn a big load on and off is with an N-channel mosfet.
To get my 2 amps at nominal cell voltage of 3.7V, I chose a 1.8ohm value for the load resistor for the load. The load resistor will need to be able to handle the maximum discharge power, that can be calculated using an Ohm's law formula P=V^2/R . with the 1.8ohm resistor and an absolute max cell voltage of 4.25V the maximum power works out to 10W. Perfect! because 10W is an extremely common power resistor size. The nominal power will only be about 7W at 3.5V 1.9A, close enough to my 2A discharge rate. I ended up finding the perfect 1.8ohm 10W power resistor on Newark.
To switch the load resistor I will use a mosfet capable of handling the 2A with a 5V gate source voltage(Vgs). I did some data sheet studying and hunting on Newark and Digikey to pick out a capable, but affordable mosfet. there were many option but I chose one that was rated for 5.6A with a <4.5V Vgs, to be safe and keep temperatures low. There are lots of resources on google for choosing the right Mosfet but it basically come down to Ohms's law and package TDP. If your P = I^2*Rdson@Vgs is high then your package TDP you gonna have a bad time.
For a charging circuit I could have deigned some thing from scratch but I opted for something a little simpler. I chose to use MCP73811 li-po/ion charger chips. They are extremely simple to use, have built in voltage and current regulation, and they have a enable input so I can terminate the charge with the system controller. This chip will drastically reduce the number of components I need compared to a charger using discrete components.
Each cell will need 2 digital I/Os to drive the discharge Mosfet and control the charger. Each cell will also need 2 analog inputs, one to measure the cell voltage and one to measure the voltage drop between the Mosfet and ground. Measuring the voltage between the Mosfet and ground will let me calculate the voltage across the load resistor only, that way I don't need to the precise Rdson of the mosfet.
The Nano has 8 analog inputs and 12 digital I/O's that means I can have 4 cell on one Arduino and 4 left over I/O's I can use for status LEDs.
I sourced a 4 cell 18650 holder on Ebay and order a bunch of them for this project.
Step 3: Circuit Design
The circuit design is relatively strain forward after the preliminary design. Components were chosen based on the preliminary design requirements, and used to create the schematic in eagle.
I created the footprint and symbol for the 4 cell 18650 holder in eagle cad and found all the other components in libraries I had or online.
The circuit for the MCP73811 comes from the typical application in the data sheet, with a pull down resistor and i line to the Arduino on the CE pin.
The Mosfet was set up as a standard low side driver, with the gate pulled low to hold it off while the Arduino pins are floating.
The load resistor is connected between the battery positive and the Mosfet drain. The analog input lines are connected on each side of the load resistor.
4 LEDs and the appropriate current limiting resistor are connected on the remain Arduino pins.
Step 4: Board Layout and Ordering Parts
From the eagle schematics a circuit board was laid out and order from dirtypcb.com, I ordered enough components to make 10 chargers.
Step 5: Assembly
After waiting a month for all the ebay parts, a few weeks for the circuit boards and a couple of days for the Newark order, I could finally assemble the first unit.
Assembly went smoothly and I got strait into programming, where I hit my first actual hiccups.
Coming soon assembly pictures from the second board.
Step 6: Programming Planning
I like to use the Arduino IDE for my personal projects and prototypes because I am too lazy to pull up Atmel Studio.
Before I had all the components I started planning the program for the charger. I wanted to run 4 separate state machines, one for each cell and run them concurrently in real time to ensure proper timing for the capacity calculation. The best way i usually do this is with a hardware timer interrupt . The timer interrupt was split in to 4 time slots, it ended up being 5 but ill get to that later.
Using timer generated interrupts is a great way to guarantee code is executed at precise intervals. I use one timer interrupt that cycles through all the functions that need to be executed. The period of the timer interrupt has to be slower then the longest execution time of all the state machines running.
The basic state machine design sudo code I completed before starting to code is below:
0 – charge cool down
if VCELL not steady then state 0 //steady should be the about same voltage for 30 seconds
if VCELL < VFULL then state 1 // start charge
if VCELL >= VFULL then state2 // start discharge
1 - Charging
If VCELL >= VCHRD then state 0 // cool down
If VCELL < VCHRD then state 1 // keep charging
2 - Discharging
If VCELL > VSTOP then state 2 // keep discharging
If VCELL < VSTOP then state 3 // cool down
3 - Discharge cooldown
If VCELL not steady then state 3 //steady should be the about same voltage for 30 seconds
If VCELL > VLOW then state 2 //start discharging again
State 4 // done
Step 7: Programming
After I assembled the first charger, I started developing the code to make it work.
I started out by defining all the I/O pins and then testing to ensure I had every thing defined properly. Next step was to define the battery voltage level that govern the state machines.
From there I started turning the sudo-code state machine I had on the previous page into real code.
the state machine worked OK but there was a big issue causing problems I had to address before moving further. The analog voltage levels were all over the place. when the batteries were charging the voltage sagged throwing off the cell voltage measurements significantly. Li-ion batteries need to be charge to +- 0.05V accuracy and i could barley keep it to +-0.25V with the default Arduino voltage reference. Before i rigged up a an external regulator to use as a reference, I stumbled upon this https://code.google.com/p/tinkerit/wiki/SecretVolt...
Apparently you can use the internal 1.1V reference to check the Vin. After playing with this for a bit I was able to track the input voltage and adjust the conversion factors to get more accurate cell voltage measurements. This still wasn't enough... I noticed the input voltage was floating +-0.2V around what my voltmeter read. I figured my cheap eBay buck converter was probably not providing the cleanest voltage and my cheap meter was averaging this output. I do intend to look at this with my scope to see what is actually going on, but putting 660uF across the voltage input reduced the voltage ripple to well under 0.05V. In theory the sensitivity of the Arduino ADC's reading should be about 0.005V but that is hard to obtain in practice. I have some ideas that will help me get a lot closer to that theoretical sensitivity if I ever make more get more boards made.
The input voltage calibration take approximately 140us plus a delay I was able to reduce to 500us so so that set the lower limit of the interrupt period to about 750us. I haven't profiled it yet but the state machine does take less then 1ms to run, so I set up the timer interrupt frequency 1000Hz. 1000Hz is one of a few nice round number you can get out from the timers, and makes the capacity calculation easier.
In the end I made arrays for every variable used by the state machine and implemented it as one function that take the cell number as the input to index all the arrays. The function returns the next state. There is another array that hold the current state for each cell.
Update Oct. 24 2015:
I've posted some code I've been playing with it calculates the capacity continuous in the interrupt sub routing regardless of the state it works pretty well but noise on the ADC line cause a fluctuations of about +-1mAh while in cool down and charging states which isn't too bad.
There is not logging done on the arduino. I have been using putty terminal to log the output to a csv file i can up load import into excel. The main problem with logging on the arduino is that it take roughly 2ms to store a float or long to the eeprom which is an eternity compared to the <1ms required by the functions run by the interrupt. There is just not enough CPU time to do any logging on the eeprom beyond maybe storing the capacities.
I might look int using the psoc4 (http://www.cypress.com/file/141306/download) on the next version of the analyzer, I have a few of them laying around and I've been meaning to do a project with them. That would be a new instructable.
Step 8: Testing
After getting the code to a reliable state ive started testing the charge and discharge functions. to be on the safe side i put a large heat sink on the resistor. I stuck the heat sink on using cheap ebay thermal grease mixed with dollar store super, it works pretty well the heat sink get quite hot and dissipates heat from all 4 resistors quite well.
Step 9: Things to Imrprove or Add for Next Version
add on board 5V reference for more accuracy
add proper decoupling capacitors to ever power pin
add capacitance on the main power input to filter out noise
use PWM pins for the mosfet control.
Power from batteries feeds back into the Arduino keeping it on when the power and usb are disconnected, need to investigate this and prevent it from happening.
Arrange power resistors in a way that's easy to add a CPU heat sink,and possible look at using beefy Mosfets to dissipate some or all of the power.
Integrate power supply and break out fan header for heat sink.