Skip to content

Commit

Permalink
Copy of Battery Template for Seplos V3
Browse files Browse the repository at this point in the history
  • Loading branch information
wollew committed Mar 8, 2024
1 parent ac892a1 commit 295dda9
Showing 1 changed file with 131 additions and 0 deletions.
131 changes: 131 additions & 0 deletions etc/dbus-serialbattery/bms/seplos_v3.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
# -*- coding: utf-8 -*-

# NOTES
# Please see "Add/Request a new BMS" https://louisvdw.github.io/dbus-serialbattery/general/supported-bms#add-by-opening-a-pull-request
# in the documentation for a checklist what you have to do, when adding a new BMS

# avoid importing wildcards
from battery import Protection, Battery, Cell
from utils import is_bit_set, read_serial_data, logger
import utils
from struct import unpack_from
import sys


class SeplosV3(Battery):
def __init__(self, port, baud, address):
super(SeplosV3, self).__init__(port, baud, address)
self.type = self.BATTERYTYPE

BATTERYTYPE = "SeplosV3"

def test_connection(self):
# call a function that will connect to the battery, send a command and retrieve the result.
# The result or call should be unique to this BMS. Battery name or version, etc.
# Return True if success, False for failure
result = False
try:
result = self.read_status_data()
# get first data to show in startup log, only if result is true
result = result and self.refresh_data()
except Exception:
(
exception_type,
exception_object,
exception_traceback,
) = sys.exc_info()
file = exception_traceback.tb_frame.f_code.co_filename
line = exception_traceback.tb_lineno
logger.error(
f"Exception occurred: {repr(exception_object)} of type {exception_type} in {file} line #{line}"
)
result = False

return result

def unique_identifier(self) -> str:
"""
Used to identify a BMS when multiple BMS are connected
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 remove this function
"""
return self.serialnumber

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.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

return True

def refresh_data(self):
# call all functions that will refresh the battery data.
# This will be called for every iteration (1 second)
# Return True if success, False for failure
result = self.read_soc_data()

return result

def read_status_data(self):
status_data = self.read_serial_data_template(self.command_status)
# check if connection success
if status_data is False:
return False

(
self.cell_count,
self.temp_sensors,
self.charger_connected,
self.load_connected,
state,
self.cycles,
) = unpack_from(">bb??bhx", status_data)

# Integrate a check to be sure, that the received data is from the BMS type you are making this driver for

self.hardware_version = "TemplateBMS " + str(self.cell_count) + " cells"
logger.info(self.hardware_version)
return True

def read_soc_data(self):
soc_data = self.read_serial_data_template(self.command_soc)
# check if connection success
if soc_data is False:
return False

voltage, current, soc = unpack_from(">hxxhh", soc_data)
self.voltage = voltage / 10
self.current = current / -10
self.soc = soc / 10
return True

def read_serial_data_template(self, command):
# use the read_serial_data() function to read the data and then do BMS spesific checks (crc, start bytes, etc)
data = read_serial_data(
command, self.port, self.baud_rate, self.LENGTH_POS, self.LENGTH_CHECK
)
if data is False:
logger.error(">>> ERROR: No reply - returning")
return False

start, flag, command_ret, length = unpack_from("BBBB", data)
checksum = sum(data[:-1]) & 0xFF

if start == 165 and length == 8 and checksum == data[12]:
return data[4 : length + 4]
else:
logger.error(">>> ERROR: Incorrect Reply")
return False

0 comments on commit 295dda9

Please sign in to comment.