667 lines
25 KiB
QML
667 lines
25 KiB
QML
import QtQuick 2.12
|
|
import QtQuick.Controls 2.12
|
|
import QtQuick.Layouts 1.12
|
|
|
|
import Controls 1.0 as Controls
|
|
import Cubo 1.0
|
|
|
|
RowLayout {
|
|
property real contentPadding: 35
|
|
property real contentRowSpacing: 20
|
|
property real contentColumnSpacing: 35
|
|
|
|
spacing: contentColumnSpacing
|
|
|
|
Flickable {
|
|
id: settingsFlickable
|
|
clip: true
|
|
contentHeight: configLayout.height
|
|
|
|
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
|
|
Layout.fillWidth: true
|
|
Layout.maximumWidth: (parent.width - parent.spacing) / 2
|
|
}
|
|
}
|
|
}
|
|
|
|
Controls.Frame {
|
|
id: configurationSettingsFrame
|
|
padding: contentPadding
|
|
implicitWidth: parent.width
|
|
Layout.fillWidth: true
|
|
|
|
GridLayout {
|
|
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 {}
|
|
Layout.fillWidth: true
|
|
Layout.maximumWidth: (parent.width - parent.columnSpacing) / 2
|
|
}
|
|
|
|
Controls.TextField {
|
|
id: numberOfCellsField
|
|
validator: IntValidator {}
|
|
Layout.fillWidth: true
|
|
Layout.maximumWidth: (parent.width - parent.columnSpacing) / 2
|
|
}
|
|
}
|
|
}
|
|
|
|
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 {}
|
|
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")
|
|
Layout.fillWidth: true
|
|
Layout.maximumWidth: (parent.width - parent.columnSpacing) / 2
|
|
}
|
|
|
|
Controls.SubtitleLabel {
|
|
text: qsTr("Maximum load current, A")
|
|
Layout.fillWidth: true
|
|
Layout.maximumWidth: (parent.width - parent.columnSpacing) / 2
|
|
}
|
|
|
|
Controls.TextField {
|
|
id: maximumChargeCurrentField
|
|
validator: DoubleValidator {}
|
|
Layout.fillWidth: true
|
|
Layout.maximumWidth: (parent.width - parent.columnSpacing) / 2
|
|
}
|
|
|
|
Controls.TextField {
|
|
id: maximumLoadCurrentField
|
|
validator: DoubleValidator {}
|
|
Layout.fillWidth: true
|
|
Layout.maximumWidth: (parent.width - parent.columnSpacing) / 2
|
|
}
|
|
|
|
Controls.SubtitleLabel {
|
|
text: qsTr("Maximum temperature, °C")
|
|
Layout.fillWidth: true
|
|
Layout.maximumWidth: (parent.width - parent.columnSpacing) / 2
|
|
Layout.columnSpan: 2
|
|
}
|
|
|
|
Controls.TextField {
|
|
id: maximumTemperatureField
|
|
validator: DoubleValidator {}
|
|
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 shutdown threshold, V")
|
|
Layout.fillWidth: true
|
|
Layout.maximumWidth: (parent.width - parent.columnSpacing) / 2
|
|
}
|
|
|
|
Controls.SubtitleLabel {
|
|
text: qsTr("Upper shutdown threshold, V")
|
|
Layout.fillWidth: true
|
|
Layout.maximumWidth: (parent.width - parent.columnSpacing) / 2
|
|
}
|
|
|
|
Controls.TextField {
|
|
id: lowerShutdownThresholdField
|
|
validator: DoubleValidator {}
|
|
Layout.fillWidth: true
|
|
Layout.maximumWidth: (parent.width - parent.columnSpacing) / 2
|
|
}
|
|
|
|
Controls.TextField {
|
|
id: upperShutdownThresholdField
|
|
validator: DoubleValidator {}
|
|
Layout.fillWidth: true
|
|
Layout.maximumWidth: (parent.width - parent.columnSpacing) / 2
|
|
}
|
|
|
|
// TODO
|
|
// Controls.SubtitleLabel {
|
|
// text: qsTr("Lower shutdown threshold, V")
|
|
// Layout.fillWidth: true
|
|
// Layout.maximumWidth: (parent.width - parent.columnSpacing) / 2
|
|
// }
|
|
|
|
// Controls.SubtitleLabel {
|
|
// text: qsTr("Upper shutdown threshold, V")
|
|
// Layout.fillWidth: true
|
|
// Layout.maximumWidth: (parent.width - parent.columnSpacing) / 2
|
|
// }
|
|
|
|
// Controls.TextField {
|
|
// id: lowerShutdownThresholdField
|
|
// Layout.fillWidth: true
|
|
// Layout.maximumWidth: (parent.width - parent.columnSpacing) / 2
|
|
// }
|
|
|
|
// Controls.TextField {
|
|
// id: upperShutdownThresholdField
|
|
// 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 {}
|
|
Layout.fillWidth: true
|
|
Layout.maximumWidth: (parent.width - parent.columnSpacing) / 2
|
|
}
|
|
|
|
Controls.TextField {
|
|
id: balancingStartDeltaVoltageField
|
|
validator: DoubleValidator {}
|
|
Layout.fillWidth: true
|
|
Layout.maximumWidth: (parent.width - parent.columnSpacing) / 2
|
|
}
|
|
}
|
|
}
|
|
|
|
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 {
|
|
text: qsTr("Use for management")
|
|
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 {
|
|
text: qsTr("Normally closed")
|
|
Layout.fillWidth: true
|
|
Layout.preferredHeight: outputSettingsFrame.outputNumberSize
|
|
}
|
|
|
|
Layout.fillWidth: true
|
|
Layout.columnSpan: 2
|
|
}
|
|
|
|
Controls.SubtitleLabel {
|
|
text: qsTr("Change in value during SOC")
|
|
Layout.fillWidth: true
|
|
Layout.maximumWidth: (parent.width - parent.columnSpacing) / 2
|
|
Layout.columnSpan: 2
|
|
}
|
|
|
|
Controls.TextField {
|
|
id: changeValueSocField
|
|
Layout.fillWidth: true
|
|
Layout.maximumWidth: (parent.width - parent.columnSpacing) / 2
|
|
Layout.columnSpan: 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 {
|
|
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: closesBelowTemperatureThirdField
|
|
Layout.fillWidth: true
|
|
Layout.maximumWidth: (parent.width - parent.columnSpacing) / 2
|
|
}
|
|
|
|
Controls.TextField {
|
|
id: opensGreaterTemperatureThirdField
|
|
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 {
|
|
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: closesBelowTemperatureFourthField
|
|
Layout.fillWidth: true
|
|
Layout.maximumWidth: (parent.width - parent.columnSpacing) / 2
|
|
}
|
|
|
|
Controls.TextField {
|
|
id: opensGreaterTemperatureFourthField
|
|
Layout.fillWidth: true
|
|
Layout.maximumWidth: (parent.width - parent.columnSpacing) / 2
|
|
}
|
|
|
|
Controls.LineSeparator {
|
|
Layout.fillWidth: true
|
|
Layout.columnSpan: 2
|
|
}
|
|
}
|
|
}
|
|
|
|
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 {}
|
|
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
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
ScrollBar.vertical: Controls.ScrollBar {
|
|
// policy: ScrollBar.AlwaysOn
|
|
}
|
|
|
|
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("Output settings")
|
|
onClicked: settingsFlickable.contentY = outputSettingsFrame.mapToItem(settingsFlickable.contentItem, 0, 0).y
|
|
}
|
|
|
|
Controls.LinkLabel {
|
|
text: qsTr("Current sensor value «0»")
|
|
onClicked: settingsFlickable.contentY = zeroSensorSettingsFrame.mapToItem(settingsFlickable.contentItem, 0, 0).y
|
|
}
|
|
|
|
Item {
|
|
Layout.fillHeight: true
|
|
}
|
|
|
|
ColumnLayout {
|
|
spacing: 15
|
|
|
|
Controls.OutlineButton {
|
|
text: qsTr("Read settings from file")
|
|
Layout.fillWidth: true
|
|
onClicked: BmsInterface.commands().getBMSconfDefault()
|
|
}
|
|
|
|
Controls.OutlineButton {
|
|
text: qsTr("Read current settings from BMS")
|
|
Layout.fillWidth: true
|
|
onClicked: BmsInterface.commands().getBMSconf()
|
|
}
|
|
|
|
Controls.OutlineButton {
|
|
text: qsTr("Write to non-volatile memory of BMS")
|
|
Layout.fillWidth: true
|
|
}
|
|
|
|
Controls.Button {
|
|
text: qsTr("Write current values to BMS")
|
|
Layout.fillWidth: true
|
|
}
|
|
|
|
Layout.fillWidth: true
|
|
}
|
|
|
|
Layout.maximumWidth: 320
|
|
Layout.fillHeight: true
|
|
}
|
|
|
|
Connections {
|
|
target: BmsInterface.bmsConfig()
|
|
onUpdated: {
|
|
serialNumberField.text = BmsInterface.bmsConfig().getParamDouble("notUsedCurrentThreshold")
|
|
|
|
numberOfBoardsField.text = BmsInterface.bmsConfig().getParamInt("cellMonitorICCount")
|
|
numberOfCellsField.text = BmsInterface.bmsConfig().getParamInt("noOfCellsSeries")
|
|
|
|
numberOfParallelCellsField.text = BmsInterface.bmsConfig().getParamInt("noOfCellsParallel")
|
|
batteryCapacityField.text = BmsInterface.bmsConfig().getParamDouble("batteryCapacity")
|
|
|
|
maximumChargeCurrentField.text = BmsInterface.bmsConfig().getParamDouble("maxAllowedCurrent")
|
|
maximumLoadCurrentField.text = BmsInterface.bmsConfig().getParamDouble("maxMismatchThreshold")
|
|
maximumTemperatureField.text = BmsInterface.bmsConfig().getParamDouble("allowedTempBattChargingMax")
|
|
|
|
// TODO
|
|
lowerShutdownThresholdField.text = BmsInterface.bmsConfig().getParamDouble("cellHardUnderVoltage")
|
|
upperShutdownThresholdField.text = BmsInterface.bmsConfig().getParamDouble("cellHardOverVoltage")
|
|
|
|
// TODO
|
|
balancingStartVoltageField.text = BmsInterface.bmsConfig().getParamDouble("cellBalanceStart")
|
|
balancingStartDeltaVoltageField.text = BmsInterface.bmsConfig().getParamDouble("cellBalanceDifferenceThreshold")
|
|
|
|
zeroSensorValueField.text = BmsInterface.bmsConfig().getParamDouble("shuntLCFactor")
|
|
}
|
|
}
|
|
|
|
Connections {
|
|
target: BmsInterface
|
|
onPortConnectedChanged: getValues()
|
|
}
|
|
|
|
onVisibleChanged: getValues()
|
|
|
|
function getValues() {
|
|
if (BmsInterface.isPortConnected() && visible) {
|
|
BmsInterface.bmsConfig().updateDone()
|
|
}
|
|
}
|
|
}
|