• Have you tried out dark mode?! Scroll to the bottom of any page to find a sun or moon icon to turn dark mode on or off!

diy solar

diy solar

Home Assistant Adaptive Battery Charging

Haysdb

Solar Enthusiast
Joined
May 30, 2024
Messages
435
Location
Thailand
I added 20 kWh of battery storage to a 12.6 kW solar system a couple of months ago. For multiple reasons I will elaborate on shortly, I set about creating an adaptive battery charging functionality in Home Assistant. On sunny days when excess power is forecast, I adjust the maximum charging rate every 15 minutes to defer the batteries reaching 100% SOC until a "target hour". The system is composed of a dashboard, two automations, and a variety of template sensors. And of course input_number and various other 'helpers'.

Why? Three reasons:
1. The charge controller of my Deye inverter is painfully unsophisticated. It charges the batteries to 100% and then holds them at "over current protection" voltage until the sun goes down. 4 to 6 hours at 57.6v until I lowered it. Charging isn't configurable in any way. Just full speed and then hold for the rest of the day. Maybe this is fine but I don't like it.
2. I can't export power yet but when I get approved, my export will be limited due to the capacity of my electric meter and the wire gauge between the inverter and the meter. If all excess energy goes to the batteries until they're fully charged, then power will be curtailed to the maximum power I can export to the grid. This will not maximize the amount of power my system can produce. I'll want to try to balance charging and export to maximize utilization of my system.
3. There will be days where there is enough power to charge the batteries, but only if none is wasted. Imagine a day with sunshine until 11 and then rain. In that scenario I'll want to charge with all available power. Normally I'd prefer to limit charging to around .25c, but when necessary I want to use every available watt to charge the batteries.

I will elaborate on what I have built, probably in excruciating detail, but for now I just wanted to get this thread started. For now here is a screenshot of my Home Assistant dashboard.
 

Attachments

  • Screenshot 2025-04-01 at 11.14.56 AM.png
    Screenshot 2025-04-01 at 11.14.56 AM.png
    333.5 KB · Views: 23
The algorithm is comprised of 5 main template sensors:

# Hourly Forecast - The Solcast hourly forecast reformatted with just the hours I want
# Available Solar Energy - Forecast energy "available" to charge the batteries
# Allocation This Hour - The amount of energy I want to add this hour
# Max Charge Current - Calculate Max Charge Current for the automation
# Target Hour Calc - Runs at 7 AM and 11 AM to set a target hour

An automation runs every 15 minutes to set max_charging_current on the inverter. Another automation runs at 7 and 11 to set a target hour based on the "10%" Solcast forecast. My first priority is to make sure the batteries get charged to 100% so I use the pessimistic forecast. The charge rate will slow down if charging gets ahead of schedule.
 
Last edited:
The automation now runs every 10 minutes and a target hour is recalculated every hour because the forecast is updated every hour and can change throughout the day as there's progressively less uncertainty. I'm now using a compromise between the "most likely" forecast and the pessimistic forecast. It's set at 50/50 but I have a slider to adjust the balance. The system has a lot of dials. I expect I'll settle on settings that work and eventually stop fiddling with them.

Another feature I added is I keep track of home load every hour and present the algorithm with a 3 day moving average for each hour. This way I can estimate how much excess solar will be "available" each hour.

Something "clever" I did is to insert some "logging" into the core template sensor that calculates how much energy to allocate to charging the batteries. If the system does something I don't understand I can just copy the entire state section of the sensor into the template tester and change one line and see the values of all the variables. I discovered that blank lines in the output can be suppressed with {%- and {#-. This makes the output easier to read.
 
Here is the dashboard. The graphs have a lot of information, but it's all information I want to see. Today is the first day to test a scenario where there is energy early in the day but not in the afternoon. I've "wasted" some energy that I probably should have captured. There are several parameters that would have made the algorithm more aggressive sooner. I have those dialed down because I haven't yet seen this scenario so haven't been able to see how it would be handled. There are bound to be days where the forecast deteriorates and I end up not getting the batteries fully charged. I'm at the mercy of the forecast.
 

Attachments

  • Screenshot 2025-04-12 at 12.09.18 PM.png
    Screenshot 2025-04-12 at 12.09.18 PM.png
    375.5 KB · Views: 13
As soon as the algorithm detected that there was less energy "available" than was needed to finish charging, it kicked max current to 160A, we got a burst of sunshine, and the batteries went from 80% to 100% in a hurry. This is one of the serendipitous features of the system. Normally I would set the max charge rate to .25c / 100A, but the batteries, battery cables, breaker and inverter are all capable of handling 160A, so if there is a scenario where there's power available now but not later, the batteries can be charged with all available solar power with no restriction.
 

Attachments

  • Screenshot 2025-04-12 at 12.24.24 PM.png
    Screenshot 2025-04-12 at 12.24.24 PM.png
    59.7 KB · Views: 4
  • Screenshot 2025-04-12 at 12.24.48 PM.png
    Screenshot 2025-04-12 at 12.24.48 PM.png
    75 KB · Views: 4
The dashboard looks really cool in portrait mode on an iPad in dark mode.

The dip midday today was a head fake, but the forecast was for it to continue being cloudy and "available" energy after noon was zero, so the batteries got charged with all available solar energy, which turned out to be a lot. The charge rate hit nearly 150A. This turned out to be extremely interesting though. When the batteries hit the first voltage threshold that caused the inverter to reduce power to 10A per battery, the battery was really only 96% full. It took more than another 30 minutes before they finally did get charged to 100% because the inverter waited 30 minutes before starting to charge again.
 

Attachments

  • IMG_4203.PNG
    IMG_4203.PNG
    209.1 KB · Views: 8
I do similar things via the max charge amp setting on controllers but I gave up on using the solar prediction for the day feature since it is horribly inaccurate for where I live. Also I have it dumping excess power to my crypto mining rigs these days so I don't do much in the limiting part now.
 
One of the goals of the adaptive charging is to try to maximize utilization of solar power by splitting power between batteries and export. Because of the limited capacity of my electric meter I need to restrict export to about 5500 watts (25 amps @220v). If the batteries are charged by noon, this will force curtailment of solar power, so I "follow the solar curve" with battery charging. It worked perfectly today.

My Solcast forecasts often start the day with a huge differential between the 'most likely' forecast and the 10% forecast, but they tend to converge as the day wears on. I get a new forecast each hour. I'm splitting the difference been the two forecasts, so if there is a 40% difference, hopefully I'm within 20%. The automation runs every 10 minutes so it can adjust pretty quickly to a changing forecast.
 

Attachments

  • Screenshot 2025-04-15 at 11.58.32 AM.png
    Screenshot 2025-04-15 at 11.58.32 AM.png
    92.9 KB · Views: 2
Last edited:
Very very cool. You should also post in the HA forum and/or Discord, they'd love to see this I'm sure.
 
The adaptive charging worked perfectly today. After endless tinkering today it "just worked." Charge power ramped down smoothly so that when the batteries high voltage alarm triggered and the inverter dropped current to 10A per battery, there was no bounce, just a smooth continuation up to high voltage protection. The inverter paused until voltage dropped by .4v and then hit the batteries again with current to top them off. There was a period of clouds and battery discharge but the batteries charged again to 100%. The inverter current barely rose above high voltage protection. Nice and easy with no drama.

There has been an edge case that's happened twice in the last week where the batteries got hit with high current right near 100% SOC and battery voltage "bounced" off HVA. The inverter dropped current to 10A per battery but because the batteries had been hit with so much current, they weren't fully absorbed at that voltage and instead of the voltage continuing to rise, it dropped. The inverter waits 30 minutes before it supplies current again. One day the batteries did finish charging...an hour and forty minutes after first hitting high voltage alarm, but on the other day they never did hit 100%.

A added logic to smoothly ramp down maximum charge current from 220A at 85% to 40A at 97% to avoid the batteries from getting hit with 140A at 98% SOC. I don't think that came into play today because there was ample sunshine and excess power so the current ramped down without any help. The batteries finished charging around 2:30 with a 3:00 target. They finished a bit early because I set a minimum charge current of 40A. I've seen SOC just hang for 2 hours at a current lower than 40A and I want to add at least 10% SOC every hour, so I think 40A is the right number for a minimum.

I've gone back and forth about max charge current but I've settled on 220A on days where "available" solar energy is forecast to be less than energy needed. That's the maximum for the inverter, the 250A breaker and the battery cables. The batteries will never see thst much current, and they'll rarely even see 150A for more than a few minutes, but why limit how much energy the batteries can absorb on a day when every watt is needed? I've seen 13,500 watts from my system with my own eyes so they COULD conceivably see that much current for a brief moment, and on a cloudy day, I want to capture that energy.
 

Attachments

  • Screenshot 2025-04-19 at 5.21.29 PM.png
    Screenshot 2025-04-19 at 5.21.29 PM.png
    270.7 KB · Views: 2
Last edited:
It’s extremely gratifying to see this work. It’s taken a crazy amount of experimentation. Today is textbook perfect. I may finally be ready to hide most of the dials and only expose them when the edit switch is on. They’ll still be there if I need them but out of sight otherwise.
 

Attachments

  • IMG_4208.jpeg
    IMG_4208.jpeg
    318.7 KB · Views: 7
I’m rather proud of this dashboard. I got tired of editing the apexcharts code to adjust various parameters so I created input-number “helpers” so I can now adjust the axis and line weights to focus on specific series and hide others. I’ve been absolutely obsessed with battery charging so I’ve spent an unhealthy amount of time studying voltages and current and inverter charging behavior.
 

Attachments

  • IMG_4212.png
    IMG_4212.png
    146.6 KB · Views: 11

diy solar

diy solar
Back
Top