Files
CuboBmsTool/qml/Screens/BmsSettingsScreen.qml

1062 lines
47 KiB
QML

import QtQuick 2.12
import QtQuick.Controls 2.12
import QtQuick.Layouts 1.12
import QtQuick.Dialogs 1.2
import Qt.labs.settings 1.1
import Controls 1.0 as Controls
import Cubo 1.0
import Utils 1.0
RowLayout {
property real contentPadding: 35
property real contentRowSpacing: 20
property real contentColumnSpacing: 35
signal needWait(bool active, string text)
spacing: contentColumnSpacing - 10
Flickable {
id: settingsFlickable
clip: true
contentWidth: width - rightMargin - leftMargin
contentHeight: configLayout.height
boundsBehavior: Flickable.StopAtBounds
rightMargin: 10
ColumnLayout {
id: configLayout
width: parent.width
spacing: 15
Controls.Frame {
id: serialNumberSettingsFrame
padding: contentPadding
implicitWidth: parent.width
Layout.fillWidth: true
RowLayout {
spacing: contentColumnSpacing
anchors.fill: parent
Controls.TitleLabel {
text: qsTr("Serial number")
Layout.fillWidth: true
Layout.maximumWidth: (parent.width - parent.spacing) / 2
}
Controls.TextField {
id: serialNumberField
validator: RegExpValidator { regExp: /[1-9][0-9]*/ }
Layout.fillWidth: true
Layout.maximumWidth: (parent.width - parent.spacing) / 2
}
}
}
Controls.Frame {
id: configurationSettingsFrame
padding: contentPadding
implicitWidth: parent.width
Layout.fillWidth: true
GridLayout {
id: configurationLayout
columns: 2
rowSpacing: contentRowSpacing
columnSpacing: contentColumnSpacing
anchors.fill: parent
Controls.TitleLabel {
text: qsTr("Configuration")
Layout.fillWidth: true
Layout.columnSpan: 2
}
Controls.SubtitleLabel {
text: qsTr("Number of boards")
Layout.fillWidth: true
Layout.maximumWidth: (parent.width - parent.columnSpacing) / 2
}
Controls.SubtitleLabel {
text: qsTr("Number of cells")
Layout.fillWidth: true
Layout.maximumWidth: (parent.width - parent.columnSpacing) / 2
}
Controls.TextField {
id: numberOfBoardsField
validator: IntValidator { bottom: 0 }
Layout.fillWidth: true
Layout.maximumWidth: (parent.width - parent.columnSpacing) / 2
onTextChanged: configurationLayout.recalculateSensorsMasks()
}
Controls.TextField {
id: numberOfCellsField
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); }
}
}
}
Controls.Frame {
id: socSettingsFrame
padding: contentPadding
implicitWidth: parent.width
Layout.fillWidth: true
GridLayout {
columns: 2
rowSpacing: contentRowSpacing
columnSpacing: contentColumnSpacing
anchors.fill: parent
Controls.TitleLabel {
text: qsTr("SOC")
Layout.fillWidth: true
Layout.columnSpan: 2
}
Controls.SubtitleLabel {
text: qsTr("Number of cells connected in parallel")
maximumLineCount: 2
wrapMode: Text.WordWrap
Layout.fillWidth: true
Layout.maximumWidth: (parent.width - parent.columnSpacing) / 2
}
Controls.SubtitleLabel {
text: qsTr("Battery capacity")
Layout.fillWidth: true
Layout.maximumWidth: (parent.width - parent.columnSpacing) / 2
}
Controls.TextField {
id: numberOfParallelCellsField
validator: IntValidator {}
Layout.fillWidth: true
Layout.maximumWidth: (parent.width - parent.columnSpacing) / 2
}
Controls.TextField {
id: batteryCapacityField
validator: DoubleValidator { decimals: 2; locale: "en-US"; notation: DoubleValidator.StandardNotation }
Layout.fillWidth: true
Layout.maximumWidth: (parent.width - parent.columnSpacing) / 2
}
}
}
Controls.Frame {
id: limitSettingsFrame
padding: contentPadding
implicitWidth: parent.width
Layout.fillWidth: true
GridLayout {
columns: 2
rowSpacing: contentRowSpacing
columnSpacing: contentColumnSpacing
anchors.fill: parent
Controls.TitleLabel {
text: qsTr("Limits")
Layout.fillWidth: true
Layout.columnSpan: 2
}
Controls.SubtitleLabel {
text: qsTr("Maximum charge current, A")
maximumLineCount: 2
wrapMode: Text.WordWrap
Layout.fillWidth: true
Layout.maximumWidth: (parent.width - parent.columnSpacing) / 2
}
Controls.SubtitleLabel {
text: qsTr("Maximum load current, A")
maximumLineCount: 2
wrapMode: Text.WordWrap
Layout.fillWidth: true
Layout.maximumWidth: (parent.width - parent.columnSpacing) / 2
}
Controls.TextField {
id: maximumChargeCurrentField
validator: DoubleValidator { decimals: 2; locale: "en-US"; notation: DoubleValidator.StandardNotation }
Layout.fillWidth: true
Layout.maximumWidth: (parent.width - parent.columnSpacing) / 2
}
Controls.TextField {
id: maximumLoadCurrentField
validator: DoubleValidator { decimals: 2; locale: "en-US"; notation: DoubleValidator.StandardNotation }
Layout.fillWidth: true
Layout.maximumWidth: (parent.width - parent.columnSpacing) / 2
}
Controls.SubtitleLabel {
text: qsTr("Maximum temperature, °C")
maximumLineCount: 2
wrapMode: Text.WordWrap
Layout.fillWidth: true
Layout.maximumWidth: (parent.width - parent.columnSpacing) / 2
Layout.columnSpan: 2
}
Controls.TextField {
id: maximumTemperatureField
validator: DoubleValidator { decimals: 2; locale: "en-US"; notation: DoubleValidator.StandardNotation }
Layout.fillWidth: true
Layout.maximumWidth: (parent.width - parent.columnSpacing) / 2
Layout.columnSpan: 2
}
}
}
Controls.Frame {
id: cellSettingsFrame
padding: contentPadding
implicitWidth: parent.width
Layout.fillWidth: true
GridLayout {
columns: 2
rowSpacing: contentRowSpacing
columnSpacing: contentColumnSpacing
anchors.fill: parent
Controls.TitleLabel {
text: qsTr("Cell configuration")
Layout.fillWidth: true
Layout.columnSpan: 2
}
Controls.SubtitleLabel {
text: qsTr("Lower disable threshold, V")
maximumLineCount: 2
wrapMode: Text.WordWrap
Layout.fillWidth: true
Layout.maximumWidth: (parent.width - parent.columnSpacing) / 2
}
Controls.SubtitleLabel {
text: qsTr("Upper disable threshold, V")
maximumLineCount: 2
wrapMode: Text.WordWrap
Layout.fillWidth: true
Layout.maximumWidth: (parent.width - parent.columnSpacing) / 2
}
Controls.TextField {
id: lowerDisableThresholdField
validator: DoubleValidator { decimals: 2; locale: "en-US"; notation: DoubleValidator.StandardNotation }
Layout.fillWidth: true
Layout.maximumWidth: (parent.width - parent.columnSpacing) / 2
}
Controls.TextField {
id: upperDisableThresholdField
validator: DoubleValidator { decimals: 2; locale: "en-US"; notation: DoubleValidator.StandardNotation }
Layout.fillWidth: true
Layout.maximumWidth: (parent.width - parent.columnSpacing) / 2
}
Controls.SubtitleLabel {
text: qsTr("Lower enable threshold (should be higher than disable), V")
maximumLineCount: 3
wrapMode: Text.WordWrap
Layout.fillWidth: true
Layout.maximumWidth: (parent.width - parent.columnSpacing) / 2
}
Controls.SubtitleLabel {
text: qsTr("Upper enable threshold (should be higher than disable), V")
maximumLineCount: 3
wrapMode: Text.WordWrap
Layout.fillWidth: true
Layout.maximumWidth: (parent.width - parent.columnSpacing) / 2
}
Controls.TextField {
id: lowerEnableThresholdField
validator: DoubleValidator { decimals: 2; locale: "en-US"; notation: DoubleValidator.StandardNotation }
Layout.fillWidth: true
Layout.maximumWidth: (parent.width - parent.columnSpacing) / 2
}
Controls.TextField {
id: upperEnableThresholdField
validator: DoubleValidator { decimals: 2; locale: "en-US"; notation: DoubleValidator.StandardNotation }
Layout.fillWidth: true
Layout.maximumWidth: (parent.width - parent.columnSpacing) / 2
}
}
}
Controls.Frame {
id: balancingSettingsFrame
padding: contentPadding
implicitWidth: parent.width
Layout.fillWidth: true
GridLayout {
columns: 2
rowSpacing: contentRowSpacing
columnSpacing: contentColumnSpacing
anchors.fill: parent
Controls.TitleLabel {
text: qsTr("Balancing configuration")
Layout.fillWidth: true
Layout.columnSpan: 2
}
Controls.SubtitleLabel {
text: qsTr("Balancing start voltage, V")
maximumLineCount: 2
wrapMode: Text.WordWrap
Layout.fillWidth: true
Layout.maximumWidth: (parent.width - parent.columnSpacing) / 2
}
Controls.SubtitleLabel {
text: qsTr("Cell voltage delta to start balancing, V")
maximumLineCount: 2
wrapMode: Text.WordWrap
Layout.fillWidth: true
Layout.maximumWidth: (parent.width - parent.columnSpacing) / 2
}
Controls.TextField {
id: balancingStartVoltageField
validator: DoubleValidator { decimals: 2; locale: "en-US"; notation: DoubleValidator.StandardNotation }
Layout.fillWidth: true
Layout.maximumWidth: (parent.width - parent.columnSpacing) / 2
}
Controls.TextField {
id: balancingStartDeltaVoltageField
validator: DoubleValidator { decimals: 2; locale: "en-US"; notation: DoubleValidator.StandardNotation }
Layout.fillWidth: true
Layout.maximumWidth: (parent.width - parent.columnSpacing) / 2
}
Controls.SubtitleLabel {
text: qsTr("Cell balancing interval, ms")
maximumLineCount: 2
wrapMode: Text.WordWrap
Layout.fillWidth: true
Layout.maximumWidth: (parent.width - parent.columnSpacing) / 2
Layout.columnSpan: 2
}
Controls.TextField {
id: balancingCellIntervalField
validator: IntValidator {}
Layout.fillWidth: true
Layout.maximumWidth: (parent.width - parent.columnSpacing) / 2
Layout.columnSpan: 2
}
}
}
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
implicitWidth: parent.width
Layout.fillWidth: true
property real outputNumberSize: 60
GridLayout {
columns: 2
rowSpacing: contentRowSpacing
columnSpacing: contentColumnSpacing
anchors.fill: parent
Controls.TitleLabel {
text: qsTr("Output settings")
Layout.fillWidth: true
Layout.columnSpan: 2
}
RowLayout {
spacing: 20
Controls.LabelWithBackground {
text: qsTr("# 1")
Layout.preferredWidth: outputSettingsFrame.outputNumberSize
Layout.preferredHeight: outputSettingsFrame.outputNumberSize
}
Controls.CheckBox {
id: chargeBatteryOutputCheckBox
text: qsTr("Use to control charger")
Layout.fillWidth: true
Layout.preferredHeight: outputSettingsFrame.outputNumberSize
}
Layout.fillWidth: true
Layout.columnSpan: 2
}
Controls.LineSeparator {
Layout.fillWidth: true
Layout.columnSpan: 2
}
RowLayout {
spacing: 20
Controls.LabelWithBackground {
text: qsTr("# 2")
Layout.preferredWidth: outputSettingsFrame.outputNumberSize
Layout.preferredHeight: outputSettingsFrame.outputNumberSize
}
Controls.CheckBox {
id: brushOrShuntOutputCheckBox
text: qsTr("Active")
Layout.fillWidth: true
Layout.preferredHeight: outputSettingsFrame.outputNumberSize
}
Layout.fillWidth: true
Layout.columnSpan: 2
}
Controls.RadioButton {
id: brushControlRadioButton
text: qsTr("Brush control")
Layout.fillWidth: true
Layout.maximumWidth: (parent.width - parent.columnSpacing) / 2
}
Controls.RadioButton {
id: shuntChargingContactorRadioButton
text: qsTr("Shunt charging contactor")
Layout.fillWidth: true
Layout.maximumWidth: (parent.width - parent.columnSpacing) / 2
}
Controls.SubtitleLabel {
text: qsTr("SOC threshold, %")
maximumLineCount: 2
wrapMode: Text.WordWrap
Layout.fillWidth: true
Layout.maximumWidth: (parent.width - parent.columnSpacing) / 2
}
Controls.SubtitleLabel {
text: qsTr("Delay, s")
maximumLineCount: 2
wrapMode: Text.WordWrap
Layout.fillWidth: true
Layout.maximumWidth: (parent.width - parent.columnSpacing) / 2
}
Controls.TextField {
id: brushUsageSocThresholdField
validator: IntValidator { bottom: 0; top: 100 }
Layout.fillWidth: true
Layout.maximumWidth: (parent.width - parent.columnSpacing) / 2
}
Controls.TextField {
id: shuntChargingContactorDelayField
validator: IntValidator { bottom: 0; top: 65535 }
Layout.fillWidth: true
Layout.maximumWidth: (parent.width - parent.columnSpacing) / 2
}
Controls.LineSeparator {
Layout.fillWidth: true
Layout.columnSpan: 2
}
RowLayout {
spacing: 20
Controls.LabelWithBackground {
text: qsTr("# 3")
Layout.preferredWidth: outputSettingsFrame.outputNumberSize
Layout.preferredHeight: outputSettingsFrame.outputNumberSize
}
Controls.CheckBox {
id: coolingOutputCheckBox
text: qsTr("Cooling activation")
Layout.fillWidth: true
Layout.preferredHeight: outputSettingsFrame.outputNumberSize
}
Layout.fillWidth: true
Layout.columnSpan: 2
}
Controls.SubtitleLabel {
text: qsTr("Closes at t<, °C")
Layout.fillWidth: true
Layout.maximumWidth: (parent.width - parent.columnSpacing) / 2
}
Controls.SubtitleLabel {
text: qsTr("Opens at t>, °C")
Layout.fillWidth: true
Layout.maximumWidth: (parent.width - parent.columnSpacing) / 2
}
Controls.TextField {
id: coolingStartThresholdField
validator: IntValidator { bottom: -32768; top: 32768 }
Layout.fillWidth: true
Layout.maximumWidth: (parent.width - parent.columnSpacing) / 2
}
Controls.TextField {
id: coolingStopThresholdField
validator: IntValidator { bottom: -32768; top: 32768 }
Layout.fillWidth: true
Layout.maximumWidth: (parent.width - parent.columnSpacing) / 2
}
Controls.LineSeparator {
Layout.fillWidth: true
Layout.columnSpan: 2
}
RowLayout {
spacing: 20
Controls.LabelWithBackground {
text: qsTr("# 4")
Layout.preferredWidth: outputSettingsFrame.outputNumberSize
Layout.preferredHeight: outputSettingsFrame.outputNumberSize
}
Controls.CheckBox {
id: heatingOutputCheckBox
text: qsTr("Heating activation")
Layout.fillWidth: true
Layout.preferredHeight: outputSettingsFrame.outputNumberSize
}
Layout.fillWidth: true
Layout.columnSpan: 2
}
Controls.SubtitleLabel {
text: qsTr("Closes at t<, °C")
Layout.fillWidth: true
Layout.maximumWidth: (parent.width - parent.columnSpacing) / 2
}
Controls.SubtitleLabel {
text: qsTr("Opens at t>, °C")
Layout.fillWidth: true
Layout.maximumWidth: (parent.width - parent.columnSpacing) / 2
}
Controls.TextField {
id: heatingStartThresholdField
validator: IntValidator { bottom: -32768; top: 32768 }
Layout.fillWidth: true
Layout.maximumWidth: (parent.width - parent.columnSpacing) / 2
}
Controls.TextField {
id: heatingStopThresholdField
validator: IntValidator { bottom: -32768; top: 32768 }
Layout.fillWidth: true
Layout.maximumWidth: (parent.width - parent.columnSpacing) / 2
}
Controls.LineSeparator {
Layout.fillWidth: true
Layout.columnSpan: 2
}
}
}
Controls.OutlineButton {
text: qsTr("Load settings from file")
onClicked: loadFileDialog.open()
Layout.preferredWidth: 270
FileDialog {
id: loadFileDialog
title: qsTr("Select configuration file")
folder: shortcuts.documents
nameFilters: [ qsTr("Configuration files (*.xml)"), qsTr("All files (*)") ]
onAccepted: {
let result = BmsInterface.bmsConfig().loadXml(loadFileDialog.fileUrl.toString().replace(/^(file:\/{3})/, ""), "bmsConfiguration")
if (!result) {
BmsInterface.emitStatusMessage(BmsInterface.bmsConfig().xmlStatus(), false)
}
}
}
Settings {
category: "loadConfiguration"
property alias folder: loadFileDialog.folder
}
}
Controls.OutlineButton {
text: qsTr("Save settings to file")
onClicked: saveFileDialog.open()
Layout.preferredWidth: 270
FileDialog {
id: saveFileDialog
title: qsTr("Select configuration file")
selectExisting: false
folder: shortcuts.documents
nameFilters: [ qsTr("Configuration files (*.xml)"), qsTr("All files (*)") ]
onAccepted: {
let result = BmsInterface.bmsConfig().saveXml(saveFileDialog.fileUrl.toString().replace(/^(file:\/{3})/, ""), "bmsConfiguration")
if (!result) {
BmsInterface.emitStatusMessage(BmsInterface.bmsConfig().xmlStatus(), false)
} else {
BmsInterface.emitStatusMessage(qsTr("BMS configuration saved to file"), true)
}
}
}
Settings {
category: "saveConfiguration"
property alias folder: saveFileDialog.folder
}
}
}
ScrollBar.vertical: Controls.ScrollBar {}
Layout.fillWidth: true
Layout.fillHeight: true
}
ColumnLayout {
spacing: contentRowSpacing
Controls.LinkLabel {
text: qsTr("Serial number")
onClicked: settingsFlickable.contentY = serialNumberSettingsFrame.mapToItem(settingsFlickable.contentItem, 0, 0).y
}
Controls.LinkLabel {
text: qsTr("Configuration")
onClicked: settingsFlickable.contentY = configurationSettingsFrame.mapToItem(settingsFlickable.contentItem, 0, 0).y
}
Controls.LinkLabel {
text: qsTr("SOC")
onClicked: settingsFlickable.contentY = socSettingsFrame.mapToItem(settingsFlickable.contentItem, 0, 0).y
}
Controls.LinkLabel {
text: qsTr("Limits")
onClicked: settingsFlickable.contentY = limitSettingsFrame.mapToItem(settingsFlickable.contentItem, 0, 0).y
}
Controls.LinkLabel {
text: qsTr("Cell configuration")
onClicked: settingsFlickable.contentY = cellSettingsFrame.mapToItem(settingsFlickable.contentItem, 0, 0).y
}
Controls.LinkLabel {
text: qsTr("Balancing configuration")
onClicked: settingsFlickable.contentY = balancingSettingsFrame.mapToItem(settingsFlickable.contentItem, 0, 0).y
}
Controls.LinkLabel {
text: qsTr("Current configuration")
onClicked: settingsFlickable.contentY = currentConfigurationFrame.mapToItem(settingsFlickable.contentItem, 0, 0).y
}
Controls.LinkLabel {
text: qsTr("Output settings")
onClicked: {
settingsFlickable.contentY = outputSettingsFrame.mapToItem(settingsFlickable.contentItem, 0, 0).y
settingsFlickable.returnToBounds()
}
}
Item {
Layout.fillHeight: true
}
ColumnLayout {
spacing: 15
Controls.OutlineButton {
text: qsTr("Read default settings")
Layout.fillWidth: true
onClicked: if (BmsInterface.isPortConnected()) {
BmsInterface.commands().getBMSconfDefault()
}
}
Controls.OutlineButton {
text: qsTr("Read current settings from BMS")
Layout.fillWidth: true
onClicked: if (BmsInterface.isPortConnected()) {
BmsInterface.commands().getBMSconf()
}
}
Controls.OutlineButton {
id: writeBmsConfigurationButton
text: qsTr("Write current values to BMS")
Layout.fillWidth: true
onClicked: if (BmsInterface.isPortConnected()) {
writeValuesToConfig()
BmsInterface.commands().setBMSconf()
}
}
Controls.Button {
id: storeBmsConfigurationButton
text: qsTr("Write to non-volatile memory of BMS")
Layout.fillWidth: true
onClicked: if (BmsInterface.isPortConnected()) {
needWait(true, qsTr("The settings are written to non-volatile memory.\nWait, please."))
writeValuesToConfig()
BmsInterface.commands().storeBMSConfig()
}
}
Layout.fillWidth: true
}
Layout.maximumWidth: 280
Layout.fillHeight: true
}
function writeValuesToConfig() {
BmsInterface.bmsConfig().setParamValue("notUsedCurrentThreshold", parseFloat(serialNumberField.text))
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))
BmsInterface.bmsConfig().setParamValue("maxAllowedCurrent", parseFloat(maximumChargeCurrentField.text))
BmsInterface.bmsConfig().setParamValue("maxMismatchThreshold", parseFloat(maximumLoadCurrentField.text))
BmsInterface.bmsConfig().setParamValue("allowedTempBattChargingMax", parseFloat(maximumTemperatureField.text))
BmsInterface.bmsConfig().setParamValue("cellHardUnderVoltage", parseFloat(lowerDisableThresholdField.text))
BmsInterface.bmsConfig().setParamValue("cellHardOverVoltage", parseFloat(upperDisableThresholdField.text))
BmsInterface.bmsConfig().setParamValue("cellLCSoftUnderVoltage", parseFloat(lowerEnableThresholdField.text))
BmsInterface.bmsConfig().setParamValue("cellSoftOverVoltage", parseFloat(upperEnableThresholdField.text))
BmsInterface.bmsConfig().setParamValue("cellBalanceStart", parseFloat(balancingStartVoltageField.text))
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)
BmsInterface.bmsConfig().setParamValue("brushOrShuntOutputChecked", brushOrShuntOutputCheckBox.checked)
BmsInterface.bmsConfig().setParamValue("brushOrShuntMode", shuntChargingContactorRadioButton.checked)
BmsInterface.bmsConfig().setParamValue("brushUsageSocThreshold", parseInt(brushUsageSocThresholdField.text))
BmsInterface.bmsConfig().setParamValue("shuntChargingContactorDelay", parseInt(shuntChargingContactorDelayField.text))
BmsInterface.bmsConfig().setParamValue("coolingOutputChecked", coolingOutputCheckBox.checked)
BmsInterface.bmsConfig().setParamValue("coolingStartThreshold", parseInt(coolingStartThresholdField.text))
BmsInterface.bmsConfig().setParamValue("coolingStopThreshold", parseInt(coolingStopThresholdField.text))
BmsInterface.bmsConfig().setParamValue("heatingOutputChecked", heatingOutputCheckBox.checked)
BmsInterface.bmsConfig().setParamValue("heatingStartThreshold", parseInt(heatingStartThresholdField.text))
BmsInterface.bmsConfig().setParamValue("heatingStopThreshold", parseInt(heatingStopThresholdField.text))
}
Connections {
target: BmsInterface.bmsConfig()
onUpdated: {
serialNumberField.text = Number(BmsInterface.bmsConfig().getParamDouble("notUsedCurrentThreshold")).toFixed()
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"))
maximumChargeCurrentField.text = MathHelper.roundDouble(BmsInterface.bmsConfig().getParamDouble("maxAllowedCurrent"))
maximumLoadCurrentField.text = MathHelper.roundDouble(BmsInterface.bmsConfig().getParamDouble("maxMismatchThreshold"))
maximumTemperatureField.text = MathHelper.roundDouble(BmsInterface.bmsConfig().getParamDouble("allowedTempBattChargingMax"))
lowerDisableThresholdField.text = MathHelper.roundDouble(BmsInterface.bmsConfig().getParamDouble("cellHardUnderVoltage"))
upperDisableThresholdField.text = MathHelper.roundDouble(BmsInterface.bmsConfig().getParamDouble("cellHardOverVoltage"))
lowerEnableThresholdField.text = MathHelper.roundDouble(BmsInterface.bmsConfig().getParamDouble("cellLCSoftUnderVoltage"))
upperEnableThresholdField.text = MathHelper.roundDouble(BmsInterface.bmsConfig().getParamDouble("cellSoftOverVoltage"))
balancingStartVoltageField.text = MathHelper.roundDouble(BmsInterface.bmsConfig().getParamDouble("cellBalanceStart"))
balancingStartDeltaVoltageField.text = MathHelper.roundDouble(BmsInterface.bmsConfig().getParamDouble("cellBalanceDifferenceThreshold"))
balancingCellIntervalField.text = BmsInterface.bmsConfig().getParamInt("cellBalanceUpdateInterval")
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")
brushOrShuntOutputCheckBox.checked = BmsInterface.bmsConfig().getParamBool("brushOrShuntOutputChecked")
brushControlRadioButton.checked = !BmsInterface.bmsConfig().getParamBool("brushOrShuntMode")
shuntChargingContactorRadioButton.checked = BmsInterface.bmsConfig().getParamBool("brushOrShuntMode")
brushUsageSocThresholdField.text = BmsInterface.bmsConfig().getParamInt("brushUsageSocThreshold")
shuntChargingContactorDelayField.text = BmsInterface.bmsConfig().getParamInt("shuntChargingContactorDelay")
coolingOutputCheckBox.checked = BmsInterface.bmsConfig().getParamBool("coolingOutputChecked")
coolingStartThresholdField.text = BmsInterface.bmsConfig().getParamInt("coolingStartThreshold")
coolingStopThresholdField.text = BmsInterface.bmsConfig().getParamInt("coolingStopThreshold")
heatingOutputCheckBox.checked = BmsInterface.bmsConfig().getParamBool("heatingOutputChecked")
heatingStartThresholdField.text = BmsInterface.bmsConfig().getParamInt("heatingStartThreshold")
heatingStopThresholdField.text = BmsInterface.bmsConfig().getParamInt("heatingStopThreshold")
}
}
}