ATtiny24 Based ΔT/Δt (Temperature Gradient) Smart Charger For NiMH Battery

ATtiny24 Based ΔT/Δt (Temperature Gradient) Smart Charger For NiMH Battery

Hope you guys are doing great.

Six months ago I would never have thought of writing a technical blog, I was just too consumed with my day job which is to troubleshoot and repair Heidelberg offset printing machines, its a great piece of equipment which largely remains a mystery to this day even after six long years in the field.

I had virtually no interest in microcontrollers until I decided to experiment with an Arduino UNO a few months ago. I built my first robot in a matter of weeks but the task didn’t fail to offer a learning curve. The batteries I used to power the robot had me confront my first problem, I initially used two 9 volt batteries to get 18 volts which I then regulated down to 12 and 5 volts in order to power the motors and control electronics respectively. The robot died in a few seconds, after doing some research online I was greeted by the embarrassing fact that 9 volt batteries offer only around 500mAh, well like I said I had zero experience with batteries and their ratings, my project needed a maximum of around 1.5 Amps and after considering many options I decided to get a battery pack of 12 AA NiMH batteries (14.4 Volts) that had a 2100mAh capacity, the battery pack, although a little heavy, worked beautifully and I was happy with it until came the time to recharge the pack, I had no reliable charger with me at the time and I couldn’t find one on the market as well which would recharge 12 cells at a time, after looking around I got one that was designed to charge lithium ion batteries to around 14 volts, well I tried the charger but ofcourse it failed and I couldn’t get a sufficiently charged battery, after trying everything from adjustable voltage adapters to laptop battery chargers I knew I had to make a charger of my own.

A Nifty Little Charging Circuit (Not good enough for my use though)

After reading through a few articles on the internet I found out that different battery chemistries have different charging characteristics and in order to reliably charge a battery one needs to use a charger designed for that battery type so a reliable end of charge or charge termination method can be used that ensures proper charge and doesn’t end up destroying the battery. I wasn’t planning on devoting much time to the design of the actual charger in the first place since I was just looking for a quick way to charge my battery pack for my next project. I searched online and found this great little circuit that used a slow charging method for NiMH batteries and was labelled as a “Low cost universal charger for NiMH and NiCd batteries”, I have put a link below to the webpage.

http://www.eeweb.com/blog/extreme_circuits/low-cost-universal-battery-charger-schematic

Well I made the circuit by following the schematics and to be honest I was quite surprised by the result, by making small modifications to the original circuit and adjusting the input supply voltage to charge a 14.4 volt battery pack, I got a perfectly charged battery pack, however my recent past experience of blowing up a Li-on battery pack, due to over charging, made me stay up virtually all night to make regular checks on the battery to see it didn’t get too hot.

I was relieved and a little frustrated at the same time since something as routine as charging shouldn’t be such a load on your nerves, at that point I decided that I needed a charge controller circuit that I could easily hook with the existing charger that I made allowing me to automatically terminate the charge cycle reliably once the battery approached a full charge.

I decided to make generic controller circuit that could be easily be adapted to any charging circuit just in case I needed to change my charger circuit, therefore after building the charge controller I wasn’t surprised when I found out that the termination didn’t work as expected. What was the mistake you ask? well my Amps were too darn low! You see my battery was rated at 2100 mAh, charging the battery anywhere below 0.5C charge rate won’t provide the distinct rise in temperature that can be used to trigger the end of charge, whereas I was using a maximing charge rate of only 0.2C, I found this out after doing a bit more research online, hence I could only get away with designing my own constant current charging circuit.

Before we discuss the design of the control and power circuit lets just first have a brief look at the theory behind NiMH charge termination and the methods used to trigger an end of charge.

The Theory of Charge Termination (NDV and Delta T/Delta t)

There are two widely used methods for charge termination for a NiCd and an NiMH battery, what are these two methods? In order to have the answer it is important to study the charge characteristics of these batteries.

4496Fig01 nickel_chargers_001

I got these two images via google search, it can give you a fair idea of how the cell voltages and temperature vary as the battery is charged and reaches a full capacity. The charging curves of NiMH and NiCd batteries are nearly identical, however the dip in terminal voltage when the battery reaches full charge is more pronounced in NiCd batteries and is also easier to detect as compared to NiMH batteries. This sort of charge termination is called negative Delta V (NDV) charge termination where the on-board controller looks for voltage dips typically of the order of 5mV/cell (for a typical NiMH cell). Since the dip in voltage is so low it is not hard to guess that detecting such small variations will be quite a challenge.

However we are fortune enough to have another and should I say more reliable charge termination method which is called Delta T(temperature)/Delta t (time) termination, utilizing this particular method the controller monitors the battery temperature through a temperature sensor installed inside the battery pack and looks for a pre-defined change in temperature in a period of typically one minute.

The above shown characteristics are at a 1C charge rate, i.e a battery rated at 2100mAh is charged by forcing a current of 2.1A through it, had the charging current been 1.05 A then this would have been a 0.5C charge rate, as a general rule the NiMH batteries exhibit the above behavior when it is charged anywhere between 0.5C to 1C, according to the research I have done, if the charge rate is held constant between 0.5C to 1C the end of charge can be detected through measuring a  temperature difference of 0.8 degree C per minute, some batteries allow for a charging rate greater than 1C, I would highly encourage you to look through the battery datasheet as the manufacturer usually mentions the recommended charging standards.

The Charger Power Circuit

As mentioned above the NiMH batteries need to be charged at a constant current through its entire charge cycle therefore the power circuit of the charger needs to be in principle a constant current source. If the current changes through the charge cycle the charge curve will not be not as shown above and it will be impossible to detect an end of charge signal.

But  what happens if we us a voltage source instead to charge the NiMH battery? Well a voltage source or power supply pushes whatever current through a load necessary to maintain a fixed voltage across it, as the NiMH battery’s charge builds up it’s terminal voltage increases and the power supply or the constant voltage source will require to push less and less current through it in order to maintain a certain voltage. so yes you can actually charge an NiMH battery with a power supply but the charging can’t be controlled with either charge termination method since the current won’t remain constant.

NiMH Charger

The design uses an LM350 linear regulator, arranged in a constant current regulator configuration, the LM350 can deliver up to 3 Amps and is ideal for my application and is fairly simple to bias for a particular current need.

Capture

Vref for this regulator is 1.2Volts, so just by adding a fixed resistance in between the Vout and ADJ pin you can get a constant current out of it. Just use the simple relation above to suit your needs.

I am using two 5W resistors in my circuit both can be by-passed when respective relays are closed, the 0.66 ohm resistor allows for a constant current of 1.8 Amp and the 0.47 ohm resistor configuration can give a constant current of around 1.2 Amp, 0.66 ohm and 0.94 ohm combined will supply a current of around 0.76 Amps, the charger controller circuit that will be discussed later will switch between the three current sates depending on the battery state by turning on respective relays and by-passing resistors, a little crude but still an easy enough circuit to built and work with.

Constant Current Source and How They Work

Its absolutely essential to have a basic understanding about the working of constant current sources, earlier we discussed briefly how voltage source or your usual power supplies work, they force current through a load in order to maintain a voltage across it, for example a 12 Volt DC power supply connected across a 12 ohm load will drive 1 Amp through it so a voltage of 12 Volts is maintained across it, it’s simple ohm’s law.

Similarly a constant current source would do the exact opposite, it will maintain a specific voltage across a load so a constant current is maintained through it, which brings me to a very important point concerning the power circuit, what if the input to the LM350 isn’t a large enough voltage that can be passed onto the load (after a certain small  drop) to drive a specific constant current through it? the current will no longer be constant and will gradually start to fall. If the load at the charger power circuit is 1 ohm then a voltage input of around 4 Volts to the LM350 will be sufficient enough to drive 1.8 Amp current through it but a 14.4 volts battery nearing full charge and connected to the charger can give close to 19 volts, through experiments I have found that you need at least 24VDC coming into the LM350 (allowing for a drop of around 2 volts) so that around 22 Volts are available to be passed on to the battery to ensure a complete charge, anything above this is good as long as you don’t exceed the maximum input rating of the LM350.

The ATtiny24 Based Charger Controller Circuit

When I first started out with designing a temperature monitoring and charging cut off circuit I wasn’t planning it to be microcontroller based, in fact at that time I was looking for a simple solution, may be a circuit that would just monitor the battery temperature and would cut off the charging when the temperature exceeded a certain level, I started with using a 555 Timer IC as a simple comparator using an NTC thermistor to trigger an output but circuit turned out to be extra sensitive to the extend that the output would trigger randomly without any temperature increase, as I read further I was introduced to the harsh reality that is associated with using an NTC thermistor, it’s “called self heating”, you see an NTC thermistor is a temperature dependent resistor and it’s resistance decreases with the increase in temperature, hence the name NTC which stands for negative temperature coefficient. When you pass a current through a thermistor in a low enough resistor arrangement than the current passing through the thermistor would generate heat causing the thermistor to self-heat and change it’s resistance giving erroneous results, secondly and more importantly I realized that a simple thermal cut-off wasn’t something I was looking for, I wanted something that could monitor the temperature gradient and provide a charge termination based on that.

I knew I needed a small microcontroller and immediately the AT-tiny series came to mind, I looked at different variants like the ATtiny85/45 and the ATtiny44/84 trying to determine which best suited my needs, before actually buying any of these microcontrollers I did some research and found out that these chips could easily be programmed with an Arduino UNO and the Arduino IDE itself can be used to write code for these chips, Since I just got into Arduino programming with the acquired set of skills still fresh and ready for further testing the ATtiny series seemed like a logical choice, the microcontroller had analog inputs and a 10 bit built-in ADC (standard stuff with microcontrollers these days) as well, just what I needed to get an NTC thermistor connected. However after searching through the local market I faced my first major obstacle, the  only tiny chip I was able to get my hands on was the ATtiny24, it could have been worse though. Ordering online would have taken up days and the cost would have reached 4000 PKR just for these chips, hence I decided to stick with the ATtiny24 and base my design around it.

To have the controller set up for programming with the Arduino IDE, I followed this wonderfully written blog which makes it really easy to start with the ATtiny24, I have linked the blog below for anyone who might be interested.

After spending a little time with the ATtiny24 I learned how seriously low 2048 Bytes of program memory is and how much I would have loved to have the ATtiny84 instead! but I had no other choice but to optimize my program down to the very last detail to make it fit inside the small space I had available.

After many iterations and changes the final design of the ATtiny24 controller circuit I settled for can be seen below,

Controller circuit

You have to excuse my drawing skills, I did try to put in a lot effort in this. The ATtiny24 chip is at the heart of the design, I am using an LM4040 4.096 volt zener shut regulator diode for the ADC external reference, the BC547 general purpose NPN transistors are used to switch the 5 volt relays, pin 7 or the A6 analog input pin is used to measure the battery voltage the pin has been protected by a1N4731A zener diode, LED1 and LED2 are used to signal charging ON and different termination states. Although a simple arrangement but this along with the power circuit is capable of doing some quite handy things, I have listed the features down below,

1- Monitors the battery temperature through a thermistor NTC and cut-off the charging when the temperature gradient is equal to or above 0.8 degree C per minute.

2- Monitors the battery voltage and doesn’t start a charge cycle if the voltage is above or equal to 16.8 volts to prevent unnecessary overcharging.

3- Measures the battery voltage through the charge cycle and terminates charging if the voltage reaches 19 volts, using this as back to the primary charge termination method.

4- Terminates charging if the battery temperature if equal to or above 43 degree C.

5- Terminates charging if none of the charge termination conditions are met in 3 hours.

LED status

The above five features are coded into the ATtiny24’s small memory, lets look at some of design issues I faced through out this project and I how I managed to overcome these problems and then finally we’ll have a look at the code itself.

a) Making a 5K Thermistor Work With an ATtiny24

log-graphThe relation between a thermistor’s resistance and temperature is not a linear one, it’s an exponential relation given by the below equation.

R(T)R(T) is resistance at a given temperature T, R25 is the resistance at 25 degree C, B is known as beta and is provided in the manufacturers datasheet.

The best known approximation of the above relationship is expressed by what is called the Steinhart-Hart equation.

steinhart-hart-equation

Where again T is the temperature, A,B and C are constants and R is the resistance.

 

The ATtiny24 would read a voltage at it’s analog input coming through a voltage divider with one resistor being the thermistor itself (as shown in the circuit diagram), to know what temperature a particular voltage level corresponds to requires the implementation of one of the above equations into the ATtiny24’s code, however as I discovered this is quite difficult, since the program memory is so limited, implementing a natural log or an exponential function would take up most of the memory and leave very little space for implementing rest of the code, I am not sure if I was limited by the Arduino IDE in this case or would this have been the same had I used another software to write and compile the code.

With this problem at hand I decided to attempt a linearization of the thermistor curve so I could replace the exponential behavior with a simple straight line equation which would be a lot easier to include in my code and won’t take up nearly as much space, it is understandable that a single straight line won’t be able to closely approximate the behavior of the curve, this is where piecewise linearization comes in, now a lot of young engineering students will be familiar with this term, those who aren’t, piecewise linearization is a method of breaking up a non-linear curve into a number of straight line equations with each line closely approximating different segments of a non-linear curve. The more the number of lines the better will be the approximation.

In order to proceed with this approach I first filled up an excel sheet using the beta NTC thermistor equation to get the resistance of the thermistor for a given temperature, later for 5 volts coming into the NTC voltage divider I calculated the corresponding voltages that would appear on the ATtiny24’s analog pin at different temperature, since I am using a 4.096 external reference for the in-built 10 bit ADC of the ATtiny, it wasn’t difficult to calculate the number of steps the ADC would read for a certain voltage allowing me to draw a graph between the ADC steps and temperature for this particular 5Kohm NTC thermistor.

Steps

In the above graph I have chosen a temperature range of 5 degree C to 60 degree C, this is sufficient for my application since temperatures hardly ever go below 5 degree C here in Karachi even in peak winter season. The X-axis shows the temperature in degree C and the Y-axis shows the steps, the ATtiny24 ADC can count from 0 to a maximum of 1023, so on the Y-axis we’ll go from 0 to a maximum of 1023 steps.

Before we go any further lets just take a quick look at the ADC calculations, the ATtiny24 has a 10 bit ADC and since I am using an LM4040 4.096 V reference zener regulator so my step size would be,

Step size = 4.096/1023

Therefore my step size is around 4mV, which means a 4mV change at the analog input will change the digital value by 1 bit, or in other words when the voltage at the analog input pin is below 4mV the ATtiny24’s ADC reads 0, when the voltage is equal to or above 4mV and below 8mV the ADC reads 1 and so on.

Coming back to piecewise linearization of the above shown curve, the below picture shows the original sheet I worked on and used to calculate the three straight line equations labeled as Sc1, Sc2 and Sc3.

Image (8)

Using two point straight line equation I have worked out three equations that approximate the curve, the equations can be seen labeled as 1, 2 and 3, but for the sake of clarity I have put down the three equations below,

Sc1 = -13.97575T + 993.068

Sc2 = -9.5278T + 814.4338

Sc3 = -11.85264T + 918.63032  

Where T is the temperature in degree C and Sc is the ADC steps corresponding to that temperature. These equations were far easier to code and had a significantly less impact on memory, however since the constants are decimal numbers therefore it took some time to implement a variant that would avoid floating point mathematics (which takes up considerably large space) without compromising any accuracy in the final code.

b) Avoiding Self Heating of the NTC Thermistor

As mentioned earlier self heating is a real problem with thermistors, during early experimentations I found out that when current would pass through the thermistor for a longer period of time it would heat up, which would lower its resistance allowing an increase in current flow further heating up the thermistor and lowering its resistance even further and setting up a chain reaction, at least I wasn’t skilled enough to lower my current flow enough where this self heating would be minimum allowing me to reach an equilibrium state, in fact I never paid much attention to this since quite early during the design phase I managed to avoid this problem through coding and some hardware changes, the relatively simple solution came from the Arduino forum members whom I have regularly consulted with during the whole design and testing phase, the solution was to power up the thermistor voltage divider through a digital output pin on the ATtiny24, since a temperature gradient is required to determine the end of charge condition the readings from the thermistor are acquired after every one minute which means the thermistor is idle for one minute between two successive readings, so power to the thermistor can be turned OFF by simply turning OFF the digital output pin through which it is being powered, problem solved! After every one minute the thermistor is first powered ON through the digital pin and six readings are taken and averaged out to avoid any variation due to noise.

c) The Code and Avoiding Floating Point Mathematics

Well the code, as mentioned previously is written using the Arduino IDE, there’s still a lot room for improvement and this is still a work in progress but the current version works quite well,

void setup()
{
pinMode (3, OUTPUT); //Indication LED
pinMode (2, OUTPUT); //Relay control
pinMode (10, OUTPUT);//Thermistor control
pinMode (7, OUTPUT);//E/S LED
pinMode (9, OUTPUT); //High current mode ON
pinMode (4, OUTPUT); //Moderate current mode ON
analogReference(EXTERNAL);
delay(5000);
digitalWrite(3,HIGH);
digitalWrite(2,HIGH);//start charging
delay(2000);
if(analogRead(A6) >= 606) //if connected battery voltage equals or is greater than 16.7 volts, terminate charging with error to protect overcharge.
{
digitalWrite(2,LOW);
for(;;)
{
digitalWrite(3,HIGH);
delay(500);
digitalWrite(3,LOW);
delay(500);
}}
}
//int cycle = 0;
byte Count = 0;
void loop()
{
unsigned long Temp_C=0, Temp_N=0, x=0, y=0, TempN=0, TempC=0, b=0;
byte a=0, i = 0;
//int volts1, volts2;
//volts1 = analogRead(A6);
delay(1000);
if(analogRead(A6) >= 544)//When battery voltage is greater than or equal to 14.4 volts
{
digitalWrite(9,HIGH);//Select 0.8C charging mode
}//digitalWrite(2,HIGH);//Start Charging
digitalWrite(10,HIGH);
//delay(5000);
delay(2000);
for(a=0;a<=5;a++){
Temp_C = analogRead(A1); //at 2.3V starts with 587
delay(1000);
if(Temp_C>=503)//Temp_C can be equal to 503000
{
x = 13975;
y = 9930680;
}
if(Temp_C<=502&&Temp_C>=386)
{
x = 11852;
y = 9186300;
}

  if(Temp_C<=385)//Temp_C can be equal to 385000
{
x = 9527;
y = 8144330;
}
Temp_C = Temp_C*10000; // 385*1000 = 385000
TempC = y-Temp_C; //(814433 – 385000)*10
TempC = TempC/x; //
b = b+TempC;
}
digitalWrite(10,LOW);
//b = b/6;
TempC = b/6;
a = 0;
b = 0;
if(analogRead(A6) >= 690) //when connected battery voltage at 18 volts (3.38 volts on the A6 pin) — edited on 17/4/2016 to 826 from 845, needs 3.30 volts on A6 now
{
digitalWrite(2,LOW);

for(;;)
{
digitalWrite(3,LOW);
}
//Count++;
}
while(i<=59)
{
delay(1000);
i++;
}
x=0;
y=0;
digitalWrite(10,HIGH);
delay(2000);
for(a=0;a<=5;a++){
Temp_N = analogRead(A1); //at 2.0V gets 503
delay(1000);
if(Temp_N>=503)
{
x = 13975;
y = 9930680;
}
if(Temp_N<=502&&Temp_N>=386)
{
x = 11852;
y = 9186300;
}
if(Temp_N<=385)
{x = 9527;
y = 8144330;}
if (Temp_N <= 365)//E/S when temperature is 45 degree or higher
{
digitalWrite(3,HIGH);
digitalWrite(7,HIGH);
digitalWrite(2, LOW);
for(;;){}}
Temp_N = Temp_N*10000;
TempN = y-Temp_N;
TempN = TempN/x;
b = b+TempN;
}
//digitalWrite(10,LOW);
TempN = b/6;
if(TempN > TempC)//Emergency cutoff charging
{
if(TempN-TempC >= 8)
{
digitalWrite(3, LOW); //Indicator LED
digitalWrite (7, HIGH); //E/S LED
digitalWrite(9, LOW);
delay(2000);
digitalWrite(4,HIGH);
delay(60000);
digitalWrite(2,LOW);//Relay control pin
for(;;){}
}}
Count++;
if(Count == 180) //Turn off charging after 3 hours regardless of termination conditions
{
digitalWrite(2,LOW);//Turn off charging
for(;;)
{
delay(500);
//digitalWrite(3,LOW);
digitalWrite(7,HIGH);
delay(500);
//digitalWrite(3,HIGH);
digitalWrite(7,LOW);
//delay(500);
}}
}

The key to avoiding floating point mathematics while maintaining accuracy is to simply multiply your result by 10, 100, 1000 or whatever is required to shift the decimal place and then save the result as an integer, lets illustrate this with a simple example.

Say you wish to find the change in temperature between two readings one of which is 35.1 degree C and the other is 35.9 degree C, if you assign either of these values to an integer variable inside a program then both 35.1 and 35.9 will be truncated and be saved as just 35 degree C completely excluding the digit after the decimal making the temperature difference between the two values equal to zero! on the other hand say if we multiply both 35.1 and 35.9 with 10 to shift the decimal place right then we would get 351 and 359 and these numbers can be saved in an integer variable without any change so now if we subtract the two values the change in temperature would be “8” where as it would have actually been “0.8”, so now instead of checking for a difference of 0.8 the ATtiny can be simply programmed to check for a difference of “8” avoiding floating point mathematics completely in the process.

The Design on Perf-Board

I don’t usually use jumper wires until they are absolutely necessary, I have always found that solder tracks are far more reliable and gives a very clean look if done correctly.

IMG_20160423_002016

IMG_20160425_202104

This is what the controller board looks like finished and ready to run.

IMG_20160423_002023

IMG_20160425_202214

This is the Charger Circuit itself, I have managed to mount the cooling fan right on top of the heat sink, this gives it a nice look and hides the bad finishing on the heat sink.

IMG_20160423_002037

Here is a link to a video with the circuit all wired up and operating as expected.

Conclusion

I never expected to devote so much time to this project but the challenges it offered were thoroughly enjoyed, I am open to suggestions, anything that can further improve the design and performance will be welcomed, nothing is without it’s flaws and I am still working towards resolving a few issues, I would like the power circuit to be a little less bulky, may be I can replace the linear current regulator setup with a proper switch mode circuit in the next iteration.

If you found this effort useful please support me by following my blog and youtube channel, this is first of the many posts to come.

 

Advertisements