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.QtWidgets import QFileDialog
|
||||||
from PySide6.QtQml import QQmlApplicationEngine
|
from PySide6.QtQml import QQmlApplicationEngine
|
||||||
|
|
||||||
|
from .bms import BMSData
|
||||||
from .profile_handler import ProfileHandler, ProfileState
|
from .profile_handler import ProfileHandler, ProfileState
|
||||||
|
|
||||||
|
|
||||||
@ -17,7 +18,7 @@ class GUI(QObject):
|
|||||||
_start_pause_btn: QObject
|
_start_pause_btn: QObject
|
||||||
_stop_btn: QObject
|
_stop_btn: QObject
|
||||||
|
|
||||||
def __init__(self, profile_handler: ProfileHandler, temperaturesUpdated: Signal):
|
def __init__(self, profile_handler: ProfileHandler, bmsUpdated: Signal):
|
||||||
super().__init__(None)
|
super().__init__(None)
|
||||||
|
|
||||||
self._engine = QQmlApplicationEngine()
|
self._engine = QQmlApplicationEngine()
|
||||||
@ -42,7 +43,7 @@ class GUI(QObject):
|
|||||||
self._update_timer.timeout.connect(self._update)
|
self._update_timer.timeout.connect(self._update)
|
||||||
self._update_timer.start(100)
|
self._update_timer.start(100)
|
||||||
|
|
||||||
temperaturesUpdated.connect(self._updateTemperatures)
|
bmsUpdated.connect(self._updateBMS)
|
||||||
|
|
||||||
def _choose_profile(self):
|
def _choose_profile(self):
|
||||||
dlg = QFileDialog()
|
dlg = QFileDialog()
|
||||||
@ -82,6 +83,8 @@ class GUI(QObject):
|
|||||||
dt = time.time() - self._profile_handler.profile_start
|
dt = time.time() - self._profile_handler.profile_start
|
||||||
self._win.setProperty("profileTime", dt)
|
self._win.setProperty("profileTime", dt)
|
||||||
|
|
||||||
def _updateTemperatures(self, temperatures: list[int]):
|
def _updateBMS(self, data: BMSData):
|
||||||
self._win.setProperty("temp_min", min(temperatures))
|
self._win.setProperty("voltage_min", min(data.voltages))
|
||||||
self._win.setProperty("temp_max", max(temperatures))
|
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 sys
|
||||||
import serial
|
import serial
|
||||||
import struct
|
import struct
|
||||||
|
import time
|
||||||
|
|
||||||
from PySide6.QtCore import QObject, Signal
|
from PySide6.QtCore import QObject, Signal
|
||||||
|
|
||||||
@ -21,6 +22,7 @@ class Temperatures(QObject):
|
|||||||
|
|
||||||
def run(self):
|
def run(self):
|
||||||
while True:
|
while True:
|
||||||
|
time.sleep(0.1)
|
||||||
self.dev.read_until(START_OF_TEMPS)
|
self.dev.read_until(START_OF_TEMPS)
|
||||||
data = self.dev.read(N_SENSORS * 2)
|
data = self.dev.read(N_SENSORS * 2)
|
||||||
temps = struct.unpack(f">{N_SENSORS}h", data)
|
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.load import Load
|
||||||
from load_controller.profile_handler import ProfileHandler
|
from load_controller.profile_handler import ProfileHandler
|
||||||
from load_controller.temperatures import Temperatures
|
from load_controller.temperatures import Temperatures
|
||||||
|
from load_controller.bms import BMSEvalBoard
|
||||||
|
|
||||||
|
|
||||||
def main(argv: list[str]) -> int:
|
def main(argv: list[str]) -> int:
|
||||||
@ -22,8 +23,13 @@ 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_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()
|
return app.exec()
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user