Car Battery Charger Adapter

1.4K336

Intro: Car Battery Charger Adapter

This instructable is for a car battery charger adapter designed to be used together with an old laptop battery power brick. It uses a buck converter (XL4015) with adjustable voltage and current to perform the main conversion. An ATTiny (digispark) is used to monitor the operation, drive a small OLED display, and switch between a Hi / Lo charging mode.

Features

  • Constant current (Hi) charging mode switching to Constant voltage as battery charges up.
  • 3A charging (can be adjusted up to 5A)
  • Display shows battery voltage, charging current and accumulated charge (Amp-Hours)
  • In-built fan for assistance with heat dissipation
  • Protection against back polarity if connected to battery in unpowered state

STEP 1: Design

The schematic shows the design of the adapter.

Most of the work is done by the XL4015 buck converter which is a step down converter capable of down converting up to 36V inputs down to 1.25V upwards with a current capability of 5 amps. The version of the converter I use here has two adjustments.

The first adjustment sets the output voltage with the internal 10K potentiometer / 270R network which gives a feedback into the converter where the junction settles around the reference 1.25V of the converter.

The second adjustment sets the current limit. The voltage drop across the 50milliOhm shunt resistor is compared against an adjustable voltage and used to turn off the buck converter.

The voltage adjustment network can be exploited to switch in an additional resistance in parallel with the 270R which will boost the output voltage. The 3k6 resistor used here will add about 1 volt extra to the output when switched in.

The current shunt resistor also provides a convenient way to monitor the charging current.

I added a pair of schottky diodes in line with the output to provide polarity protection. Each diode is capable of 5A load but I used two in parallel to minimise voltage drop and ensure good heat dissipation.

The rest of the circuit is the ATTiny digispark board used as a monitor / controller. Two GPIO are used to drive the OLED SSD1306 display. Two GPIO are used in ADC mode to monitor the output voltage and the charging current. One GPIO is used to switch the voltage boost control. When it is set to input then the voltage is normal. When it is set to low output then the 3K6 activates to boost the voltage.

The output voltage is used to power a 12V cooling fan and as input to the voltage regulator on the digispark. A small series resistor drops a couple of volts to lower fan speed and reduce dissipation in the voltage regulator.

STEP 2: Construction

The adapter was built into a custom 3D printed box.

It is wise first of all to temporarily wire the converter to the laptop power supply and set the voltage adjustment to around 14V output. The current adjustment can also be set low to start with.

The reverse of the buck converter provides three convenient points to pick up the signals required by the monitoring circuit; 0V , boost control, and current measure. Solder 3 wires onto these points.

The 2 power zener diodes were mounted on a small piece of stripboard and wired into the +O/P of the converter.

Solder wires onto the display and glue into box with display lined up with the hole.

Mount the fan with 4 screws and bolts.

Bring laptop lead and output wires into the box with stripped ends suitable for the terminal connectors.

I connected the 10K/470R,2k2, and 3k6 resistors onto the digispark board itself.

Complete the rest of the hook up and use a piece of double side tape to secure the digispark board to the size of the enclosure. Note that you may want to program and calibrate the digispark board before installing although it is possible to update the firmware in place.

STEP 3: Firmware and Calibration

The firmware for the ATTiny is available at https://github.com/roberttidey/BatteryChargerAdapter

Two libraries (SSD1306BB and I2CTinyBB) are used to drive the display. These are also available at that github.

This can be compiled and uploaded in the Arduino IDE with digispark support added.

3 #defines are available to fine tune the monitoring of voltage and current. The measurements are against the internal nominal 1.1V reference of the ATTiny but this can vary from device to device.

#define CONV_VOLTS is used to tweak the voltage monitoring
#define CONV_AMPS is used to tweak the current monitoring

#define AMPS_ZERO is used to tweak any zero offset error on the ADC. This is useful as the voltage being measured is quite low.

You can adjust CONV_VOLTS by feeding in 12V to the 10K / 470R divider and then checking the display. If it is not close to 12.00V then adjust the value by the inverse ratio of the displayed voltage to 12.00. Adjust the CONV_AMPS by the same ratio.

You can adjust the AMPS_ZERO by grounding the current monitor pin. If the current display is not zero adjust the value by about 1/50 of the amps shown. E.g. if it shows 150mA then use a value of 3.

Final calibration of the adapter should take place when it is all hooked up. Adjust the buck converter voltage adjust to give 13.6V output (after the schottky diodes with no load. Adjust the buck converter current adjust to give the desired maximum charge current with a low or zero load. I use about 3A. If using a higher current then the converter may get hot but will shutdown and protect itself if this happens.

31 Comments

Hi, instead of XL4015 buck converter i am using XL4016 it have current sense resistor 10 milli ohms, from its current sense point it showing zero amps in display. can you help me were i can change value in code for the same.
There are conversion constants at the top of the program.
#define CONV_AMPS 20168ul
#define CONV_CHARGE 333ul

These are set for the 50 milliOhm. The CONV_AMPS when multiplied by the ADC reading gives the microamps. So if shunt is 5 times lower then the CONV_AMPS should be 5 times higher (100840). Similarly CONV_CHARGE gives accumulating charge conversion should also be 5 times higher (1665).

As the voltage across the shunt is lower it is definitely worthwhile calibrating the current by measuring the current with a multimeter and then adjusting those values a bit to get the reading right.
Thank you for you detailed response.
In calibration section of article "You can adjust CONV_VOLTS by feeding in 12V to the 10K / 470R divider and then checking the display. If it is not close to 12.00V then adjust the value by the inverse ratio of the displayed voltage to 12.00. Adjust the CONV_AMPS by the same ratio."
If i get 12v by adding 1000 to the "CONV_VOLTS" it will be 22963ul.
So as mentioned to adjust the CONV_AMPS by the same ratio. I need to add 1000 to "CONV_AMPS" so it will be 21168ul.
After this I need to add "CONV_AMPS should be 5 times higher" and the value will be 105840ul right.

That's correct. However, the 10 milliohm shunt value will be susceptible to any track resistance etc. so if you can measure the actual value with ammeter that would be good.
Hi for getting a approximate voltage and amps i used below values
#define CONV_VOLTS 23303ul
#define CONV_AMPS 8000ul
other than this the result is doubling. what value i need to give for CONV_CHARGE for the above...
The 8000 value sounds low, more like what I would expect from a 100mOhm resistor. It is important that the 0V for the cpu is close to one end of the shunt and the current measurement pick up point is close to the other end.

Whatever value for CONV_AMPS you use then the CONV_CHARGE should be

CONV_AMPS * interval / 3600

So for a 6 second interval (6000mSec) then divide CONV_AMPS by 600
Hi sorry i am not getting you, for CONV_AMPS 20168ul as in code
CONV_CHARGE=20168*6000/3600 ,is something wrong for me.
The interval in the charge equation should be in seconds not miiliseconds
However, the comment in the code was misleading as the charge calculation is performed every 8 intervals

So the equation should be

CONV_CHARGE = CONV_AMPS * 8 * Interval(seconds) / 3600

I have corrected the comment.
Thank you very much for clarification....
Hi when i give the value 100840 for CONV_AMPS for using 10 milliOhm shunt the display can't show the value 1 amp or more current. the value will show only after decimal and before decimal showing zero's only. I tried also increasing values for conv_amps.
1 amp through 10 mOhm shunt should gives amps ADC reading of 10 (10mV)
Multiplied by 100840 gives 1008400
Display should regard 1000000 as 1A and display as 1.00 This all happens in the makeValString routine.

What I suggest is checking the display part is working as expected by putting in a fixed value for amps rather than the measured value and making sure display is OK.

So on about line 98 temporarily change
makeValString((unsigned long)amps, CONV_AMPS);

to
makeValString((unsigned long)15, CONV_AMPS);

With your CONV_AMPS that should give a display of around 1.50

If that is OK then revert the change and you then need to check why the voltage on the shunt is not as expected. As it is quite a low voltage then it is sensitive to any voltage offsets which can be caused by either the ADC itself or by the earth wiring.

The AMPS_ZERO constant is used to compensate for any ADC offset. In the default code this was set to 3 but will vary from one ATTiny. It is supposed to be set to give close to 0.00 display when no current is being drawn.
Hi I have changed the code as suggested and showing value 0.52 in amp. I also tried by swapping with volts place and showing same value as shown in picture.
I have tried the value CONV_AMPS 200840ul and now reading amps show 0.06.
So amps is not showing integer part. The 0.52 should probably be 1.52 and when you doubled the CONV_AMPS it should be 3.06.

This is strange as the code for display is same as use for the volts which is showing integers.

My units definitely show the correct values for amps including integers.

Can you double check the makeValString code is the same as on github?

I'll run a further test here to see if I can see any reason for this.
OK. I think I have found an issue when a CONV factor is greater than 65535 which is the case when you increased the value for your 10 milliOhm shunt.

The makeValString function line needs to be

void makeValString(unsigned long val, unsigned long conv) {

I have updated github code
Showing the values of AMP as expected. Thank you very much.
Hi when i connected to battery for charging eventhough it showing current about 2 amp , the charge mode will go to low and high and vice versa when voltage is above 14 , i think AMP threshold value need to changed. currently i give the default value(25) in the code. what value i need to given here.
Yes. The AMP_THRESHOLD is the ADC value across the shunt. As you have a much lower shunt then this value should be correspondingly lower. 25 (25mV) was set for a threshold of 0.5 amp with 50mOhm, so to get the same with 10mOhm you would need a value of 5.

Note that it can alternate between Hi and Lo when battery is getting full; that is normal.
Thank you that works. I got a smart charger ....
Hi what is the threshold voltage value of the mentioned VOLTS_THRESHOLD 625 in the code.
ADC nominally gives 1023 for 1.00V so 625 corresponds to 0.61V at the measurement point.
Battery voltage is tapped down by 10K /470R resistor so the 0.61V corresponds to 0.61 * (10 + 0.47) / 0.47 = 13.58V
However, this is a nominal value as the ADC reference of 1.00V will vary a bit from ATTiny to ATTiny.

One way to adjust for this is to see what value value one used for CONV_VOLTS to get a good reading on the display and then scale VOLTS_THRESHOLD by
CONV_VOLTS (actual) / CONV_VOLTS(default value)

If you want to change the threshold from 13.58V to a different value then just scale the value of VOLTS_THRESHOLD by the ratio of the new threshold to the default of 13.58
More Comments