liFePO4 charger

davidwf

Senior Member
I have a LiFePO4 battery in the car to run a small coolbox/freezer....the battery charges from the car via a Victron 12 12 9 DC-DC converter (I didnt want to use a dedicated DC-DC charger as they are horrendously expensive and the smallest one is rated at 18A which is a bit high).....I have had it charging at 14.4-14.6V then off until it drops to 13.6 but I understand that is not ideal.
I was thinking of something along these lines......
1776092010553.png
 
Can you tell us what the battery capacity is (Ah) and your proposed charge current in the bulk charge phase?

A larger shunt resistor would allow you to reduce the gain of the op-amp as it will amplify noise as well. The ADC(s) in the PICAXE should be adequate for sensing the battery voltage and charge current.

I used an 08M2 as a charge controller for NiMH batteries - a different task and algorithm, of course.
 
Battery is 22AH LiFePO4
DC-DC converter has built in current limit of approx 9-10 AH which I have been using for over a year as the bulk charge, limited by an op-amp and voltage detector set at 14.5V off and 13.6V on....it seems to be working well but is obviously not ideal - circuit attached for reference
08M2 would be good as I need it to be as physically small as possible whilst monitoring the charge current and battery voltage
proposed revised cct idea attached....opto coupler o/p to offset the 5V supply
thanks
 

Attachments

  • charger.jpg
    charger.jpg
    240.6 KB · Views: 16
  • PIC LifePO4 charger.jpg
    PIC LifePO4 charger.jpg
    342.6 KB · Views: 15
this seems to work
on PIC pin 3 the ADC gives a range of approx 850 to 934 for battery voltage 13.1 to 14.6V and is used to trigger charging at battery voltage below 13.1V
on PIC pin the 5 ADC gives a range of approx 8 to 200 for i/p current range 0.4 to 10A and is used to detect when the charge current across R9 drops below 400mA
only need the lower end but cant get any better resolution than that with a 0.1 Ohm R9 but I think that will suffice
 

Attachments

Hi,

That looks as if it should work well; Just a few details that I might do slightly differently.

Personally, I normally assume the limits on a LiFePO4 cell as 3.2 volts Low, 3.6 volts High. So a range for 4 cells from 14.4 down to 12.8 volts, but perhaps it's better to start recharging before they get too low.

The ADC input sensitivity can be increased by +150% or +400% by using the FVR2048 or FVR1024 respectively as the reference, instead of Vdd. FVR1024 is officially discouraged, but seems to work fine for this type of application. However, I would use the extra gain to permit a lower current-sensing resistor value, rather than increased resolution.

The power in a 0.1 ohm R9 would be up to about 8 watts; One possibility is to shunt it with a forward diode, perhaps Schottky, to lower the power dissipation whilst retaining or improving the low-current sensitivity. Schottky Diodes seem to have a less sharp "knee" in their V/I characteristic, so may achieve a reasonably "logarithmic" current response. The tolerances, particularly of the FVR, and probably most very low value resistors, generally require a calibration process anyway. Personally, I prefer to apply the calibration within the software (EEPROM) rather than with an external Potentiometer.

Cheers, Alan.
 
Thank you!
I have never heard of FVR.....Although greater resolution would obviously be good, for the intended purpose of detecting the drop in charge current I feel that the standard resolution should work fine....it doesnt need to be accurate, just to be detectable
As you noted, the 0.1 Ohm resistor will get hot....and in testing got bloody hot!! so have already decided to use a current shunt instead.... https://www.amazon.co.uk/dp/B07XT7R4KS ......which has an insertion loss of a mere 1.2mOhm..... the resistor also caused a small voltage drop at the coolbox meaning the compressor had to run for longer and considerably reduced the charging current so a current shunt will also help that
I appreciate that a 10A shunt would probably suffice but the listing is for two (which I need) and the charge current could briefly exceed 11A so have a margin of safety
Have yet to update the ADC code depending on the module o/p voltages
 

Attachments

  • LiFePO4 charger with monitoring.jpg
    LiFePO4 charger with monitoring.jpg
    121 KB · Views: 11
Last edited:
Hi again,
Couldnt seem to get the suggested method working, my son managed to improve the range slightly by using an external reference voltage and setting a function in line 21 of the attached but it is still far from ideal....is the suggested function not available on 08M2+ PIC I wonder ?
If this is not the right way of doing it maybe you would kindly advise - or even revise the program
Thanks
David
 

Attachments

  • car LiFePO4 charger.bas
    car LiFePO4 charger.bas
    1.6 KB · Views: 6
  • LifePO4 charging.jpg
    LifePO4 charging.jpg
    288.7 KB · Views: 10
  • ADC conversion.jpg
    ADC conversion.jpg
    179.1 KB · Views: 10
Manual 2 - BASIC Commands. "adcsetup" (Page 32) paragraph 2: "On M2 parts the appropriate adcsetup bit is set automatically by the ‘readadc/readadc10/touch’ command. Therefore on these parts the only real use of adcsetup is to change a pin back from analogue to digital setup."
 
Hi,
Hi again,
Couldnt seem to get the suggested method working, my son managed to improve the range slightly by using an external reference voltage and setting a function in line 21 of the attached but it is still far from ideal...

I'm not clear what you mean by "suggested method", and in what way is the current code "far from ideal" ? The adcconfig %010 ' set adc reference voltage to pin 6 appears to be selecting an external voltage reference (3 volts) but this doesn't seem "useful", because the reference is simply being divided down (externally) from the normal default supply rail voltage (except perhaps it's adding some additional decoupling). The internal FVR (Fixed Voltage Reference) would use adcconfig %011 (together with a FVRSETUP ... instruction) , so connecting an external "reference" of 2 or 4 volts onto pin 6 could be a useful way of checking that the internal/external ADC reference is working correctly (but otherwise using Leg 6 for the Opto. Output would be better).

Just some other general comments:

It's much easier for us if you paste the actual code (at least when of moderate length) between [code ] and [/code] tags (no spaces within the tags); which also allows tables, etc. to be shown with their columns retained.

The #SIMSPEED 10 is "not required" and AFAIK a value of less than 30 is just "hiding" the tracking of the execution lines, which is normally not necessary. Similarly it seems unnecessary to comment out the SERTXD debugging commands and #TERMINAL 4800.

Cheers, Alan.
 
thanks for your advice......
the "simspeed" was left in from previous projects
if left in, the SERTXD lines cause the program to run slow (maybe not in this project but certainly in others)....it was only really needed when developing / testing
the terminal command was com'd out as I am using the SEROUT pin (7) as an output
I felt that pasting the code would clutter the page too much.....but will do so in future
the "far from ideal" was reference to the close steps of the ADC which was jittering and changing with every read, dropping the resistors to the values shown and adding the 2x 10uF capacitors across them seems to have stabilised the o/p so I am guessing it was picking up noise
the "suggested method" of using the internal reference voltages didnt work as we need ADC values shown, setting 3V ref seemed better overall
I see whet you mean though so will try the FVR function and drop both i/p's down with scaling resistors and o/p on pin 6
 
The ADC input sensitivity can be increased by +150% or +400% by using the FVR2048 or FVR1024 respectively as the reference, instead of Vdd. FVR1024 is officially discouraged, but seems to work fine for this type of application. However, I would use the extra gain to permit a lower current-sensing resistor value, rather than increased resolution.

Still not quite understanding how to benefit from setting the FVR range. One of the voltages that needs to be measured is between 13V and 14.6V. If using FVR of 1.024V for example, and scaling the input down with a voltage divider, then the range of adc values will be between ~90% to 100% of 1024, since the 13 is around 90% of 14.6 and both must be scaled uniformly relative to 0 (the chip being used cannot have the lower reference voltage changed).
In order to get an increased resolution over that specific range, wouldn't the lower reference voltage need to be raised up?
 
Hi,

No, the FVR probably offers no advantages if you have a regulated Supply Rail (7805) and an amplified current sensor which can give up to 5 volts of swing. The FVR allows the use of an unregulated supply rail, and the FVR_1024 (1 volt) can give a 1 volt Full Scale value (or a full byte from 0.25 volt if using READADC10).

IMHO it's better not to design the nominal input voltages to be too close to the absolute maximum input of the ADC; I normally allow around 20% margin in case of "unfortunate" tolerance values. For example a pair of 5% resistors in a divider chain, can give a 10% error and most regulators have a +/-5% tolerance (the PICaxe's FVR specification is nearly +/-10%).

A simple solution to the ADC noise is to average several measurements (which take less than 1 ms each). It's not even necessary to divide by the number of values (to give a true average), just accumulate the value and adjust the reference constants accordingly; the accumulation/noise may even improve the resolution of the measured value (i.e. beyond the 10 bits of READADC10).

However, there is always likely to be some dither/jitter in an ADC result, which needs to be accommodated by the program. One solution is to introduce some "hysteresis" into the decision-making (similar to a Hardware "Schmitt Trigger"), but a simpler method can be to use < or > (or <= and =>) comparisons in the IF .... THEN , or similar, structures.

The Code Window is indeed a "window" (with a scroll bar), so it's unlikely to totally dominate a post (although a few of mine have run very close to the 10,000 characters forum post limit). ;)

Cheers, Alan.
 
After a lot more experimenting I think we have settled on the FVR2048 command along with this code


pause 1000

symbol in_charge_current = C.2 ' see "readings.xlsx" for value conversion with adc
symbol in_battery_voltage = C.4
symbol out_charge_enable = C.1 ' low = charging enabled

symbol analogue_charge_current = w1
symbol analogue_battery_voltage = w2
symbol currently_charging = b6

symbol CURRENT_THRESHOLD = 724 ' around 1A (5% of AH of battery = 5% of 22AH = approx 1A)
symbol VOLTAGE_THRESHOLD_START = 922 ' around 13.3V
symbol NUM_AVERAGE_LOOPS = 1

currently_charging = 1
low out_charge_enable

fvrsetup FVR2048
adcconfig %011 ' set adc reference voltage to FVR

main:
readadc10 in_charge_current, analogue_charge_current
readadc10 in_battery_voltage, analogue_battery_voltage

'sertxd("charge current = ", #analogue_charge_current, cr, lf)
'sertxd("battery voltage = ", #analogue_battery_voltage, cr, lf)

if currently_charging = 1 and analogue_charge_current < CURRENT_THRESHOLD then
currently_charging = 0
'sertxd("stopping charging because current is low: ", #analogue_charge_current, cr, lf)
endif

if currently_charging = 0 and analogue_battery_voltage < VOLTAGE_THRESHOLD_START then
currently_charging = 1
'sertxd("starting charging because voltage is low: ", #analogue_battery_voltage, cr, lf)
endif

if currently_charging = 1 then
low out_charge_enable
'sertxd("charging", cr, lf)
else
high out_charge_enable
'sertxd("discharging", cr, lf)
endif

pause 1000
goto main



As others have found, the FVR command does NOT require re-insertion after each read ADC
we re-scaled the inputs to pins 3 & 5 to match the required ranges (<922 ADC voltage and <724 ADC current)
The only other issue we had was that when we read the ADC values there was still considerable jittering and fluctuation (maybe 5 or more counts which, with the miniscule values we are reading equates to quite a variation)
we tried averaging readings over different amounts and time periods but they were still present
The addition of C5 & C7 totally eliminated that even with no averaging which I dont understand as the inputs and 5V rail are varying by less than 0.1mV (yes, my meter has 4 decimal places and even the lowest digit wasnt changing) so it must be something in the ADC conversion but why the capacitors stop it is a mystery to me
I tried electrolytics which were fine but opted for tantalum for their stability and low leakage

so, to confirm operation.... charging at a 9A current limited 14.6V from the DC-DC converter commences when the battery voltage drops below 13.3V and remains so until the charge current dips below 1A then stops completely until the voltage drops again

Thanks to all that have contributed - it is appreciated !😁
 

Attachments

  • ADC conversion.jpg
    ADC conversion.jpg
    119.5 KB · Views: 9
  • LifePO4 charging.jpg
    LifePO4 charging.jpg
    151.4 KB · Views: 0
Last edited:
The addition of C5 & C7 totally eliminated that even with no averaging which I dont understand as the inputs and 5V rail are varying by less than 0.1mV (yes, my meter has 4 decimal places and even the lowest digit wasnt changing) so it must be something in the ADC conversion but why the capacitors stop it is a mystery to me
I tried electrolytics which were fine but opted for tantalum for their stability and low leakage
(Any) microcontroller is a digital device and will generate a lot of electrical noise. This noise appears on its power pins and will affect ADC inputs. With the ADC inputs, the higher the source impedance the more noise can appear on an ADC input pin. Even the ADC's sample-and-hold process is noisy. A significantly large external capacitance on an ADC input is useful, particularly for inputs that should only change slowly.
 
OK, thanks.... a friend also suggested it may be because there is only one ADC which is switching between inputs....either way the caps seem to resolve it :)
 
Back
Top