Added temperature monitor screen. Added current factors for BMS configuration

This commit is contained in:
Yury Shuvakin
2023-03-21 10:10:28 +03:00
parent 7c732215ec
commit 0daea7162a
17 changed files with 1496 additions and 326 deletions

View File

@@ -62,6 +62,7 @@ RowLayout {
Layout.fillWidth: true
GridLayout {
id: configurationLayout
columns: 2
rowSpacing: contentRowSpacing
columnSpacing: contentColumnSpacing
@@ -87,17 +88,137 @@ RowLayout {
Controls.TextField {
id: numberOfBoardsField
validator: IntValidator {}
validator: IntValidator { bottom: 0 }
Layout.fillWidth: true
Layout.maximumWidth: (parent.width - parent.columnSpacing) / 2
onTextChanged: configurationLayout.recalculateSensorsMasks()
}
Controls.TextField {
id: numberOfCellsField
validator: IntValidator {}
validator: IntValidator { bottom: 0 }
Layout.fillWidth: true
Layout.maximumWidth: (parent.width - parent.columnSpacing) / 2
}
Repeater {
id: bmsSensorsMaskRepeater
property var bmsSensorsMaskModel: []
ColumnLayout {
id: bmsSensorsMaskLayout
Layout.fillWidth: true
property var boardIndex: index
Controls.SubtitleLabel {
text: index === 0 ? qsTr("BMS sensors mask for master board") : qsTr("BMS sensors mask for slave board #") + index
maximumLineCount: 2
wrapMode: Text.WordWrap
Layout.fillWidth: true
}
Controls.Frame {
padding: 10
Layout.fillWidth: true
Layout.fillHeight: true
ColumnLayout {
spacing: 10
anchors.fill: parent
Repeater {
model: 4
Controls.CheckBox {
text: qsTr("#") + (index + 1)
opacity: (bmsSensorsMaskLayout.boardIndex === 0 && (index === 2 || index === 3)) ? 0 : 1
enabled: opacity
checked: bmsSensorsMaskRepeater.bmsSensorsMaskModel[bmsSensorsMaskLayout.boardIndex * 4 + index]
onCheckedChanged: bmsSensorsMaskRepeater.bmsSensorsMaskModel[bmsSensorsMaskLayout.boardIndex * 4 + index] = checked
}
}
Item {
visible: index === 0
Layout.fillHeight: true
}
}
}
}
}
Repeater {
id: batterySensorsMaskRepeater
property var batterySensorsMaskModel: []
ColumnLayout {
id: batterySensorsMaskLayout
Layout.fillWidth: true
property var boardIndex: index
Controls.SubtitleLabel {
text: index === 0 ? qsTr("Battery sensors mask for master board") : qsTr("Battery sensors mask for slave board #") + index
maximumLineCount: 2
wrapMode: Text.WordWrap
Layout.fillWidth: true
}
Controls.Frame {
padding: 10
Layout.fillWidth: true
Layout.fillHeight: true
ColumnLayout {
spacing: 10
anchors.fill: parent
Repeater {
model: 4
Controls.CheckBox {
text: qsTr("#") + (index + 1)
enabled: opacity
opacity: (batterySensorsMaskLayout.boardIndex === 0 && (index === 2 || index === 3)) ? 0 : 1
checked: batterySensorsMaskRepeater.batterySensorsMaskModel[batterySensorsMaskLayout.boardIndex * 4 + index]
onCheckedChanged: batterySensorsMaskRepeater.batterySensorsMaskModel[batterySensorsMaskLayout.boardIndex * 4 + index] = checked
}
}
Item {
visible: index === 0
Layout.fillHeight: true
}
}
}
}
}
function recalculateSensorsMasks() {
const bmsSensorsModel = bmsSensorsMaskRepeater.bmsSensorsMaskModel
const batterySensorsModel = batterySensorsMaskRepeater.batterySensorsMaskModel
const newSize = parseInt(numberOfBoardsField.text) * 4
if (newSize) {
arrayResize(bmsSensorsModel, newSize, false)
arrayResize(batterySensorsModel, newSize, true)
bmsSensorsMaskRepeater.model = 0
bmsSensorsMaskRepeater.bmsSensorsMaskModel = bmsSensorsModel
bmsSensorsMaskRepeater.model = parseInt(numberOfBoardsField.text)
batterySensorsMaskRepeater.model = 0
batterySensorsMaskRepeater.batterySensorsMaskModel = batterySensorsModel
batterySensorsMaskRepeater.model = parseInt(numberOfBoardsField.text)
}
}
function arrayResize(array, size, value) {
while (array.length > size) { array.pop(); }
while (array.length < size) { array.push(value); }
}
}
}
@@ -363,6 +484,82 @@ RowLayout {
}
}
Controls.Frame {
id: currentConfigurationFrame
padding: contentPadding
implicitWidth: parent.width
Layout.fillWidth: true
GridLayout {
columns: 2
rowSpacing: contentRowSpacing
columnSpacing: contentColumnSpacing
anchors.fill: parent
Controls.TitleLabel {
text: qsTr("Current configuration")
Layout.fillWidth: true
Layout.columnSpan: 2
}
Controls.SubtitleLabel {
text: qsTr("Current factor K1")
maximumLineCount: 2
wrapMode: Text.WordWrap
Layout.fillWidth: true
Layout.maximumWidth: (parent.width - parent.columnSpacing) / 2
}
Controls.SubtitleLabel {
text: qsTr("Current factor K2")
maximumLineCount: 2
wrapMode: Text.WordWrap
Layout.fillWidth: true
Layout.maximumWidth: (parent.width - parent.columnSpacing) / 2
}
Controls.TextField {
id: currentFactorK1Field
validator: DoubleValidator { decimals: 3; locale: "en-US"; notation: DoubleValidator.StandardNotation }
Layout.fillWidth: true
Layout.maximumWidth: (parent.width - parent.columnSpacing) / 2
}
Controls.TextField {
id: currentFactorK2Field
validator: DoubleValidator { decimals: 3; locale: "en-US"; notation: DoubleValidator.StandardNotation }
Layout.fillWidth: true
Layout.maximumWidth: (parent.width - parent.columnSpacing) / 2
}
Controls.SubtitleLabel {
text: qsTr("Current sensor value \"0\"")
Layout.fillWidth: true
Layout.columnSpan: 2
}
Controls.TextField {
id: zeroSensorValueField
validator: DoubleValidator { decimals: 3; locale: "en-US"; notation: DoubleValidator.StandardNotation }
Layout.fillWidth: true
Layout.maximumWidth: (parent.width - parent.columnSpacing) / 2
Layout.columnSpan: 2
}
Controls.Button {
id: zeroSensorValueCalibrationButton
text: qsTr("Calibrate \"0\"")
Layout.fillWidth: true
Layout.maximumWidth: (parent.width - parent.columnSpacing) / 2
Layout.columnSpan: 2
onClicked: {
BmsInterface.commands().sendTerminalCmd("setZeroCurrent")
Qt.callLater(storeBmsConfigurationButton.clicked)
}
}
}
}
Controls.Frame {
id: outputSettingsFrame
padding: contentPadding
@@ -581,43 +778,6 @@ RowLayout {
}
}
Controls.Frame {
id: zeroSensorSettingsFrame
padding: contentPadding
implicitWidth: parent.width
Layout.fillWidth: true
GridLayout {
columns: 2
rowSpacing: contentRowSpacing
columnSpacing: contentColumnSpacing
anchors.fill: parent
Controls.SubtitleLabel {
text: qsTr("Current sensor value \"0\"")
Layout.fillWidth: true
Layout.columnSpan: 2
}
Controls.TextField {
id: zeroSensorValueField
validator: DoubleValidator { decimals: 2; locale: "en-US"; notation: DoubleValidator.StandardNotation }
Layout.fillWidth: true
Layout.maximumWidth: (parent.width - parent.columnSpacing) / 2
Layout.columnSpan: 2
}
Controls.Button {
id: zeroSensorValueCalibrationButton
text: qsTr("Calibrate \"0\"")
Layout.fillWidth: true
Layout.maximumWidth: (parent.width - parent.columnSpacing) / 2
Layout.columnSpan: 2
onClicked: BmsInterface.commands().sendTerminalCmd("setZeroCurrent")
}
}
}
Controls.OutlineButton {
text: qsTr("Load settings from file")
onClicked: loadFileDialog.open()
@@ -710,14 +870,14 @@ RowLayout {
}
Controls.LinkLabel {
text: qsTr("Output settings")
onClicked: settingsFlickable.contentY = outputSettingsFrame.mapToItem(settingsFlickable.contentItem, 0, 0).y
text: qsTr("Current configuration")
onClicked: settingsFlickable.contentY = currentConfigurationFrame.mapToItem(settingsFlickable.contentItem, 0, 0).y
}
Controls.LinkLabel {
text: qsTr("Current sensor value \"0\"")
text: qsTr("Output settings")
onClicked: {
settingsFlickable.contentY = zeroSensorSettingsFrame.mapToItem(settingsFlickable.contentItem, 0, 0).y
settingsFlickable.contentY = outputSettingsFrame.mapToItem(settingsFlickable.contentItem, 0, 0).y
settingsFlickable.returnToBounds()
}
}
@@ -746,6 +906,7 @@ RowLayout {
}
Controls.OutlineButton {
id: writeBmsConfigurationButton
text: qsTr("Write current values to BMS")
Layout.fillWidth: true
onClicked: if (BmsInterface.isPortConnected()) {
@@ -755,6 +916,7 @@ RowLayout {
}
Controls.Button {
id: storeBmsConfigurationButton
text: qsTr("Write to non-volatile memory of BMS")
Layout.fillWidth: true
onClicked: if (BmsInterface.isPortConnected()) {
@@ -777,6 +939,29 @@ RowLayout {
BmsInterface.bmsConfig().setParamValue("cellMonitorICCount", parseInt(numberOfBoardsField.text))
BmsInterface.bmsConfig().setParamValue("noOfCellsSeries", parseInt(numberOfCellsField.text))
const numberOfBoards = parseInt(numberOfBoardsField.text)
const bmsSensorsModel = bmsSensorsMaskRepeater.bmsSensorsMaskModel
const batterySensorsModel = batterySensorsMaskRepeater.batterySensorsMaskModel
let bmsSensorsMask = 0
let batterySensorsMask = 0
for (let i = 0; i < numberOfBoards * 4; ++i) {
bmsSensorsMask |= Number(bmsSensorsModel[i]) << i
batterySensorsMask |= Number(batterySensorsModel[i]) << i
}
// disable 3 and 4 sensor for master
bmsSensorsMask = bmsSensorsMask & ~(1 << 2)
bmsSensorsMask = bmsSensorsMask & ~(1 << 3)
batterySensorsMask = batterySensorsMask & ~(1 << 2)
batterySensorsMask = batterySensorsMask & ~(1 << 3)
print(bmsSensorsMask, batterySensorsMask)
BmsInterface.bmsConfig().setParamValue("tempEnableMaskBMS", bmsSensorsMask)
BmsInterface.bmsConfig().setParamValue("tempEnableMaskBattery", batterySensorsMask)
BmsInterface.bmsConfig().setParamValue("noOfCellsParallel", parseInt(numberOfParallelCellsField.text))
BmsInterface.bmsConfig().setParamValue("batteryCapacity", parseFloat(batteryCapacityField.text))
@@ -793,6 +978,8 @@ RowLayout {
BmsInterface.bmsConfig().setParamValue("cellBalanceDifferenceThreshold", parseFloat(balancingStartDeltaVoltageField.text))
BmsInterface.bmsConfig().setParamValue("cellBalanceUpdateInterval", parseInt(balancingCellIntervalField.text))
BmsInterface.bmsConfig().setParamValue("floatCurrentK1", parseFloat(currentFactorK1Field.text))
BmsInterface.bmsConfig().setParamValue("floatCurrentK2", parseFloat(currentFactorK2Field.text))
BmsInterface.bmsConfig().setParamValue("shuntLCFactor", parseFloat(zeroSensorValueField.text))
BmsInterface.bmsConfig().setParamValue("chargeBatteryOutputChecked", chargeBatteryOutputCheckBox.checked)
@@ -819,6 +1006,21 @@ RowLayout {
numberOfBoardsField.text = BmsInterface.bmsConfig().getParamInt("cellMonitorICCount")
numberOfCellsField.text = BmsInterface.bmsConfig().getParamInt("noOfCellsSeries")
const numberOfBoards = BmsInterface.bmsConfig().getParamInt("cellMonitorICCount")
const numberOfSensorsPerBoard = BmsInterface.bmsConfig().getParamInt("noOfTempSensorPerModule")
const bmsSensorsMask = BmsInterface.bmsConfig().getParamInt("tempEnableMaskBMS")
const batterySensorsMask = BmsInterface.bmsConfig().getParamInt("tempEnableMaskBattery")
const bmsSensorsModel = []
const batterySensorsModel = []
for (let i = 0; i < numberOfBoards * numberOfSensorsPerBoard; ++i) {
bmsSensorsModel.push((bmsSensorsMask & (1 << i)) != 0)
batterySensorsModel.push((batterySensorsMask & (1 << i)) != 0)
}
bmsSensorsMaskRepeater.bmsSensorsMaskModel = bmsSensorsModel
batterySensorsMaskRepeater.batterySensorsMaskModel = batterySensorsModel
numberOfParallelCellsField.text = BmsInterface.bmsConfig().getParamInt("noOfCellsParallel")
batteryCapacityField.text = MathHelper.roundDouble(BmsInterface.bmsConfig().getParamDouble("batteryCapacity"))
@@ -835,7 +1037,9 @@ RowLayout {
balancingStartDeltaVoltageField.text = MathHelper.roundDouble(BmsInterface.bmsConfig().getParamDouble("cellBalanceDifferenceThreshold"))
balancingCellIntervalField.text = BmsInterface.bmsConfig().getParamInt("cellBalanceUpdateInterval")
zeroSensorValueField.text = MathHelper.roundDouble(BmsInterface.bmsConfig().getParamDouble("shuntLCFactor"))
currentFactorK1Field.text = MathHelper.roundDouble(BmsInterface.bmsConfig().getParamDouble("floatCurrentK1"), 3)
currentFactorK2Field.text = MathHelper.roundDouble(BmsInterface.bmsConfig().getParamDouble("floatCurrentK2"), 3)
zeroSensorValueField.text = MathHelper.roundDouble(BmsInterface.bmsConfig().getParamDouble("shuntLCFactor"), 3)
chargeBatteryOutputCheckBox.checked = BmsInterface.bmsConfig().getParamBool("chargeBatteryOutputChecked")

View File

@@ -0,0 +1,102 @@
import QtQuick 2.12
import QtQuick.Layouts 1.12
import QtQuick.Controls 1.4 as OldControls
import Controls 1.0 as Controls
import Cubo 1.0
ColumnLayout {
spacing: 10
Controls.Frame {
padding: 35
topPadding: 20
bottomPadding: 20
ColumnLayout {
anchors.fill: parent
spacing: 20
Controls.TitleLabel {
text: qsTr("CAN availability state")
Layout.fillWidth: true
}
GridLayout {
columns: 2
Controls.AvailabilityIndicator {
neutral: false
}
Controls.SubtitleLabel {
text: qsTr("External CAN")
}
Controls.AvailabilityIndicator {
neutral: false
}
Controls.SubtitleLabel {
text: qsTr("Charging CAN")
}
Layout.fillWidth: true
}
RowLayout {
Controls.CheckBox {
leftPadding: 0
text: qsTr("External CAN")
}
Controls.CheckBox {
leftPadding: 0
text: qsTr("Charging CAN")
}
Controls.Button {
text: qsTr("Apply")
}
}
}
Layout.fillWidth: true
}
Controls.Frame {
padding: 35
topPadding: 20
bottomPadding: 20
OldControls.TableView {
id: currentTable
anchors.fill: parent
// columnSpacing: 1
// rowSpacing: 1
clip: true
property var currentModel: CurrentTableModel{}
model: currentModel
// delegate: Rectangle {
// implicitWidth: 100
// implicitHeight: 50
// border.width: 1
// Text {
// text: display
// anchors.centerIn: parent
// }
// }
}
Component.onCompleted: {
currentTable.currentModel.setCurrentData([[0.2, 0.5, 1],[0.2, 0.7, 1],[0.2, 0.6, 1]])
}
Layout.fillWidth: true
Layout.fillHeight: true
}
}

View File

@@ -0,0 +1,287 @@
import QtQuick 2.12
import QtQuick.Controls 2.12
import QtQuick.Layouts 1.12
import Controls 1.0 as Controls
import Cubo 1.0
import Utils 1.0
Item {
id: root
property var numberOfBoards: 0
property var auxSensorsModel: []
property var expSensorsModel: []
ColumnLayout {
spacing: 15
anchors.fill: parent
Controls.Frame {
padding: 25
implicitWidth: parent.width
Layout.fillWidth: true
Layout.rightMargin: 10
GridLayout {
columns: 2
columnSpacing: 70
rowSpacing: 15
anchors.fill: parent
RowLayout {
spacing: 10
Controls.ContentLabel {
text: qsTr("Minimum battery temperature, °C")
}
Controls.DotSeparator {
Layout.fillWidth: true
}
Controls.SubtitleLabel {
id: minBatteryTemperatureLabel
text: "-"
}
Layout.fillWidth: true
Layout.maximumWidth: (parent.width - parent.columnSpacing) / 2
}
RowLayout {
spacing: 10
Controls.ContentLabel {
text: qsTr("Minimum BMS temperature, °C")
}
Controls.DotSeparator {
Layout.fillWidth: true
}
Controls.SubtitleLabel {
id: minBmsTemperatureLabel
text: "-"
}
Layout.fillWidth: true
Layout.maximumWidth: (parent.width - parent.columnSpacing) / 2
}
RowLayout {
spacing: 10
Controls.ContentLabel {
text: qsTr("Average battery temperature, °C")
}
Controls.DotSeparator {
Layout.fillWidth: true
}
Controls.SubtitleLabel {
id: avgBatteryTemperatureLabel
text: "-"
}
Layout.fillWidth: true
Layout.maximumWidth: (parent.width - parent.columnSpacing) / 2
}
RowLayout {
spacing: 10
Controls.ContentLabel {
text: qsTr("Average BMS temperature, °C")
}
Controls.DotSeparator {
Layout.fillWidth: true
}
Controls.SubtitleLabel {
id: avgBmsTemperatureLabel
text: "-"
}
Layout.fillWidth: true
Layout.maximumWidth: (parent.width - parent.columnSpacing) / 2
}
RowLayout {
spacing: 10
Controls.ContentLabel {
text: qsTr("Maximum battery temperature, °C")
}
Controls.DotSeparator {
Layout.fillWidth: true
}
Controls.SubtitleLabel {
id: maxBatteryTemperatureLabel
text: "-"
}
Layout.fillWidth: true
Layout.maximumWidth: (parent.width - parent.columnSpacing) / 2
}
RowLayout {
spacing: 10
Controls.ContentLabel {
text: qsTr("Maximum BMS temperature, °C")
}
Controls.DotSeparator {
Layout.fillWidth: true
}
Controls.SubtitleLabel {
id: maxBmsTemperatureLabel
text: "-"
}
Layout.fillWidth: true
Layout.maximumWidth: (parent.width - parent.columnSpacing) / 2
}
}
}
Flickable {
id: settingsFlickable
clip: true
contentWidth: width - rightMargin - leftMargin
contentHeight: boardsLayout.height
boundsBehavior: Flickable.StopAtBounds
rightMargin: 10
GridLayout {
id: boardsLayout
width: parent.width
columns: 2
rowSpacing: 15
columnSpacing: 15
Repeater {
model: numberOfBoards
Controls.Frame {
padding: 25
Layout.fillWidth: true
Layout.maximumWidth: (parent.width - parent.columnSpacing) / 2
ColumnLayout {
id: sensorsLayout
anchors.fill: parent
spacing: 15
property var boardIndex: index
Controls.SubtitleLabel {
text: index === 0 ? qsTr("Sensors for master board") : qsTr("Sensors for slave board #") + index
maximumLineCount: 2
wrapMode: Text.WordWrap
Layout.fillWidth: true
}
Repeater {
model: 4
RowLayout {
spacing: 10
opacity: (sensorsLayout.boardIndex === 0 && (index === 2 || index === 3)) ? 0 : 1
Controls.ContentLabel {
text: qsTr("Sensor #") + (index + 1) + ", °C"
}
Controls.DotSeparator {
Layout.fillWidth: true
}
Controls.SubtitleLabel {
text: {
var value = auxSensorsModel[sensorsLayout.boardIndex * 4 + index]
return value ? value : 0
}
}
Layout.fillWidth: true
Layout.maximumWidth: (parent.width - parent.columnSpacing) / 2
}
}
}
}
}
}
ScrollBar.vertical: Controls.ScrollBar {}
Layout.fillWidth: true
Layout.fillHeight: true
}
}
Connections {
target: BmsInterface.commands()
enabled: root.visible
onValuesReceived: {
maxBatteryTemperatureLabel.text = MathHelper.roundDouble(values.tempBattHigh)
avgBatteryTemperatureLabel.text = MathHelper.roundDouble(values.tempBattAverage)
minBatteryTemperatureLabel.text = MathHelper.roundDouble(values.tempBattLow)
maxBmsTemperatureLabel.text = MathHelper.roundDouble(values.tempBMSHigh)
avgBmsTemperatureLabel.text = MathHelper.roundDouble(values.tempBMSAverage)
minBmsTemperatureLabel.text = MathHelper.roundDouble(values.tempBMSLow)
}
onAuxReceived: {
let tempModel = []
for (let temperature of auxVoltageArray) {
tempModel.push(temperature)
}
auxSensorsModel = []
auxSensorsModel = tempModel
}
onExpTempReceived: {
let tempModel = []
for (let temperature of expTempVoltageArray) {
tempModel.push(temperature)
}
expSensorsModel = []
expSensorsModel = tempModel
}
}
Connections {
target: BmsInterface.bmsConfig()
onUpdated: {
numberOfBoards = BmsInterface.bmsConfig().getParamInt("cellMonitorICCount")
}
}
Connections {
target: BmsInterface
onPortConnectedChanged: getValues()
}
onVisibleChanged: getValues()
Timer {
id: refreshValuesTimer
interval: 1000
onTriggered: getValues()
}
function getValues() {
if (BmsInterface.isPortConnected() && visible) {
BmsInterface.commands().getValues()
BmsInterface.commands().getAux()
// BmsInterface.commands().getExpansionTemp()
refreshValuesTimer.start()
}
}
}

View File

@@ -12,3 +12,5 @@ TerminalScreen 1.0 TerminalScreen.qml
FirmwareUpdateScreen 1.0 FirmwareUpdateScreen.qml
NetworkSettingsScreen 1.0 NetworkSettingsScreen.qml
TimeSettingsScreen 1.0 TimeSettingsScreen.qml
CanSettingsScreen 1.0 CanSettingsScreen.qml
TemperatureMonitorScreen 1.0 TemperatureMonitorScreen.qml