Skip to content

Commit

Permalink
Changes 2023.05.02
Browse files Browse the repository at this point in the history
* Added: Read charge/discharge limits from JKBMS by @mr-manuel
* Changed: Fix for Louisvdw#450 by @mr-manuel
* Changed: Other small fixes and optimizations
  • Loading branch information
mr-manuel committed May 2, 2023
2 parents fce00b9 + ebfb5bc commit 1d82436
Show file tree
Hide file tree
Showing 11 changed files with 113 additions and 45 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
* Added: JKBMS BLE - Show if balancing is active and which cells are balancing by @mr-manuel
* Added: Post install notes by @mr-manuel
* Added: Recalculation interval in linear mode for CVL, CCL and DCL by @mr-manuel
* Added: Read charge/discharge limits from JKBMS by @mr-manuel
* Added: Script to install directly from repository by @mr-manuel
* Added: Show charge mode (absorption, bulk, ...) in Parameters page by @mr-manuel
* Added: Show charge/discharge limitation reason by @mr-manuel
Expand All @@ -50,6 +51,7 @@
* Changed: Fix for https://github.com/Louisvdw/dbus-serialbattery/issues/351 by @mr-manuel
* Changed: Fix for https://github.com/Louisvdw/dbus-serialbattery/issues/397 by @transistorgit
* Changed: Fix for https://github.com/Louisvdw/dbus-serialbattery/issues/421 by @mr-manuel
* Changed: Fix for https://github.com/Louisvdw/dbus-serialbattery/issues/450 by @mr-manuel
* Changed: Fixed black lint errors by @mr-manuel
* Changed: Fixed cell balancing background for cells 17-24 by @mr-manuel
* Changed: Fixed Time-To-Go is not working, if `TIME_TO_SOC_VALUE_TYPE` is set to other than `1` https://github.com/Louisvdw/dbus-serialbattery/pull/424#issuecomment-1440511018 by @mr-manuel
Expand Down
64 changes: 41 additions & 23 deletions etc/dbus-serialbattery/battery.py
Original file line number Diff line number Diff line change
Expand Up @@ -150,12 +150,12 @@ def to_temp(self, sensor: int, value: float) -> None:
:param value: the sensor value
:return:
"""
if sensor == 0:
self.temp_mos = min(max(value, -20), 100)
if sensor == 1:
self.temp1 = min(max(value, -20), 100)
if sensor == 2:
self.temp2 = min(max(value, -20), 100)
if sensor == "mos":
self.temp_mos = min(max(value, -20), 100)

def manage_charge_voltage(self) -> None:
"""
Expand Down Expand Up @@ -232,17 +232,19 @@ def manage_charge_voltage_linear(self) -> None:
)

self.charge_mode = (
"Bulk dynamic (vS: "
+ str(round(voltageSum, 2))
+ " - pS: "
+ str(round(penaltySum, 2))
+ ")"
"Bulk dynamic"
# + " (vS: "
# + str(round(voltageSum, 2))
# + " - pS: "
# + str(round(penaltySum, 2))
# + ")"
if self.max_voltage_start_time is None
else "Absorption dynamic (vS: "
+ str(round(voltageSum, 2))
+ " - pS: "
+ str(round(penaltySum, 2))
+ ")"
else "Absorption dynamic"
# + "(vS: "
# + str(round(voltageSum, 2))
# + " - pS: "
# + str(round(penaltySum, 2))
# + ")"
)

elif self.allow_max_voltage:
Expand All @@ -263,7 +265,7 @@ def manage_charge_voltage_linear(self) -> None:
and voltageDiff >= utils.CELL_VOLTAGE_DIFF_TO_RESET_VOLTAGE_LIMIT
):
self.charge_mode += " + Balancing"
self.charge_mode += " (LM)"
self.charge_mode += " (Linear Mode)"

def manage_charge_voltage_step(self) -> None:
"""
Expand Down Expand Up @@ -327,7 +329,11 @@ def manage_charge_current(self) -> None:
charge_limits = [
self.max_battery_charge_current
] # gets removed after finished testing
charge_limits_new = {self.max_battery_charge_current: "None (Max Config Limit)"}
charge_limits_new = {utils.MAX_BATTERY_CHARGE_CURRENT: "Config Limit"}

# if values are not the same, then the limit was read also from the BMS
if utils.MAX_BATTERY_CHARGE_CURRENT != self.max_battery_charge_current:
charge_limits_new.update({self.max_battery_charge_current: "BMS Limit"})

if utils.CCCM_CV_ENABLE:
tmp = self.calcMaxChargeCurrentReferringToCellVoltage()
Expand Down Expand Up @@ -399,9 +405,9 @@ def manage_charge_current(self) -> None:

self.charge_limitation = (
charge_limits_new[min(charge_limits_new)]
+ " ("
+ str(round(min(charge_limits_new), 3))
+ ")"
# + " ("
# + str(round(min(charge_limits_new), 3))
# + ")"
)

if self.control_charge_current == 0:
Expand All @@ -415,9 +421,13 @@ def manage_charge_current(self) -> None:
discharge_limits = [
self.max_battery_discharge_current
] # gets removed after finished testing
discharge_limits_new = {
self.max_battery_discharge_current: "None (Max Config Limit)"
}
discharge_limits_new = {utils.MAX_BATTERY_DISCHARGE_CURRENT: "Config Limit"}

# if values are not the same, then the limit was read also from the BMS
if utils.MAX_BATTERY_DISCHARGE_CURRENT != self.max_battery_discharge_current:
discharge_limits_new.update(
{self.max_battery_discharge_current: "BMS Limit"}
)

if utils.DCCM_CV_ENABLE:
tmp = self.calcMaxDischargeCurrentReferringToCellVoltage()
Expand Down Expand Up @@ -493,9 +503,9 @@ def manage_charge_current(self) -> None:

self.discharge_limitation = (
discharge_limits_new[min(discharge_limits_new)]
+ " ("
+ str(round(min(discharge_limits_new), 3))
+ ")"
# + " ("
# + str(round(min(discharge_limits_new), 3))
# + ")"
)

if self.control_discharge_current == 0:
Expand Down Expand Up @@ -900,6 +910,14 @@ def log_settings(self) -> None:
f"> MAX BATTERY CHARGE CURRENT: {utils.MAX_BATTERY_CHARGE_CURRENT}A | "
+ f"MAX BATTERY DISCHARGE CURRENT: {utils.MAX_BATTERY_DISCHARGE_CURRENT}A"
)
if (
utils.MAX_BATTERY_CHARGE_CURRENT != self.max_battery_charge_current
or utils.MAX_BATTERY_DISCHARGE_CURRENT != self.max_battery_discharge_current
):
logger.info(
f"> MAX BATTERY CHARGE CURRENT: {self.max_battery_charge_current}A | "
+ f"MAX BATTERY DISCHARGE CURRENT: {self.max_battery_discharge_current}A (read from BMS)"
)
logger.info(f"> CVCM: {utils.CVCM_ENABLE}")
logger.info(
f"> MIN CELL VOLTAGE: {utils.MIN_CELL_VOLTAGE}V | MAX CELL VOLTAGE: {utils.MAX_CELL_VOLTAGE}V"
Expand Down
27 changes: 23 additions & 4 deletions etc/dbus-serialbattery/bms/battery_template.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,9 @@
# -*- coding: utf-8 -*-

# NOTES
# Please also update the feature comparison table, if you are adding a new BMS
# https://louisvdw.github.io/dbus-serialbattery/general/features/#bms-feature-comparison

from battery import Protection, Battery, Cell
from utils import is_bit_set, read_serial_data, logger
import utils
Expand All @@ -21,6 +26,9 @@ def test_connection(self):
result = False
try:
result = self.read_status_data()
# get first data to show in startup log
if result:
self.refresh_data()
except Exception as err:
logger.error(f"Unexpected {err=}, {type(err)=}")
result = False
Expand All @@ -32,12 +40,23 @@ def get_settings(self):
# Set the current limits, populate cell count, etc
# Return True if success, False for failure

# Uncomment if BMS does not supply capacity
# self.capacity = BATTERY_CAPACITY
self.max_battery_charge_current = utils.MAX_BATTERY_CHARGE_CURRENT
self.max_battery_discharge_current = utils.MAX_BATTERY_DISCHARGE_CURRENT
self.capacity = (
utils.BATTERY_CAPACITY # if possible replace constant with value read from BMS
)
self.max_battery_charge_current = (
utils.MAX_BATTERY_CHARGE_CURRENT # if possible replace constant with value read from BMS
)
self.max_battery_discharge_current = (
utils.MAX_BATTERY_DISCHARGE_CURRENT # if possible replace constant with value read from BMS
)
self.max_battery_voltage = utils.MAX_CELL_VOLTAGE * self.cell_count
self.min_battery_voltage = utils.MIN_CELL_VOLTAGE * self.cell_count

# provide a unique identifier from the BMS to identify a BMS, if multiple same BMS are connected
# e.g. the serial number
# If there is no such value, please leave the line commented. In this case the capacity is used,
# since it can be changed by small amounts to make a battery unique. On +/- 5 Ah you can identify 11 batteries
# self.unique_identifier = str()
return True

def refresh_data(self):
Expand Down
3 changes: 3 additions & 0 deletions etc/dbus-serialbattery/bms/ecs.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,9 @@ def test_connection(self):

self.find_LiPro_cells()

# get first data to show in startup log
self.refresh_data()

return self.get_settings()
except IOError:
return False
Expand Down
25 changes: 18 additions & 7 deletions etc/dbus-serialbattery/bms/jkbms.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,6 @@ def get_settings(self):
# After successful connection get_settings will be call to set up the battery.
# Set the current limits, populate cell count, etc
# Return True if success, False for failure
self.max_battery_charge_current = utils.MAX_BATTERY_CHARGE_CURRENT
self.max_battery_discharge_current = utils.MAX_BATTERY_DISCHARGE_CURRENT
self.max_battery_voltage = utils.MAX_CELL_VOLTAGE * self.cell_count
self.min_battery_voltage = utils.MIN_CELL_VOLTAGE * self.cell_count

Expand Down Expand Up @@ -84,18 +82,19 @@ def read_status_data(self):
unpack_from(">xH", celldata, c * 3 + 1)[0] / 1000
)

# MOSFET temperature
offset = cellbyte_count + 3
temp_mos = unpack_from(">H", self.get_data(status_data, b"\x80", offset, 2))[0]
self.to_temp(0, temp_mos if temp_mos < 99 else (100 - temp_mos))

# Temperature sensors
offset = cellbyte_count + 6
temp1 = unpack_from(">H", self.get_data(status_data, b"\x81", offset, 2))[0]
offset = cellbyte_count + 9
temp2 = unpack_from(">H", self.get_data(status_data, b"\x82", offset, 2))[0]
self.to_temp(1, temp1 if temp1 < 99 else (100 - temp1))
self.to_temp(2, temp2 if temp2 < 99 else (100 - temp2))

# MOSFET temperature
offset = cellbyte_count + 3
temp_mos = unpack_from(">H", self.get_data(status_data, b"\x80", offset, 2))[0]
self.to_temp("mos", temp_mos if temp_mos < 99 else (100 - temp_mos))

offset = cellbyte_count + 12
voltage = unpack_from(">H", self.get_data(status_data, b"\x83", offset, 2))[0]
self.voltage = voltage / 100
Expand All @@ -108,6 +107,18 @@ def read_status_data(self):
else (current - self.CURRENT_ZERO_CONSTANT) / 100
)

# Continued discharge current
offset = cellbyte_count + 66
self.max_battery_discharge_current = float(
unpack_from(">H", self.get_data(status_data, b"\x97", offset, 2))[0]
)

# Continued charge current
offset = cellbyte_count + 72
self.max_battery_charge_current = float(
unpack_from(">H", self.get_data(status_data, b"\x99", offset, 2))[0]
)

offset = cellbyte_count + 18
self.soc = unpack_from(">B", self.get_data(status_data, b"\x85", offset, 1))[0]

Expand Down
11 changes: 8 additions & 3 deletions etc/dbus-serialbattery/bms/jkbms_ble.py
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,11 @@ def test_connection(self):
return False

logger.info("JK BMS found!")

# get first data to show in startup log
self.get_settings()
self.refresh_data()

return True

def get_settings(self):
Expand Down Expand Up @@ -147,11 +152,11 @@ def refresh_data(self):
for c in range(self.cell_count):
self.cells[c].voltage = st["cell_info"]["voltages"][c]

self.to_temp(0, st["cell_info"]["temperature_mos"])
self.to_temp(1, st["cell_info"]["temperature_sensor_1"])
self.to_temp(2, st["cell_info"]["temperature_sensor_2"])
self.to_temp("mos", st["cell_info"]["temperature_mos"])
self.current = st["cell_info"]["current"]
self.voltage = st["cell_info"]["total_voltage"]
self.current = round(st["cell_info"]["current"], 1)
self.voltage = round(st["cell_info"]["total_voltage"], 2)

self.soc = st["cell_info"]["battery_soc"]
self.cycles = st["cell_info"]["cycle_count"]
Expand Down
9 changes: 5 additions & 4 deletions etc/dbus-serialbattery/bms/lltjbd.py
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,9 @@ def test_connection(self):
result = False
try:
result = self.read_hardware_data()
# get first data to show in startup log
if result:
self.refresh_data()
except Exception as err:
logger.error(f"Unexpected {err=}, {type(err)=}")
result = False
Expand Down Expand Up @@ -165,12 +168,10 @@ def read_gen_data(self):
self.max_battery_voltage = utils.MAX_CELL_VOLTAGE * self.cell_count
self.min_battery_voltage = utils.MIN_CELL_VOLTAGE * self.cell_count

# 0 = MOS, 1 = temp 1, 2 = temp 2
for t in range(self.temp_sensors):
temp1 = unpack_from(">H", gen_data, 23 + (2 * t))[0]
if t == 0:
self.to_temp("mos", utils.kelvin_to_celsius(temp1 / 10))
else:
self.to_temp(t, utils.kelvin_to_celsius(temp1 / 10))
self.to_temp(t, utils.kelvin_to_celsius(temp1 / 10))

return True

Expand Down
3 changes: 3 additions & 0 deletions etc/dbus-serialbattery/bms/renogy.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,9 @@ def test_connection(self):
result = False
try:
result = self.read_gen_data()
# get first data to show in startup log
if result:
self.refresh_data()
except Exception as err:
logger.error(f"Unexpected {err=}, {type(err)=}")
result = False
Expand Down
8 changes: 6 additions & 2 deletions etc/dbus-serialbattery/bms/revov.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,8 +54,12 @@ def test_connection(self):
result = False
try:
result = self.read_gen_data()
except:
pass
# get first data to show in startup log
if result:
self.refresh_data()
except Exception as err:
logger.error(f"Unexpected {err=}, {type(err)=}")
result = False

return result

Expand Down
4 changes: 3 additions & 1 deletion etc/dbus-serialbattery/config.default.ini
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,9 @@ FLOAT_CELL_VOLTAGE = 3.35
; Specify cell voltage diff where CVL limit is kept until diff is equal or lower
CELL_VOLTAGE_DIFF_KEEP_MAX_VOLTAGE_UNTIL = 0.010
; Specify cell voltage diff where CVL limit is reset to max voltage, if value get above
CELL_VOLTAGE_DIFF_TO_RESET_VOLTAGE_LIMIT = 0.050
; the cells are considered as imbalanced, if the cell diff exceeds 5% of the nominal cell voltage
; e.g. 3.2 V * 5 / 100 = 0.160 V
CELL_VOLTAGE_DIFF_TO_RESET_VOLTAGE_LIMIT = 0.080

; -- CVL reset based on SoC option (step mode)
; Specify how long the max voltage should be kept, if reached then switch to float voltage
Expand Down
2 changes: 1 addition & 1 deletion etc/dbus-serialbattery/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ def _get_list_from_config(

# Constants - Need to dynamically get them in future
DRIVER_VERSION = "1.0"
DRIVER_SUBVERSION = ".0-jkbms_ble (20230501)"
DRIVER_SUBVERSION = ".0-jkbms_ble (20230502)"
zero_char = chr(48)
degree_sign = "\N{DEGREE SIGN}"

Expand Down

0 comments on commit 1d82436

Please sign in to comment.