Node-RED Flow for SOC Limiting

I just finished a flow that I like a lot and thought I’d share.

I am under the impression that LiFePo4 batteries enjoy sitting at 80% SOC (State of Charge) far more than they like sitting at 100%. My plan then was to create a flow that will allow me to turn on SOC limiting and set the limit. When the limit is set, the Multiplus-II will be turned off when the battery’s SOC hits the limit and when the battery’s SOC gets to 5% below the limit it will turn back on.

First of all, I’m not a battery expert (yet) so if cycling around 75-80% with a small load (1-4A) is not better for the battery than sitting at 100% and letting the Multi act as a power supply, certainly let me know.

I created the flow in its own tab called “Limit SOC” and here’s what it looks like…

The first block sets a default value of false for a flow-level variable called limitSOC and saves it. If that is true, the limiting logic will apply. The blue box is a Node-RED UI element that renders a switch. I’ll show you what that ends up looking like later.

The second block sets a default value of 80 for another flow-level variable called socLimitValue which determines the percentage the battery should be held at and obviously doesn’t apply if the previous variable is false. Again, the blue box is a Node-RED UI element - this time a numeric text box between 50% and 90% and in 5% steps.

The final block is the implementation. The 30, 77, and 90 injection nodes are just for testing. As is the “Charge Mode Friendly Name” node.

The SOC is read from the SmartShunt and a function block maps the ranges to a value of 1-4 corresponding to the switch values for a Multi. Here’s the script…

if (flow.get("limitSOC")) {
    let socLimit = flow.get("socLimitValue");

    if (msg.payload <= socLimit - 5) {
        // SOC is 5 below the limit — start charging
        msg.payload = 3;
    } else if (msg.payload >= socLimit) {
        // SOC is at or above the limit — stop charging
        msg.payload = 4;
    } else {
        // SOC is within the hysteresis band — do nothing
        return null;
    }
} else {
    // Limit SOC is off — always charge
    msg.payload = 3;
}

return msg;

The logic starts with checking the limitSOC variable, and if it’s false it hits the line msg.payload = 3 which turns the Multi on. Otherwise, if the SOC is 5% below the limit value or less it turns the charger on (value 3). If it’s at or above the limit it turns it off (value 4). If it’s in between it returns null which doesn’t send anything to the Multi. That strategy of creating a null zone is called hysteresis and is implemented to avoid fast cycling of the charger right near the limit.

The flow works great, and if I go to the Node-RED UI page it renders like this…

It’s easy to pull that UI up on my PC or phone and turn the limit off. The plan is to leave it at 80 unless I’m getting ready to go on a trip. Even then, I have an Orion XS hooked up to my alternator, so I could just leave the house at 80% and I’m sure to be charged by the time I get to where I’m going.

I hope you can use this. Let me know if it’s been helpful or if you have any suggestions to improve it.

After thinking more through the use cases with this, I decided to expand and rename it.

I’m now calling it “Cycle Control” and instead of limiting just the upper end of the SOC and hardcoding the 5% hysteresis band, I decided to allow configuration of an upper limit and lower limit. This effectively allows me to cycle my batteries between a custom upper and lower limit.

My cursory research online says this is healthier than just letting the batteries sit at 100% all the time, but I’d love to hear from others what they think of that. I am thinking about the thousands of cycles that LFP batteries have in them. If I create a cycle that lasts for a day (remember, I’m only running a fridge and a small light) and my battery has 4000 cycles, then that’s 11 years. Is that better for the battery than sitting at 100% for those 11 years? You tell me.

Here’s the new flow…

And the code for the main function…

if (flow.get("enableCycleControl")) {
    let upperLimit = flow.get("upperLimit");
    let lowerLimit = flow.get("lowerLimit");

    if (msg.payload <= lowerLimit) {
        // lower limit — start charging
        msg.payload = 3;
    } else if (msg.payload >= upperLimit) {
        // upper limit — stop charging
        msg.payload = 4;
    } else {
        // SOC is within limits — do nothing
        return null;
    }
} else {
    // cycle control is off — always charge
    msg.payload = 3;
}

return msg;

That is not a good impression to have, and generally discouraged. This has been discussed numerous times on the forum in some detail.
Commercial, supported batteries take this into account in their design specs and BMS operation.
It might be relevant to some DIY built batteries, but for the most part you will accomplish little by doing so, and may do more harm than good.

1 Like

I am not going to debate the 80% SOC but will make a few points.

If you were using a lithium chemistry such as lithium cobalt then this may be more important but not so much for lithium iron phosphate.
If it was so important why are the battery manufacturers not doing this. This does seem to be a DIYer concern.
The main rule is do not hold them continuously at 100% at absorption voltage, once charging is complete drop the voltage to 13.5V or lower for a nominal 12V battery which is below the 100% rested voltage. This avoids overcharging.

Some unintended consequences of keeping to 80% SOC.

The cells in a battery only balance when the SOC is close to 100%. Keeping the SOC to 80% will.not balance the cells, you will still need to fully charge from time to time, and if your cells drift you may not rebalance them quickly and may be at risk of early BMS shutdown due to high or low cell voltage.

The SOC value drifts over time depending upon how good the BMS or shunt is. The SOC is reset to 100% when the battery is fully charged based on voltage and current. Again you need routine recharges to 100% . If you do not then after time your 80% SOC may well be 60%.

1 Like

Good notes, @pwfarnell. Thanks. Yeah, I should have mentioned the need to occasionally take the batteries up to 100%. In fact, I’ve considered trying to work that into the flow - a “top up every x days” field. We’ll see.

Thanks for the specifics in your former reply, @pwfarnell. I did some research on that and confirmed that, like you said, resting at 100% is very different than holding electrical pressure on batteries at 100%.

I still do see research saying that resting at 80% is better than resting at 100% (especially at higher temperature which is not my condition in the Pacific Northwest).

“Keeping the battery at 100% for long periods increases aging slightly. If long shelf life is desired, keeping the SOC around 50–80% is optimal.”

“Keeping the battery at 100% for long periods increases aging slightly. If long shelf life is desired, keeping the SOC around 50–80% is optimal.” Victron Energy – Lithium Batteries Blog

“Storing batteries at 100% SOC promotes oxidation and reduces calendar life. A lower SOC reduces stress and slows aging.” Battery University (BU-808)

Show lower capacity fade over time when batteries are stored at 60–80% SOC vs. 100%, especially at elevated temperatures. EVE & CATL Cell Aging Graphs

It’s not immediately clear to me whether these sources mean resting or keeping an elevated voltage applied.

But everything I can find basically points to this not being that big of a deal either way. I’m not going to worry about it either way. I’m just going to have fun writing Node-RED flows :slight_smile:

Thanks again.

You could also simply reduce the Charge Voltage Limit in DVCC.

Play around with it to figure out what voltage equals about 80%.

But mind to disable the limit from time to time to allow cell balancing.

Good thought, @dognose. From what I’ve read, that’s a good way to do it. This other method I’m playing with where I programmatically turn the charger off when I get to the top of the cycle and then back on at the bottom is called microcycling.

One advantage of reducing float as you suggest is that the charger is basically acting as a power supply for loads (versus microcycling where the battery is on its own until it gets to the bottom of the cycle).

From the research I’ve done, though, some battery manufacturers consider it good to exercise a battery in microcycles versus letting them sit at a single level. Furthermore, Battleborn suggests that even if you hold it at float, it will microcycle and that is still counted as cycling.

I did some AI research but the mods deleted it. So I manually pulled together a list of web references on this subject so others can do their own research about what some other internet people (mostly battery manufacturers) have to say on the subject.

BU-808: How to Prolong Lithium-based Batteries - Battery University (Lithium Ion)

The Lithium Battery Charging Cycle: to float or not to float? - Renogy United Kingdom

float - Lithium manufacturer says no? - VictronEnergy

BattleBorn response to continually charging LiFePO4s | My Grand RV - Grand Design RV Forum

How Long Do LiFePO4 Batteries Last? - Renogy United States

Everything You Need to Know About Lithium Battery Charging Cycles - Renogy Australia

For the record, I doubt anyone’s going to do any noticeable harm to their battery by either keeping it at the top or microcycling it, but it’s just fun and interesting to sus out the nuances on the subject.

There are a few fairly hard facts here:

  1. Even LFP manufacturers recommend reducing the charge (to somewhere between 40 and 80?) for storage. So it’s pretty clear that sitting idle at 100% most of the time is less than optimal.
  2. This effect is FAR less detrimental to the battery health for LFPs than for other lithium ion chemistries.
  3. The value of having as much energy as possible available to you when you need it should definitely outweigh any degradation concerns in an LFP bank.
  4. Your batteries need a good period at 100% every so often to balance the cells.

Still - for those of us with use-cases that involve long periods of non-usage - like a boat or a camper sitting idle for weeks at a time while you’re working, it seems a little unnecessary to keep them at 100% for all that time. I also have made several Node red flows to avoid this - but I decided to try and avoid the micro-cykling. (Mine would keep oscillating between 75 and 80%.) So I started to use the «prefer renewable energy» function in the Multiplus which will keep them at a stable voltage (corresponding to 70% SOC) for a period of up to 4 weeks before taking them to 100% for balancing. I then use VRM to access the Node red dashboard and switch to «full charge» some hours before using the boat so that I always have 100% available when going sailing.
This works pretty good for me.