Skip to content

Commit

Permalink
TEST for controller optimizations, commit will be reverted later
Browse files Browse the repository at this point in the history
Added PID-Controller
  • Loading branch information
mr-manuel committed Jan 7, 2025
1 parent 941dd7c commit 78d567f
Show file tree
Hide file tree
Showing 9 changed files with 398 additions and 22 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
* Changes to `config.default.ini`: `CELL_VOLTAGE_DIFF_KEEP_MAX_VOLTAGE_TIME_RESTART` was superseeded by `SWITCH_TO_FLOAT_CELL_VOLTAGE_DEVIATION`, which has a different behavior
* Changes to `config.default.ini`: `CELL_VOLTAGE_DIFF_KEEP_MAX_VOLTAGE_UNTIL` was replaced by `SWITCH_TO_FLOAT_CELL_VOLTAGE_DIFF`
* Changes to `config.default.ini`: `CELL_VOLTAGE_DIFF_TO_RESET_VOLTAGE_LIMIT` was replaced by `SWITCH_TO_BULK_CELL_VOLTAGE_DIFF`
* Changes to `config.default.ini`: `CVL_ICONTROLLER_FACTOR` was replaced by `CVL_CONTROLLER_KI`
* Changes to `config.default.ini`: `CVL_ICONTROLLER_MODE` was superseeded by `CVL_CONTROLLER_MODE`, which has a different behavior
* Changes to `config.default.ini`: `LINEAR_LIMITATION_ENABLE` was superseeded by `CHARGE_MODE`, which has a different behavior
* Changes to `config.default.ini`: `LINEAR_RECALCULATION_EVERY` was replaced by `CVL_RECALCULATION_EVERY`
Expand Down Expand Up @@ -52,9 +53,11 @@
* Added: Felicity BMS by @versager
* Added: JKBMS CAN - Extended protocol with version V2 by @Hooorny and @mr-manuel
* Added: LiTime BMS by @calledit
* Added: D-Controller for managing CVL on high cell voltage by @mr-manuel
* Added: Make battery data available on MQTT under a single topic by enabling `PUBLISH_BATTERY_DATA_AS_JSON` by @mr-manuel
* Added: Min/Max lifetime temperature to history class and battery template by @mr-manuel
* Added: Pace BMS by @KoljaWindeler
* Added: PID-Controller for managing CVL on high cell voltage by @mr-manuel
* Added: Possibility to add external sensor for SoC by @mr-manuel
* Added: Signal handler for clean service restart/shutdown by @mr-manuel
* Changed: A lot of under the hood optimizations by @mr-manuel
Expand All @@ -77,6 +80,7 @@
* Changed: The setting `CELL_VOLTAGE_DIFF_KEEP_MAX_VOLTAGE_TIME_RESTART` was superseeded by `SWITCH_TO_FLOAT_CELL_VOLTAGE_DEVIATION`, which has a different behavior by @mr-manuel
* Changed: The setting `CELL_VOLTAGE_DIFF_KEEP_MAX_VOLTAGE_UNTIL` was replaced by `SWITCH_TO_FLOAT_CELL_VOLTAGE_DIFF` by @mr-manuel
* Changed: The setting `CELL_VOLTAGE_DIFF_TO_RESET_VOLTAGE_LIMIT` was replaced by `SWITCH_TO_BULK_CELL_VOLTAGE_DIFF` by @mr-manuel
* Changed: The setting `CVL_ICONTROLLER_FACTOR` was replaced by `CVL_CONTROLLER_KI` in the `config.default.ini` by @mr-manuel
* Changed: The setting `CVL_ICONTROLLER_MODE` was superseeded by `CVL_CONTROLLER_MODE`, which has a different behavior by @mr-manuel
* Changed: The setting `EXTERNAL_CURRENT_SENSOR_DBUS_DEVICE` was replaced by `EXTERNAL_SENSOR_DBUS_DEVICE` in the `config.default.ini` by @mr-manuel
* Changed: The setting `EXTERNAL_CURRENT_SENSOR_DBUS_PATH` was replaced by `EXTERNAL_SENSOR_DBUS_PATH_CURRENT` in the `config.default.ini` by @mr-manuel
Expand Down
79 changes: 61 additions & 18 deletions dbus-serialbattery/battery.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@
from abc import ABC, abstractmethod
import sys

if utils.CHARGE_MODE == 4:
from simple_pid import PID


class Protection(object):
"""
Expand Down Expand Up @@ -664,6 +667,7 @@ def manage_charge_voltage_limit(self) -> None:
time_diff = 0
control_voltage = 0
current_time = int(time())
debug = None

try:
voltage_sum = self.get_cell_voltage_sum()
Expand Down Expand Up @@ -748,51 +752,89 @@ def manage_charge_voltage_limit(self) -> None:

if found_high_cell_voltage:
# reduce voltage by penalty sum
# keep penalty above min battery voltage and below max battery voltage
control_voltage = min(
max(
voltage_sum - penalty_sum,
self.min_battery_voltage,
),
self.max_battery_voltage,
)
control_voltage_1 = voltage_sum - (penalty_sum * utils.CVL_CONTROLLER_KP) # ORIGINAL
control_voltage_2 = self.max_battery_voltage - (penalty_sum * utils.CVL_CONTROLLER_KP)
debug = f"cvl_1: {control_voltage_1:.2f} V • cvl_2: {control_voltage_2:.2f} V"
control_voltage = control_voltage_1
else:
control_voltage = self.max_battery_voltage

# use I-Controller
# use I-Controller (is the current code really an I-Controller?)
elif utils.CVL_CONTROLLER_MODE == 2:
if self.control_voltage:
control_voltage = self.control_voltage - (
(self.get_max_cell_voltage() - cell_voltage_max_allowed - utils.SWITCH_TO_FLOAT_CELL_VOLTAGE_DIFF) * utils.CVL_ICONTROLLER_FACTOR
(self.get_max_cell_voltage() - cell_voltage_max_allowed - utils.SWITCH_TO_FLOAT_CELL_VOLTAGE_DIFF) * utils.CVL_CONTROLLER_KI
)
else:
control_voltage = self.max_battery_voltage

control_voltage = min(
max(control_voltage, self.min_battery_voltage),
self.max_battery_voltage,
)
"""
# New untested I-Controller from GitHub Copilot
# Initialize integral term
self.integral_term = 0
if self.control_voltage:
# Calculate the error
error = self.get_max_cell_voltage() - cell_voltage_max_allowed - utils.SWITCH_TO_FLOAT_CELL_VOLTAGE_DIFF
# Accumulate the error to the integral term
self.integral_term += error
# Adjust the control voltage using the integral term
control_voltage = self.control_voltage - (self.integral_term * utils.CVL_CONTROLLER_KI)
else:
control_voltage = self.max_battery_voltage
"""

# use D-Controller (untested)
elif utils.CVL_CONTROLLER_MODE == 3:
if not hasattr(self, "previous_error"):
self.previous_error = 0

# Calculate the error
error = self.get_max_cell_voltage() - cell_voltage_max_allowed

# Calculate the derivative of the error
derivative = error - self.previous_error

# Adjust the control voltage using the derivative term
control_voltage = self.control_voltage - (derivative * utils.CVL_CONTROLLER_KD)

# Update previous error
self.previous_error = error

# use PID-Controller (untested)
elif utils.CVL_CONTROLLER_MODE == 4:
pid_controller = PID(Kp=utils.CVL_CONTROLLER_KP, Ki=utils.CVL_CONTROLLER_KI, Kd=utils.CVL_CONTROLLER_KD, setpoint=self.max_battery_voltage)
control_voltage = pid_controller(voltage_sum)

# use no controller
else:
control_voltage = self.max_battery_voltage

# set control voltage
# keep control voltage above min battery voltage and below max battery voltage
# 6 decimals are needed for a proper controller working
# https://github.com/Louisvdw/dbus-serialbattery/issues/1041
self.control_voltage = round(control_voltage, 6)
self.control_voltage = round(
min(
max(control_voltage, self.min_battery_voltage),
self.max_battery_voltage,
),
6,
)

self.charge_mode = "Bulk" if self.max_voltage_start_time is None else "Absorption"

# If control voltage is not equal to max battery voltage, then a high cell voltage was detected
if control_voltage != self.max_battery_voltage:
self.charge_mode += " (Cell OVP)" # Cell over voltage protection
self.charge_mode += ", Cell OVP " # Cell over voltage protection

if self.max_battery_voltage == self.soc_reset_battery_voltage:
self.charge_mode += " & SoC Reset"
self.charge_mode += ", SoC Reset"

if self.get_balancing() and voltage_cell_diff >= utils.SWITCH_TO_BULK_CELL_VOLTAGE_DIFF:
self.charge_mode += " + Balancing"
self.charge_mode += ", Balancing"

# Float mode
else:
Expand Down Expand Up @@ -860,6 +902,7 @@ def manage_charge_voltage_limit(self) -> None:

self.charge_mode_debug = (
f"driver started: {formatted_time} • running since: {self.get_seconds_to_string(int(time()) - self.driver_start_time)}\n"
+ (f"{debug}\n" if debug else "")
+ f"max_battery_voltage: {(self.max_battery_voltage):.2f} V • "
+ f"control_voltage: {self.control_voltage:.2f} V\n"
+ f"voltage: {self.voltage:.2f} V • "
Expand Down
12 changes: 9 additions & 3 deletions dbus-serialbattery/config.default.ini
Original file line number Diff line number Diff line change
Expand Up @@ -302,9 +302,15 @@ SWITCH_TO_BULK_CELL_VOLTAGE_DIFF = 0.080
; 0: Disabled
; 1: P-Controller (penalty sum method)
; 2: I-Controller
CVL_CONTROLLER_MODE = 0
; I-Controller factor (V/Vs)
CVL_ICONTROLLER_FACTOR = 0.2
; 3: D-Controller (untested)
; 4: PID-Controller (untested)
CVL_CONTROLLER_MODE = 1
; Proportional component (Kp)
CVL_CONTROLLER_KP = 1.0
; Integral component (Ki)
CVL_CONTROLLER_KI = 0.2
; Derivative component (Kd)
CVL_CONTROLLER_KD = 0.1


; --------- Cell Voltage Current Limitation (affecting CCL/DCL) ---------
Expand Down
1 change: 1 addition & 0 deletions dbus-serialbattery/ext/simple_pid/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
from simple_pid.pid import PID as PID
Loading

0 comments on commit 78d567f

Please sign in to comment.