Skip to content

Commit

Permalink
Merge branch 'TimeToSoc' into python3-startup-issues
Browse files Browse the repository at this point in the history
  • Loading branch information
Louisvdw committed Mar 3, 2022
2 parents 58dbfa0 + 01ecc0f commit b3fc6f2
Show file tree
Hide file tree
Showing 4 changed files with 101 additions and 47 deletions.
43 changes: 25 additions & 18 deletions etc/dbus-serialbattery/battery.py
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,8 @@ def __init__(self, port, baud):
# max battery charge/discharge current
self.max_battery_current = None
self.max_battery_discharge_current = None

self.time_to_soc_update = TIME_TO_SOC_LOOP_CYCLES

def test_connection(self):
# Each driver must override this function to test if a connection can be made
Expand Down Expand Up @@ -173,24 +175,29 @@ def get_cell_balancing(self, idx):
return 1
return 0

def get_timetosoc(self, socnum):
# Update TimeToSoC items
if self.battery.capacity is None or not self.battery.current:
return None

# check if we are past socNum when charging
# or discharging
# or on the same SOC (using 0.5% tolerance)
if (self.battery.current > 0 and self.battery.soc > socnum) or \
(self.battery.current < 0 and self.battery.soc < socnum) or \
(self.battery.soc - socnum < 0.5):
return "00:00:00"

# Get Seconds to reach goal Soc using current flow
crntPrctPerSec = (abs(self.battery.current / (self.battery.capacity / 100)) / 3600)
secondstogo = int(abs(socnum - self.battery.soc) / crntPrctPerSec)

return str(timedelta(seconds=secondstogo))

def get_timetosoc(self, socnum, crntPrctPerSec):
if self.current > 0:
diffSoc = (socnum - self.soc)
else:
diffSoc = (self.soc - socnum)

ttgStr = None
if self.soc != socnum and (diffSoc > 0 or TIME_TO_SOC_INC_FROM is True):
secondstogo = int(diffSoc / crntPrctPerSec)
ttgStr = ""

if (TIME_TO_SOC_VALUE_TYPE & 1):
ttgStr += str(secondstogo)
if (TIME_TO_SOC_VALUE_TYPE & 2):
ttgStr += " ["
if (TIME_TO_SOC_VALUE_TYPE & 2):
ttgStr += str(timedelta(seconds=secondstogo))
if (TIME_TO_SOC_VALUE_TYPE & 1):
ttgStr += "]"

return ttgStr


def get_min_cell_voltage(self):
min_voltage = None
Expand Down
23 changes: 17 additions & 6 deletions etc/dbus-serialbattery/daly.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@ def __init__(self, port,baud,address):
self.cell_max_voltage = None
self.cell_min_no = None
self.cell_max_no = None
self.poll_interval = 2000
self.poll_interval = 1000
self.poll_step = 0
self.type = self.BATTERYTYPE
# command bytes [StartFlag=A5][Address=40][Command=94][DataLength=8][8x zero bytes][checksum]
command_base = b"\xA5\x40\x94\x08\x00\x00\x00\x00\x00\x00\x00\x00\x81"
Expand Down Expand Up @@ -46,11 +47,21 @@ def get_settings(self):

def refresh_data(self):
result = self.read_soc_data()
result = result and self.read_alarm_data()
result = result and self.read_cells_volts()
result = result and self.read_cell_voltage_range_data()
result = result and self.read_temperature_range_data()
result = result and self.read_fed_data()
if self.poll_step == 0:
# This must be listed in step 0 as get_min_cell_voltage and get_max_cell_voltage in battery.py needs it at first cycle for publish_dbus in dbushelper.py
result = result and self.read_cell_voltage_range_data()
elif self.poll_step == 1:
result = result and self.read_alarm_data()
elif self.poll_step == 2:
result = result and self.read_cells_volts()
elif self.poll_step == 3:
result = result and self.read_temperature_range_data()
#else: # A placeholder to remind this is the last step. Add any additional steps before here
# This is last step so reset poll_step
self.poll_step = -1

self.poll_step += 1

return result

Expand Down Expand Up @@ -223,7 +234,7 @@ def read_cells_volts(self):
frame = 0
while frame >= 0 and frame < maxFrame and cellnum < self.cell_count:
startPos = ((frame * 12) + 4)
logger.warning('cell: ' + str(cellnum) + ', startPos: ' + str(startPos) + ', frame: ' + str(frame))
#logger.warning('cell: ' + str(cellnum) + ', startPos: ' + str(startPos) + ', frame: ' + str(frame))
if frame > 0 and frame < 16:
startPos += 1
frame, frameCell[0], frameCell[1], frameCell[2], reserved = unpack_from('>bhhhb', cells_volts_data, startPos)
Expand Down
58 changes: 35 additions & 23 deletions etc/dbus-serialbattery/dbushelper.py
100755 → 100644
Original file line number Diff line number Diff line change
Expand Up @@ -136,15 +136,19 @@ def setup_vedbus(self):
self._dbusservice.add_path('/Alarms/HighTemperature', None, writeable=True)
self._dbusservice.add_path('/Alarms/LowTemperature', None, writeable=True)

#cell voltages - begining
for i in range(self.battery.cell_count):
self._dbusservice.add_path('/Voltages/Cell%s'%(str(i+1)), None, writeable=True, gettextcallback=lambda p, v: "{:0.3f}V".format(v))
self._dbusservice.add_path('/Balances/Cell%s'%(str(i+1)), None, writeable=True)
self._dbusservice.add_path('/Voltages/Sum', None, writeable=True, gettextcallback=lambda p, v: "{:2.2f}V".format(v))
self._dbusservice.add_path('/Voltages/Diff', None, writeable=True, gettextcallback=lambda p, v: "{:0.3f}V".format(v))
#cell voltages
if (BATTERY_CELL_DATA_FORMAT>0):
for i in range(1, self.battery.cell_count+1):
cellpath = '/Cell/%s/Volts' if (BATTERY_CELL_DATA_FORMAT & 2) else '/Voltages/Cell%s'
self._dbusservice.add_path(cellpath%(str(i)), None, writeable=True, gettextcallback=lambda p, v: "{:0.3f}V".format(v))
if (BATTERY_CELL_DATA_FORMAT & 1):
self._dbusservice.add_path('/Balances/Cell%s'%(str(i)), None, writeable=True)
pathbase = 'Cell' if (BATTERY_CELL_DATA_FORMAT & 2) else 'Voltages'
self._dbusservice.add_path('/%s/Sum'%pathbase, None, writeable=True, gettextcallback=lambda p, v: "{:2.2f}V".format(v))
self._dbusservice.add_path('/%s/Diff'%pathbase, None, writeable=True, gettextcallback=lambda p, v: "{:0.3f}V".format(v))

# Create TimeToSoC items
for num in [100, 95, 90, 85, 80, 75, 70, 65, 60, 55, 50, 45, 40, 35, 30, 25, 20, 15, 10, 5, 0]:
for num in TIME_TO_SOC_POINTS:
self._dbusservice.add_path('/TimeToSoC/' + str(num), None, writeable=True)

return True
Expand All @@ -164,9 +168,6 @@ def publish_battery(self, loop):
if error_count >= 10:
self.battery.online = False




# This is to mannage CCCL
self.battery.manage_charge_current()

Expand Down Expand Up @@ -236,20 +237,31 @@ def publish_dbus(self):
self._dbusservice['/Alarms/HighTemperature'] = self.battery.protection.temp_high_discharge
self._dbusservice['/Alarms/LowTemperature'] = self.battery.protection.temp_low_discharge

#cell voltages - begining
voltageSum = 0
for i in range(self.battery.cell_count):
voltage = self.battery.get_cell_voltage(i)
self._dbusservice['/Voltages/Cell%s'%(str(i+1))] = voltage
self._dbusservice['/Balances/Cell%s'%(str(i+1))] = self.battery.get_cell_balancing(i)
if voltage:
voltageSum+=voltage
self._dbusservice['/Voltages/Sum'] = voltageSum
self._dbusservice['/Voltages/Diff'] = self.battery.get_max_cell_voltage() - self.battery.get_min_cell_voltage()
#cell voltages
if (BATTERY_CELL_DATA_FORMAT>0):
voltageSum = 0
for i in range(self.battery.cell_count):
voltage = self.battery.get_cell_voltage(i)
cellpath = '/Cell/%s/Volts' if (BATTERY_CELL_DATA_FORMAT & 2) else '/Voltages/Cell%s'
self._dbusservice[cellpath%(str(i+1))] = voltage
if (BATTERY_CELL_DATA_FORMAT & 1):
self._dbusservice['/Balances/Cell%s'%(str(i+1))] = self.battery.get_cell_balancing(i)
if voltage:
voltageSum+=voltage
pathbase = 'Cell' if (BATTERY_CELL_DATA_FORMAT & 2) else 'Voltages'
self._dbusservice['/%s/Sum'%pathbase] = voltageSum
self._dbusservice['/%s/Diff'%pathbase] = self.battery.get_max_cell_voltage() - self.battery.get_min_cell_voltage()

# Update TimeToSoC
# for num in [100, 95, 90, 85, 80, 75, 70, 65, 60, 55, 50, 45, 40, 35, 30, 25, 20, 15, 10, 5, 0]:
# self._dbusservice['/TimeToSoC/' + str(num)] = self.battery.get_timetosoc(num)

if self.battery.capacity is not None and len(TIME_TO_SOC_POINTS) > 0 and self.battery.time_to_soc_update == 0:
self.battery.time_to_soc_update = TIME_TO_SOC_LOOP_CYCLES
crntPrctPerSec = (abs(self.battery.current / (self.battery.capacity / 100)) / 3600)

for num in TIME_TO_SOC_POINTS:
self._dbusservice['/TimeToSoC/' + str(num)] = self.battery.get_timetosoc(num, crntPrctPerSec) if self.battery.current else None

else:
self.battery.time_to_soc_update -= 1

logger.debug("logged to dbus [%s]"%str(round(self.battery.soc, 2)))
self.battery.log_cell_data()
24 changes: 24 additions & 0 deletions etc/dbus-serialbattery/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,30 @@
# Invert Battery Current. Default non-inverted. Set to -1 to invert
INVERT_CURRENT_MEASUREMENT = 1

# TIME TO SOC settings [Valid values 0-100, but I don't recommend more that 20 intervals]
# Set of SoC percentages to report on dbus. The more you specify the more it will impact system performance.
# TIME_TO_SOC_POINTS = [100, 95, 90, 85, 80, 75, 70, 65, 60, 55, 50, 45, 40, 35, 30, 25, 20, 15, 10, 5, 0] # Every 5% SoC
# TIME_TO_SOC_POINTS = [100, 95, 90, 85, 75, 50, 25, 20, 10, 0]
TIME_TO_SOC_POINTS = [] # No data set to disable
# Specify TimeToSoc value type: [Valid values 1,2,3]
# TIME_TO_SOC_VALUE_TYPE = 1 # Seconds
# TIME_TO_SOC_VALUE_TYPE = 2 # Time string HH:MN:SC
TIME_TO_SOC_VALUE_TYPE = 3 # Both Seconds and time str "<seconds> [days, HR:MN:SC]"
# Specify how many loop cycles between each TimeToSoc updates
TIME_TO_SOC_LOOP_CYCLES = 5
# Include TimeToSoC points when moving away from the SoC point. [Valid values True,False]
# These will be as negative time. Disabling this improves performance slightly.
TIME_TO_SOC_INC_FROM = False


# Select the format of cell data presented on dbus. [Valid values 0,1,2,3]
# 0 Do not publish all the cells (only the min/max cell data as used by the default GX)
# 1 Format: /Voltages/Cell# (also available for display on Remote Console)
# 2 Format: /Cell/#/Volts
# 3 Both formats 1 and 2
BATTERY_CELL_DATA_FORMAT = 1


def is_bit_set(tmp):
return False if tmp == zero_char else True

Expand Down

0 comments on commit b3fc6f2

Please sign in to comment.