Talk to EET BMS eval board
This commit is contained in:
parent
1020d8731e
commit
7bcafa2c4d
62
load_controller/bms.py
Normal file
62
load_controller/bms.py
Normal file
@ -0,0 +1,62 @@
|
||||
from abc import abstractmethod
|
||||
import time
|
||||
from dataclasses import dataclass
|
||||
|
||||
from .temperatures import N_SENSORS
|
||||
|
||||
from PySide6.QtCore import QObject, Signal, Slot, Qt
|
||||
|
||||
from pymodbus.client import ModbusSerialClient
|
||||
|
||||
MODBUS_BAUDRATE = 115200
|
||||
VOLTAGE_ADDRESS = 0x00
|
||||
SLAVE_UNIT_ID = 0x02
|
||||
|
||||
NUM_CELLS = 3
|
||||
VOLTAGE_QUANT = 1 / 10000.0
|
||||
|
||||
|
||||
@dataclass
|
||||
class BMSData:
|
||||
voltages: list[float]
|
||||
temperatures: list[float]
|
||||
|
||||
|
||||
class BMS(QObject):
|
||||
dataUpdated = Signal(BMSData)
|
||||
|
||||
@abstractmethod
|
||||
def do_work(self):
|
||||
pass
|
||||
|
||||
|
||||
class BMSEvalBoard(BMS):
|
||||
_dev: ModbusSerialClient
|
||||
_data: BMSData
|
||||
|
||||
def __init__(self, uart_path: str, temperaturesUpdated: Signal):
|
||||
super().__init__(None)
|
||||
self._dev = ModbusSerialClient(
|
||||
method="rtu", port=uart_path, baudrate=MODBUS_BAUDRATE
|
||||
)
|
||||
self._data = BMSData([0.0] * NUM_CELLS, [0.0] * N_SENSORS)
|
||||
temperaturesUpdated.connect(
|
||||
self._updateTemperatures, Qt.ConnectionType.DirectConnection
|
||||
)
|
||||
|
||||
def do_work(self):
|
||||
while True:
|
||||
time.sleep(0.1)
|
||||
result = self._dev.read_holding_registers(
|
||||
VOLTAGE_ADDRESS, NUM_CELLS, SLAVE_UNIT_ID
|
||||
)
|
||||
self._data.voltages = list(
|
||||
map(lambda v: v * VOLTAGE_QUANT, result.registers)
|
||||
)
|
||||
self.dataUpdated.emit(self._data)
|
||||
|
||||
@Slot(list)
|
||||
def _updateTemperatures(self, temps: list[float]):
|
||||
assert len(temps) == N_SENSORS
|
||||
self._data.temperatures = temps
|
||||
self.dataUpdated.emit(self._data)
|
@ -5,6 +5,7 @@ from PySide6.QtCore import QTimer, QObject, Signal
|
||||
from PySide6.QtWidgets import QFileDialog
|
||||
from PySide6.QtQml import QQmlApplicationEngine
|
||||
|
||||
from .bms import BMSData
|
||||
from .profile_handler import ProfileHandler, ProfileState
|
||||
|
||||
|
||||
@ -17,7 +18,7 @@ class GUI(QObject):
|
||||
_start_pause_btn: QObject
|
||||
_stop_btn: QObject
|
||||
|
||||
def __init__(self, profile_handler: ProfileHandler, temperaturesUpdated: Signal):
|
||||
def __init__(self, profile_handler: ProfileHandler, bmsUpdated: Signal):
|
||||
super().__init__(None)
|
||||
|
||||
self._engine = QQmlApplicationEngine()
|
||||
@ -42,7 +43,7 @@ class GUI(QObject):
|
||||
self._update_timer.timeout.connect(self._update)
|
||||
self._update_timer.start(100)
|
||||
|
||||
temperaturesUpdated.connect(self._updateTemperatures)
|
||||
bmsUpdated.connect(self._updateBMS)
|
||||
|
||||
def _choose_profile(self):
|
||||
dlg = QFileDialog()
|
||||
@ -82,6 +83,8 @@ class GUI(QObject):
|
||||
dt = time.time() - self._profile_handler.profile_start
|
||||
self._win.setProperty("profileTime", dt)
|
||||
|
||||
def _updateTemperatures(self, temperatures: list[int]):
|
||||
self._win.setProperty("temp_min", min(temperatures))
|
||||
self._win.setProperty("temp_max", max(temperatures))
|
||||
def _updateBMS(self, data: BMSData):
|
||||
self._win.setProperty("voltage_min", min(data.voltages))
|
||||
self._win.setProperty("voltage_max", max(data.voltages))
|
||||
self._win.setProperty("temp_min", min(data.temperatures))
|
||||
self._win.setProperty("temp_max", max(data.temperatures))
|
||||
|
@ -1,6 +1,7 @@
|
||||
import sys
|
||||
import serial
|
||||
import struct
|
||||
import time
|
||||
|
||||
from PySide6.QtCore import QObject, Signal
|
||||
|
||||
@ -21,6 +22,7 @@ class Temperatures(QObject):
|
||||
|
||||
def run(self):
|
||||
while True:
|
||||
time.sleep(0.1)
|
||||
self.dev.read_until(START_OF_TEMPS)
|
||||
data = self.dev.read(N_SENSORS * 2)
|
||||
temps = struct.unpack(f">{N_SENSORS}h", data)
|
||||
|
8
main.py
8
main.py
@ -10,6 +10,7 @@ from load_controller.gui import GUI
|
||||
from load_controller.load import Load
|
||||
from load_controller.profile_handler import ProfileHandler
|
||||
from load_controller.temperatures import Temperatures
|
||||
from load_controller.bms import BMSEvalBoard
|
||||
|
||||
|
||||
def main(argv: list[str]) -> int:
|
||||
@ -22,8 +23,13 @@ def main(argv: list[str]) -> int:
|
||||
temps.moveToThread(temp_thread)
|
||||
temp_thread.started.connect(temps.run)
|
||||
temp_thread.start()
|
||||
bms = BMSEvalBoard(argv[3], temps.temperaturesUpdated)
|
||||
bms_thread = QThread()
|
||||
bms.moveToThread(bms_thread)
|
||||
bms_thread.started.connect(bms.do_work)
|
||||
bms_thread.start()
|
||||
|
||||
gui = GUI(profile_handler, temps.temperaturesUpdated)
|
||||
gui = GUI(profile_handler, bms.dataUpdated)
|
||||
|
||||
return app.exec()
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user