There is an official statement from their own battery manual under battery care. But of course it does not relate to JK and a DIY bank.
4.The batteries must spend at least 2 hours in absorption charge mode each month to ensure sufficient time in balancing mode. For detailed information on how the balancing process works, see the Cell balancing chapter.
@peter_m I understand you may want Victron to comment but they have very specific instructions for their products. Their instructions are very clear so no need for further comment.
If enthusiasts want to alternatively program Victron equipment to handle other types of batteries, Victron provide the ability for people to do that. In fact they are extremely accomodating for those who want to experiment and do their own thing.
If the SOC is collected from the BMS you can in most cases acces the BMS via software to set a SOC value that matches with the cell voltages that are measured. Some BMS have the tendency to slightly miscalculate tbe SOC so over time it drifts away from the real value (like, in my case with Daly).
If you don’t want to charge the batteries to the top, you can set a max. voltage that lies under the specs of the battery manufacturer there too.
In a car and boat they basically use drop wiring. Only the main wiring harnas is terminated. Either by or at the first and last device. A BMS has dip switches to set the address, but others use preferences to set them - like Victron’s latest energy meter.
Dear Philippoo,
I am using a Pylontech stack of US5000C and would like to do it quite similar to what you did using MQTT to tell the Cerbo to limit the MaxChargeVoltage. I am still struggling with producing a change of MaxChargeVoltage on the Cerbo GX while sending the MQTT according to MQTT Explorer worked fine. Would you mind sending me your script so that I could see by comparison where I have a systematic flaw.
Kind Regards
FredG
When I like the cells to get balanced, I set the target SoC to 101% and accordingly the voltage stays at bulk/absorption level. From time to time I take a look at min/max cell voltage and if difference is below balancer threshold I switch back to my 85% SoC. No big deal.
I’ve been working on a Node Red flow for that for quite a while now and I think I’m nearly there.
Main problem is that each type of system requires some amount of tweaking so it’s not easy to create a “one size fits all” solution.
Each type of BMS seems to react differently as well, which adds another layer of complexity.
Manipulating the DVCC Maximum Charge Voltage is the correct approach which should work with ESS.
The seemingly obvious (but not correct) approach of setting the DVCC Charge Current limit to zero is what doesn’t always work with ESS.
From what I’m learning, it depends a lot on the battery and BMS if it’s actually useful to limit the Target SoC and how to do it best.
no, I have 16s DIY with JK BMS. But that shouldn’t matter regarding the SoC based control. important thing is that the SoC info is quite reliable like from SmartShunt or other battery conputer. The BMS calculation often is not too reliable since the current measurement there is more necessary at high currents.
my script looks like that:
while True:
soc = get_soc()
if soc > 85.0 and voltage_is_high:
set_voltage_limit(float_voltage)
voltage_is_high = False
elif soc < 84.5 and not voltage_is_high:
set_voltage_limit(bulk_voltage)
voltage_is_high = True
time.sleep(30)
with MQTT the get/set procedures look like
# on_message callback of paho.mqtt.client
def on_message(client, userdata, msg):
if(topic == "N/b12345678d/battery/289/Soc"): # instance may vary
payload = json.loads(msg.payload.decode()) # Payload to Dict
battsysinfos[SOC] = float(payload["value"]) # store SoC value in a global object
def get_soc():
return battsysinfos[SOC]
def set_voltage_limit(value):
data = {"value": value}
jstr = json.dumps(data, separators=(',',':')) # data to json string
mqtt_client.publish("W/12345678d/settings/0/Settings/SystemSetup/MaxChargeVoltage", jstr)
with dbus it might look like that:
import dbus
BMS_CAN = 'com.victronenergy.battery.socketcan_can0' # change to batt computer in case
VICTRON_SETTINGS = 'com.victronenergy.settings'
SocObj = bus.get_object(BMS_CAN, '/Soc') # change to batt computer in case
MaxChargeVoltObj = bus.get_object(VICTRON_SETTINGS, '/Settings/SystemSetup/MaxChargeVoltage')
def get_soc():
return SocObj.GetValue(dbus_interface='com.victronenergy.BusItem')
def set_voltage_limit(value):
MaxChargeVoltObj.SetValue(value, dbus_interface='com.victronenergy.BusItem')
with NodeRed it should be some kind similar (probably even easier). I never used NodeRed.
bulk_voltage is ‘easy’ (just some quite high voltage below max - never gets reached anyway), for float_voltage you have to try a little what is the ‘free-wheeling’ voltage according to your target SoC (but it’s not too important, just some float voltage)
the advantages of doing like this are that the battery gets charged with ‘full power’ if it should charge (while the higher target voltage never gets reached) and that at ‘float mode’ there is almost no current to or from the battery, but the MPPT chargers drive the loads that appear.
It does matter. victron have overridden the default behaviour of pylontech by automatically adjusting the charge voltage, something they already clamped lower.
There is no need to muck with the charging of a pylontech and restricting it further is unlikely to improve anything beyond making balancing worse.
fu.., you are right. and looking at the pylontech_quirk it seems as if especially the 15-cells 48V is quite bitchy.
""" Quirk for Pylontech. Make a bit of room at the top.
...
# 48V battery (15 cells) ...
# The more important part is clipping the charge voltage to a
# lower value. This is to fix the sawtooth voltage issue.
# Aim for 52.5V, but somewhat aggressively penalise the charge
# voltage if the highest cell goes over 3.485V. Filter this
# to keep it somewhat stable.
but as far as I see on the first look, the quirk just overwrites the “bulk_voltage level”. the quirk happens in _adjust_battery_operational_limits, but further down in dvcc._on_timer we find
if charge_voltage is not None:
user_charge_voltage = self._settings['maxchargevoltage']
if user_charge_voltage > 0:
charge_voltage = min(charge_voltage, user_charge_voltage)
That means that if maxchargevoltage is lower than the quirked charge_voltage, the ‘float_voltage level limit’ would take effect and we are fine. (I think charge_voltage is not None)
ps. for sure from time to time you have to allow balancing. but usually it’s not necessary to do so continuously.
FYI, in my current implementation I’m using the following inputs and logic:
Inputs: My chosen maximum charge current, (dis)charge current threshold (BCDT) and Target SoC, then AC and DC load, battery SoC, Battery Charge Limit, Battery Voltage Limit, Battery Discharge Current Limit, battery voltage, battery current, DVCC Charge Voltage Limit, DVCC Charge Current Limit, Multi Low Battery status and Battery Min Discharge Voltage.
The logic:
if Battery SoC == Target SoC
if battery is discharging faster than 30% of discharge current limit: turn off DVCC Charge Voltage Limit
if battery is discharging faster than my (dis)charge current threshold: increase DVCC Charge Voltage Limit
if battery is charging faster than my (dis)charge current threshold: decrease DVCC Charge Voltage Limit
else: set DVCC Charge Voltage Limit to the battery voltage + a threshold (0.05V works OK for me)
if Battery SoC > Target SoC
if battery is discharging faster than 30% of discharge current limit: turn off DVCC Charge Voltage Limit
if battery is discharging faster or equal than my (dis)charge current treshold or the current from the system load: set DVCC Charge Voltage Limit to the battery voltage
else: decrease DVCC Charge Voltage Limit
if Battery SoC < Target SoC
if battery is discharging faster than 30% of discharge current limit: turn off DVCC Charge Voltage Limit
if battery is charging faster than my chosen max charge current x 1.1: decrease DVCC Charge Voltage Limit
if battery is charging faster than my chosen max charge current x 0.75: set DVCC Charge Voltage Limit to the battery voltage + a treshold (0.5V in my case)
else: increase DVCC Charge Voltage Limit
if there’s a Low Battery Warning from the Multi or the battery voltage is close to the battery discharge voltage limit: set DVCC Charge Voltage Limit to the battery voltage + a treshold (0.5V)
This to prevent you from running the battery to the ground by accidentally or intentionally setting an unrealistically low target SoC that could cause the system to shut down
and some other glue, safety & tapering logic here and there, but the most important bits of the logic are stated above
I’m decreasing/increasing the DVCC Charge Voltage Limit with 0.1V increments and run the loop every 5 seconds, to avoid resonance and high CPU load.
This is why the first rule in every condition is to immediately stop the limiter if a (too) heavy load is turned on, because then the 0.1V increments every 5 seconds would react too slow.
For the next iteration I’m planning to use the minimum and maximum cell voltages to stop increasing the DVCC Charge Voltage Limit if one of the cells would go over a specific high voltage threshold and the battery’s voltage limiter hasn’t kicked in yet, or to force balancing if the delta between minimum and maximum cell voltage would become too high.
Moving the High Discharge rule that’s now part of every condition outside of and before the main “equal, higher or lower” loop could be an optimization as well.
As for batteries and their preferred way of balancing:
My BYD B-Box Premium LVL pack tends to only start balancing when the pack’s voltage is at 56.6V and reported SoC is 100%, and it balances sloooooow
Limiting the target SoC for this battery seems to be counterproductive, limiting the DVCC Charge Voltage Limit to 57.6V (as recommended in the relevant Victron battery pages) helps to prevent high cell voltages
My Pytes 48100R pack seems to start balancing around 90% reported SoC, don’t remember at what pack voltage
Balancing is fairly fast so limiting their target SoC to ~90-95% could maybe increase the lifespan
Not using Pylontech, because 15S
Not enough experience with JK-BMS to comment on their behavior.
Depending on the results of my experiments I might drop my Target SoC limiter altogether and keep just the bits of logic that keep the battery charge current within my predefined limit, by limiting the charge voltage.
Use case for this would be a system with MPPTs that is set to inject DC surplus to the grid, because in that particular case the DVCC Charge Current Limit is ignored.
@nickdb since you are a Victron Expert - could you help me with the following?!
Values in the /Settings path like MaxChargeVoltage usually get stored non-volatile, right? So if we change those values frequently - does it harm some flash memory?
well, there are several publications saying that it is not healthy to always keep cells at topmost charge at topmost voltage. Often it is said that you should keep SoC between arround 30 and 80% for maximal lifetime. Toyota does like this (at least with some models) in order to be able to guaranty the batt lifetime of their plug-in hybrids.
There are also publications that say today’s LiFePO4 cells are allright with all the time being charged to the top. This might be right, too, since cells are that good today, that they might get replaced after 10 or 15 years anyway not because of their SoH but because of other reasons.
With the Battery Life concept Victron follows the principle “Why discharge a battery if it can’t get charged the next days?!”. For me I created the principle “Why charge a battery to the top if doesn’t get discharged the next days?!”.
One thing is sure: It does not harm the battery to keep it at a non-extreme state. As long as you allow cell balancing from time to time / when required.