• 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

YamBMS JK-BMS-CAN with new Cut-Off Charging Logic (open-source)

Which problem does YamBMS try to solve? How does YamBMS accomplish that goal.
Too many (problems) at once actually.
  • First and foremost is facilitating inverter communication for DIY batteries. Currently over CANBus. The YAM in YamBMS stands for combining multiple such DIY batteries in parallel with your inverter.
    For many users new to the Solar landscape, it commonly translates to their DIY battery setups enjoying benefits of battery data availability on remote monitoring portal. As it did for me.
  • Not just that, YamBMS features far better, and highly adaptive charging logic than anything currently in existence, unsurpassed even by proprietary manufacturers. Many careful choices made were the result of purely academic and theoretical deliberations over months. That is 'almost' a technical whitepaper in its own right.
  • Third is the idea of having control and 'actually owning' the hardware you bought.
    For example, My inverter model exports electricity only after it has fully charged the battery. So, I've automated a 'charging current limit zero' command for it to export electricity whenever I want to.
    Open Hardware, Open software, Secure & Private Home.

When sending these highly dynamic requested charge voltage and termination/cut-off values to the inverter/charge-controller. Are these values being written to EPROM somewhere in the inverter? How afraid should one be that the inverter of BMS is out of EPROM write/erase/program cycles (100,000 times the number of spare pages available) because of the highly dynamic (read: 17,280 times a day sending the requested value at a 5 second interval)
Inverter manufacturers themselves specify that these values sent over the communication bus at 1 Hz. Not just charging parameters but battery health and cell level data is also sent.

The same logic applies when discharging, it high datasheet discharge rates LFP cells can be discharged to 2.5 volts per cell. When the discharge rate is lower, discharging the battery should be stopped at a higher voltage then datasheet value. (The lithium cell discharge voltage level is current dependant).

I think that YamBMS currently only handles the charging part, not the discharging part, or does it?
Absolutely! There so many implementations that need to be done properly by BMS and Inverter manufacturers' side. This is just one of the many.
We have to workaround and are bottlenecked by the features implemented into inverters at the moment. We can 'request' hardware what to do, not 'control' it.
 
Last edited:
...In those cases, the logic within YamBMS will automatically reduce the maximum allowable discharge current as the battery reaches UVP.
Is YamBMS UVP also having dynamic (read: discharge-current-dependant) voltage logic similar to the charging logic?
I mean increase UVP for small discharge currents, and have UVP at 2.5V/cell for maximum discharge current (at 25ºC Tcell)?
Or is such dynamic discharging limit not necessary at all?

This brings me to the next question: does YamBMS factor in the cell temperature, into the "allowable charge current"?

From MB31 datasheet. Charge maximum rate:
0.05P between 0 and 5ºC
0.12P between 5 and 10ºC
0.30P between 10 and 15ºC
0.50P between 15 and 55/60ºC

For discharge there is no temperature maximum rate in the MB31 datasheet, I mean: between -20ºC and 55/60ºC its always 0.5P. However at temperatures below 25ºC leave room for deeper discharge voltages at 0.5P, before reaching 0% SoC.
 
Is YamBMS UVP also having dynamic (read: discharge-current-dependant) voltage logic similar to the charging logic?
I mean increase UVP for small discharge currents, and have UVP at 2.5V/cell for maximum discharge current (at 25ºC Tcell)?
Or is such dynamic discharging limit not necessary at all?

Currently UVP is used for the following:
  • Cell Low V. = Cell UVP + 0.02
  • Max discharge voltage = cell_low_v * cell_count
  • If min_cell_v <= cell_low_v SoC 0% is sent
  • Auto DCL function will reduce the discharge current when min_cell_v approaches cell_low_v
Regarding a dynamic UVP depending on the discharge current I don't think it is necessary, as you can see on the graph below from 2.8V/cell the SoC can be considered at 0% regardless of the discharge current.

If we look at what happens at 3.0V during a discharge at 1C we would still be at 5% against 0% for a discharge at 0.1C. But who discharges their battery at 1C?

LF280 LFP 280Ah battery discharge and charge curves.png


This brings me to the next question: does YamBMS factor in the cell temperature, into the "allowable charge current"?

From MB31 datasheet. Charge maximum rate:
0.05P between 0 and 5ºC
0.12P between 5 and 10ºC
0.30P between 10 and 15ºC
0.50P between 15 and 55/60ºC

Currently there is no adaptation of the charging current according to the temperature.
I assume that you configure your BMS to stop charging at 0°C.
Regarding high temperature I use OTP at 50°C and OTPR at 45°C

It would be complicated to create a charging profile for each type of cell (some use several batteries composed of different cell models) but we could make one for each type of chemistry.

Here is what is written in the EVE LF280K V3 datasheet, it may be different from MB31.

So we should find reasonable values for LFP.

Do you agree that for a 280Ah cell 1P = 280 * 3.2V?

Capture d’écran 2024-12-04 à 09.34.56.png

Discharging rate

Capture d’écran 2024-12-04 à 10.11.00.png
 
Last edited:
My YamBMS (1.4.5) just started cycling between charge/discharge, and the SOC drops to 0% as if it is losing communication somehow. Currently 1 BMS is reporting 59%, other is 54%. My inverter is set to self-consumption mode, so it should prefer the battery, and only use the grid if battery is too low, I have the inverter set to only charge the battery via grid if it drops below 22%, and YamBMS is set to request charge at 10%. It is currently night time, so no PV. Was working fine a while ago, was pulling 8000w between the 2 packs, I power cycles everything and still not sure what is going on. No alarms at the packs or anywhere else. On the BMS control page I cannot move the switches for charge/discharge on BMS1, and the charge/discharge status show "unknown". Attached a log.

1733303893885.png


1733303862121.png
1733303979036.png
 

Attachments

My YamBMS (1.4.5) just started cycling between charge/discharge, and the SOC drops to 0% as if it is losing communication somehow. Currently 1 BMS is reporting 59%, other is 54%. My inverter is set to self-consumption mode, so it should prefer the battery, and only use the grid if battery is too low, I have the inverter set to only charge the battery via grid if it drops below 22%, and YamBMS is set to request charge at 10%. It is currently night time, so no PV. Was working fine a while ago, was pulling 8000w between the 2 packs, I power cycles everything and still not sure what is going on. No alarms at the packs or anywhere else. On the BMS control page I cannot move the switches for charge/discharge on BMS1, and the charge/discharge status show "unknown". Attached a log.

View attachment 260530


View attachment 260529
View attachment 260531


Quick analysis, one of your cells reached the UVPR value which sent a SoC of 0%.

What value did you use for UVPR?

Check your cell voltage graphs.
 
@jahyde

3.0V per cell is almost 0%. The soc of both your BMS are completely wrong.

FYI : since YamBMS 1.5.1 we replaced UVPR with UVP+0.02V.
 
But who discharges their battery at 1C?
The one with a 15 kVA (290A) or 12 kVA (250A) hybrid LV inverter per 1 battery bank and trying to make make money on the 60 / 15 minute energy markets.

Update: Near EoL 1C will be reached more often as 280Ah times 0,7 = 196 Ah. Because according to the Eve datasheet you quoted: "the charging power (rate) must me adjusted to the SoH (capacity attenuation)".

Do you agree that for a 280Ah cell 1P = 280 * 3.2V?
Yes, I agree: 1P = 1C times nominal voltage of 3.2V. 280Ah, 1C = 280A, thus 1P = 896 W
 
Last edited:
If we look at what happens at 3.0V during a discharge at 1C we would still be at 5% against 0% for a discharge at 0.1C.
I read the "New cell initial performance of EVE LF280 LiFePo4 280 AH discharge & charge curves at cell current rate equilibrium @ 25 dags C" graph as: at 1C you can discharge down to 2.775V, at 0.5C down to 2,85V, at 0.2C down to 2,93V, at 0.1C down to 2,99V, and at near 0.0C only down to 3,075V.

The current related maximum charge voltage (100% SoC) is there on the discharge (to 0% SoC) as well, as current dependant discharge voltage.

As long as al other cell manufacturer datasheet recommendations are followed (temperature rate restrictions/clamping force/clamping cells between 10-17mm thick steel, not plywood/etcetera), and charging (even just slow) starts after 30 minutes rest, I don't see any reason why not to discharge down to 0% SoC.

Update: The user just above (@jahyde) is already trying to discharge below 0% SoC: rate = 0.003C at lowest cell 3.057V (=below 3.075V)
 
Last edited:
I read the "New cell initial performance of EVE LF280 LiFePo4 280 AH discharge & charge curves at cell current rate equilibrium @ 25 dags C" graph as: at 1C you can discharge down to 2.775V, at 0.5C down to 2,85V, at 0.2C down to 2,93V, at 0.1C down to 2,99V, and at near 0.0C only down to 3,075V.

The current related maximum charge voltage (100% SoC) is there on the discharge (to 0% SoC) as well, as current dependant discharge voltage.

As long as al other cell manufacturer datasheet recommendations are followed (temperature rate restrictions/clamping force/clamping cells between 10-17mm thick steel, not plywood/etcetera), and charging (even just slow) starts after 30 minutes rest, I don't see any reason why not to discharge down to 0% SoC.

If you discharge with 1C current (which is certainly not good for the cells and requires using a 300A BMS) and at 0% every day there is an interest in applying a 0% discharge logic.

Personally my battery is more often charged to 100% than discharged to 0%.

@MrPablo @shvm @Der_Hannes what do you think ?
 
Last edited:
@Sleeper85 Testing the heat functionI have have set a higher UTP and UTPR and intentionally triggered UTP alarm. The Yambms displayed a warning alarm but it was OTP instead UTP, please take in consideration to check this issue in the fallowing update.
1733407703628.png
below is a screenshot from the BMS
1733407825359.png

Another thing:
Why is showing cell real count 15?
1733408223403.png
as in reality i have 16 cells?
1733408348496.png
 
Last edited:
@Sleeper85 Testing the heat functionI have have set a higher UTP and UTPR and intentionally triggered UTP alarm. The Yambms displayed a warning alarm but it was OTP instead UTP, please take in consideration to check this issue in the fallowing update.
View attachment 260774
below is a screenshot from the BMS
View attachment 260775

Another thing:
Why is showing cell real count 15?
View attachment 260776
as in reality i have 16 cells?
View attachment 260777

I guess you are using the RS485 component for JK-PB?

Cell real count is an info coming from @txubelaxu component, it's strange that it's 15.

YamBMS cell count is what is configured in the main YAML.

Concerning the error, do you have the value of errors_bitmask ?
 
Last edited:
I guess you are using the RS485 component for JK-PB?

Cell real count is an info coming from @txubelaxu component, it's strange that it's 15.
Yes i am using RS485.

Here is bitmask error. The values i change are UTP and UTPR, nothing related to Powertube, or MOS. I guess there are some entities names switched in the code.
1733412691346.png
1733412858688.png

As a clarification. The PB BMS has only 4 temperature sensors. (Temp 1, 2, 4, 5). Temperature sensor 3 is the MOS or PowerTube temperature with one decimal accuracy.
1733413533726.png
 
Last edited:
@virus100b

The two sensors below are those of the JK-PB component on which YamBMS is based.

So I think the problem is in the component developed by @txubelaxu

1733421081155.png

An errors_bitmask of 2 corresponds to a Power tube overtemperature alarm.

YamBMS analyzes the bitmask value and returns the name of the corresponding alarm, therefore OTP.

C++:
  # +--------------------------------------+
  # | Errors Bitmask (16bit)               |
  # +--------------------------------------+
      
  # 0x8B 0x00 0x00: Battery warning message              0000 0000 0000 0000
  #
  # Bit 0    Low capacity                                1 (alarm), 0 (normal)    warning
  # Bit 1    Power tube overtemperature                  1 (alarm), 0 (normal)    alarm
  # Bit 2    Charging overvoltage                        1 (alarm), 0 (normal)    alarm
  # Bit 3    Discharging undervoltage                    1 (alarm), 0 (normal)    alarm
  # Bit 4    Battery over temperature                    1 (alarm), 0 (normal)    alarm
  # Bit 5    Charging overcurrent                        1 (alarm), 0 (normal)    alarm
  # Bit 6    Discharging overcurrent                     1 (alarm), 0 (normal)    alarm
  # Bit 7    Cell pressure difference                    1 (alarm), 0 (normal)    alarm
  # Bit 8    Overtemperature alarm in the battery box    1 (alarm), 0 (normal)    alarm
  # Bit 9    Battery low temperature                     1 (alarm), 0 (normal)    alarm
  # Bit 10   Cell overvoltage                            1 (alarm), 0 (normal)    alarm
  # Bit 11   Cell undervoltage                           1 (alarm), 0 (normal)    alarm
  # Bit 12   309_A protection                            1 (alarm), 0 (normal)    alarm
  # Bit 13   309_A protection                            1 (alarm), 0 (normal)    alarm
  # Bit 14   Reserved
  # Bit 15   Reserved
  #
  # Examples:
  # 0x0001 = 00000000 00000001: Low capacity alarm
  # 0x0002 = 00000000 00000010: MOS tube over-temperature alarm
  # 0x0003 = 00000000 00000011: Low capacity alarm AND power tube over-temperature alarm
 
I double checked, both packs were uvpr 2.65. I lowered it to 2.58... but all of those cells were well over 3v.
 
I double checked, both packs were uvpr 2.65. I lowered it to 2.58... but all of those cells were well over 3v.
And at which state (charging/discharging) and which rate?

When the values of your screenshot are correct, I read: BMS1 is discharging at 0.03C. BMS2 is in rest.

For BMS2 the SoC is already below 0%. Resting voltage for SoC 0% is approximately 3,075 V. Cells #12 and 13 are below this point. When factoring in measurement accuracy, the other ones might be as well.

For BMS1 the SoC based on 3,057V and discharging 0.03C is approaching 0% when the lowest cell hits approximately the 3,040 voltage mark.

Or, am I misinterpreting the Voltage-SoC-rate graph below?

LF280 AH battery dischg 0.1C-1.0C.png
 
I double checked, both packs were uvpr 2.65. I lowered it to 2.58... but all of those cells were well over 3v.

You don't have to lower your UVPR it is already very low. My UVPR is at 3.0V.

Starting from YamBMS 1.5.1 it is UVP+0.02V that is used (my UVP is at 2.8V).

Does your BMS have the SoC 0% parameter?

Can you show us the cell_min_v graphs of your two BMS at the time of the problem?

It would also be interesting to see the number of BMS combined at the time of the problem.
 
I have a small problem. I previously had two BMSs, which I had to replace with two new ones. My storage system completed several dozen cycles on the previous BMSs. Is it possible to add a manual cycle count adjustment so that the SOH (State of Health) is calculated correctly?
 
I have a small problem. I previously had two BMSs, which I had to replace with two new ones. My storage system completed several dozen cycles on the previous BMSs. Is it possible to add a manual cycle count adjustment so that the SOH (State of Health) is calculated correctly?

In YamBMS it would be possible by modifying the code but it would be necessary to adapt the code to each version, in the BMS I don't think so...
 
I understand that it might not be possible directly in the BMS, but I’m asking specifically about YamBMS. My question is whether a "box" for entering such a value will be added in an update, or do you mean manually modifying the code on my end?
 
This part of the charging state machine below is hard to read for newbies like me.

How can the code loop in two directions at the same time, after the blue "Cut-Off" block?

What is meant with "switch" in the sentence "controlled by a switch".
A physical button-like device, or a statement in code?

esphome-yambms_documents_README_Charging_logic.md at main · Sleeper85_esphome-yambms · GitHub.png
 
This part of the charging state machine below is hard to read for newbies like me.

How can the code loop in two directions at the same time, after the blue "Cut-Off" block?

What is meant with "switch" in the sentence "controlled by a switch".
A physical button-like device, or a statement in code?

View attachment 261106

The first code did not use the EOC timer switch (switch you will find in HA). The charge ended in the cut-off phase if there was no equalization in progress for 60s. This works well with a single battery but it can be a big problem with several batteries of different quality, the end of charge could then last an eternity, so I added this 30min timer (default value that you can change) to end the charge at the latest after 30 minutes even if the cells of all the batteries are not equalized. I added a switch that allows to use or not this EOC timer, which is useful if you want to properly equalize your batteries.
 
You don't have to lower your UVPR it is already very low. My UVPR is at 3.0V.

Starting from YamBMS 1.5.1 it is UVP+0.02V that is used (my UVP is at 2.8V).

Does your BMS have the SoC 0% parameter?

Can you show us the cell_min_v graphs of your two BMS at the time of the problem?

It would also be interesting to see the number of BMS combined at the time of the problem.
At ~12am on 12/5 I know SOC was 62%, at 3am Cell_Min_V was 3.11v, during this time there was only 3 refrigerators running, a hot water heater *might* come on for 5~8 minutes every ~4 hours, between 2x packs of 280ah, not sure how it could have drained, and I was even ongrid at the time, and my inverter is configured to top up the battery to 20% if it hits 15%. My inverter reported at 6:10am a 4kw load, which would have been the hotwater heater, but it was reading 57% SOC at the inverter pulling 112amps from the battery, then at ~6:15 the inverter reports it was pulling from the grid. Didnt notice anything at all since we were ongrid, inverter set to self-consumption mode, so use solar/bat first, then use grid. Then I just happened to check my HA around 9am and reset the ESP32 and set the inverter to force charging. It was not allowing any charge because the inverter could not get SOC from YamBMS I think, inverter screen said lost communication with BMS.

I have UVP at 2.58, have since bumped things up a bit, below are all my current JK settings.

Last night I tested again - with grid main breaker turned off, we finish the night around ~65% SOC @11:30, turn off lights/heating, by 7am we were at 59%, then started producing 1-2KW PV, by 8am we are taking in 5KW... 98% SOC at ~9:30am.

Here is the min voltage:
1733530677731.png
SOC started bouncing up and down for some reason around 6:16am-

1733532971386.png
3 seconds later SOC increased-
1733532858051.png

2 minutes later we lost everything:
1733532868392.png

1733531151261.png

Here is inverter data around that time:

1733533045392.png
Minutes later we seem to have a protection event.
1733533062429.png
This is a Midnight MN15 AIO. 2x JK-PB2A16S-20P v15 HW, 15.30 FW, today updated to 15.33, YamBMS 1.4.5.
1733533368673.png
If these are bad protection settings, I am definitely open to suggestions. My inverter is set to use 15-100% SOC range, if SOC gets to 10% it should charge from grid to bring it back over 15%.
 

Attachments

  • 1733531059121.png
    1733531059121.png
    25.3 KB · Views: 1
Does anything need to be changed to manage PSRAM size on board_esp32-s3-devkitc-1_mcp2515? I have another board with 2mb PSRAM:

1733545410332.png

I see in the notes it says "QD stands for Quad SPI and OT stands for Octal SPI." Do I need to change anything else besides these lines:
YAML:
# PSRAM activation and settings
psram:
  mode: quad
  speed: 80MHz
 
Last edited:
View attachment 261187
If these are bad protection settings, I am definitely open to suggestions. My inverter is set to use 15-100% SOC range, if SOC gets to 10% it should charge from grid to bring it back over 15%.
UVPR at 2.65 volts is really low. When your 4 kW load is running that draws 90-95 amps in the low SoC's. When UVP=2.6 is reached, the load gets disconnected and the battery is empty. In a matter of seconds, maybe a few minutes, after disconnect, the voltage will "bounce" back from 2.6 to 2.65 volts (only 50 millivolts). I've seen rates in the 1 millivolt per second range.

I would Increase UVPR to a 0% SoC value at 0 load. Under that set UVPR point there shouldn't be any case to discharge the battery further. I would say, based on the equilibrium graph, that SOC 0% Volt. (V) = 3.075 volts (batt.state=resting).

The 3.075V might need a little tweaking (millivolts decrease) when your (deeply) discharged battery voltage doesn't recover to that point in (let's say at least 30 minutes to a few hours), and after some resting time is still not ready for charging (because the BMS keeps the battery disconnected).

Note: MrPablo sets UVPR to 3.001V and SoC-0% Volt. to 3.000V (state Nov. 2024)
Auto CCL _ DCL functions with JK-PB and new JK-B · Issue #11 · Sleeper85_esphome-yambms · GitHub.png

PS Understanding your case would benefit from descriptions like "I expected to see ... here." next to "I see ... happening" (the latter is present).
 
Last edited:

diy solar

diy solar
Back
Top