Check temperature & voltage

This commit is contained in:
Jasper Blanckenburg 2023-01-26 13:58:18 +01:00
parent 7bcafa2c4d
commit a91f9d70db
5 changed files with 101 additions and 7 deletions

View File

@ -1,7 +1,9 @@
from abc import abstractmethod from abc import abstractmethod
import time import time
from dataclasses import dataclass from dataclasses import dataclass
from enum import Enum
from .load import Load
from .temperatures import N_SENSORS from .temperatures import N_SENSORS
from PySide6.QtCore import QObject, Signal, Slot, Qt from PySide6.QtCore import QObject, Signal, Slot, Qt
@ -15,16 +17,79 @@ SLAVE_UNIT_ID = 0x02
NUM_CELLS = 3 NUM_CELLS = 3
VOLTAGE_QUANT = 1 / 10000.0 VOLTAGE_QUANT = 1 / 10000.0
THRESH_UV = 2.5
THRESH_OV = 4.2
THRESH_UT = 1
THRESH_OT = 60
class BMSError(Enum):
NONE = 0
UV = 1
OV = 2
UT = 3
OT = 4
def __str__(self):
if self == self.NONE:
return ""
elif self == self.UV:
return "Undervoltage"
elif self == self.OV:
return "Overvoltage"
elif self == self.UT:
return "Undertemperature"
elif self == self.OT:
return "Overtemperature"
else:
return "Unknown error"
@dataclass @dataclass
class BMSData: class BMSData:
voltages: list[float] voltages: list[float]
temperatures: list[float] temperatures: list[float]
error: BMSError
class BMS(QObject): class BMS(QObject):
dataUpdated = Signal(BMSData) dataUpdated = Signal(BMSData)
_data: BMSData
_load: Load
_num_cells: int
_num_sensors: int
def __init__(self, load: Load, num_cells: int, num_sensors: int):
super().__init__(None)
self._load = load
self._num_cells = num_cells
self._num_sensors = num_sensors
self._data = BMSData([0.0] * num_cells, [0.0] * num_sensors, BMSError.NONE)
def _check_for_errors(self):
error = BMSError.NONE
for v in self._data.voltages:
if v > THRESH_OV:
error = BMSError.OV
break
elif v < THRESH_UV:
error = BMSError.UV
break
for t in self._data.temperatures:
if t > THRESH_OT:
error = BMSError.OT
break
if t < THRESH_UT:
error = BMSError.UT
break
if error != self._data.error:
print(f"Error changed: {error}")
self._data.error = error
self._load.set_error(error != BMSError.NONE)
self.dataUpdated.emit(self._data)
@abstractmethod @abstractmethod
def do_work(self): def do_work(self):
pass pass
@ -32,14 +97,12 @@ class BMS(QObject):
class BMSEvalBoard(BMS): class BMSEvalBoard(BMS):
_dev: ModbusSerialClient _dev: ModbusSerialClient
_data: BMSData
def __init__(self, uart_path: str, temperaturesUpdated: Signal): def __init__(self, uart_path: str, temperaturesUpdated: Signal, load: Load):
super().__init__(None) super().__init__(load, NUM_CELLS, N_SENSORS)
self._dev = ModbusSerialClient( self._dev = ModbusSerialClient(
method="rtu", port=uart_path, baudrate=MODBUS_BAUDRATE method="rtu", port=uart_path, baudrate=MODBUS_BAUDRATE
) )
self._data = BMSData([0.0] * NUM_CELLS, [0.0] * N_SENSORS)
temperaturesUpdated.connect( temperaturesUpdated.connect(
self._updateTemperatures, Qt.ConnectionType.DirectConnection self._updateTemperatures, Qt.ConnectionType.DirectConnection
) )
@ -53,10 +116,12 @@ class BMSEvalBoard(BMS):
self._data.voltages = list( self._data.voltages = list(
map(lambda v: v * VOLTAGE_QUANT, result.registers) map(lambda v: v * VOLTAGE_QUANT, result.registers)
) )
self._check_for_errors()
self.dataUpdated.emit(self._data) self.dataUpdated.emit(self._data)
@Slot(list) @Slot(list)
def _updateTemperatures(self, temps: list[float]): def _updateTemperatures(self, temps: list[float]):
assert len(temps) == N_SENSORS assert len(temps) == N_SENSORS
self._data.temperatures = temps self._data.temperatures = temps
self._check_for_errors()
self.dataUpdated.emit(self._data) self.dataUpdated.emit(self._data)

View File

@ -88,3 +88,4 @@ class GUI(QObject):
self._win.setProperty("voltage_max", max(data.voltages)) self._win.setProperty("voltage_max", max(data.voltages))
self._win.setProperty("temp_min", min(data.temperatures)) self._win.setProperty("temp_min", min(data.temperatures))
self._win.setProperty("temp_max", max(data.temperatures)) self._win.setProperty("temp_max", max(data.temperatures))
self._win.setProperty("bmsError", str(data.error))

View File

@ -9,6 +9,7 @@ from .profile_handler import ProfileHandler
class Load(QObject): class Load(QObject):
dev: serial.Serial dev: serial.Serial
_error: bool
_current: float _current: float
_timer: QTimer _timer: QTimer
@ -17,6 +18,7 @@ class Load(QObject):
def __init__(self, uart_path: str, profile_handler: ProfileHandler): def __init__(self, uart_path: str, profile_handler: ProfileHandler):
super().__init__(None) super().__init__(None)
self.dev = serial.Serial(uart_path, 115200) self.dev = serial.Serial(uart_path, 115200)
self._error = False
self._current = 0 self._current = 0
self._profile_handler = profile_handler self._profile_handler = profile_handler
@ -25,12 +27,16 @@ class Load(QObject):
self._timer.timeout.connect(self._update_load) self._timer.timeout.connect(self._update_load)
self._timer.start(100) self._timer.start(100)
def set_error(self, error):
self._error = error
@Slot() @Slot()
def _update_current(self, current): def _update_current(self, current):
self._current = current self._current = current
def _update_load(self): def _update_load(self):
curr_quants = round(self._current / 0.1) current = 0 if self._error else self._current
curr_quants = round(current / 0.1)
assert curr_quants <= 0xFFFF assert curr_quants <= 0xFFFF
msb = curr_quants >> 8 msb = curr_quants >> 8

View File

@ -23,7 +23,7 @@ def main(argv: list[str]) -> int:
temps.moveToThread(temp_thread) temps.moveToThread(temp_thread)
temp_thread.started.connect(temps.run) temp_thread.started.connect(temps.run)
temp_thread.start() temp_thread.start()
bms = BMSEvalBoard(argv[3], temps.temperaturesUpdated) bms = BMSEvalBoard(argv[3], temps.temperaturesUpdated, load)
bms_thread = QThread() bms_thread = QThread()
bms.moveToThread(bms_thread) bms.moveToThread(bms_thread)
bms_thread.started.connect(bms.do_work) bms_thread.started.connect(bms.do_work)

View File

@ -18,12 +18,13 @@ ApplicationWindow {
property real voltage_max: 0 property real voltage_max: 0
property real temp_min: 0 property real temp_min: 0
property real temp_max: 0 property real temp_max: 0
property string bmsError: ""
property bool bmsErrorVisible: false
Connections { Connections {
target: profile_handler target: profile_handler
function onCurrentChanged(new_current) { function onCurrentChanged(new_current) {
console.log("currentChanged");
current = new_current; current = new_current;
} }
@ -45,6 +46,11 @@ ApplicationWindow {
currentTimeSeries.append(profileTime, 100) currentTimeSeries.append(profileTime, 100)
} }
onBmsErrorChanged: {
console.log(bmsError);
bmsErrorVisible = bmsError != "";
}
RowLayout { RowLayout {
id: layout id: layout
anchors.fill: parent anchors.fill: parent
@ -151,6 +157,22 @@ ApplicationWindow {
Layout.row: 3 Layout.row: 3
Layout.column: 1 Layout.column: 1
} }
Text {
text: "BMS Error:"
Layout.row: 4
Layout.column: 0
visible: bmsErrorVisible
color: "red"
font.bold: true
}
Text {
text: bmsError
Layout.row: 4
Layout.column: 1
visible: bmsErrorVisible
color: "red"
font.bold: true
}
} }
} }