7import QGroundControl.FactControls
8import QGroundControl.Controls
9import QGroundControl.AutoPilotPlugins.PX4
11// Note: Only the _SOURCE parameter can be assumed to be always available. The remainder of the parameters
12// may or may not be available depending on the _SOURCE setting.
15 pageComponent: pageComponent
21 width: Math.max(availableWidth, innerColumn.width)
22 height: innerColumn.height
24 readonly property string _highlightPrefix: "<font color=\"" + qgcPal.warningText + "\">"
25 readonly property string _highlightSuffix: "</font>"
27 property int _textEditWidth: ScreenTools.defaultFontPixelWidth * 8
28 property Fact _uavcanEnable: controller.getParameterFact(-1, "UAVCAN_ENABLE", false)
29 property int _indexedBatteryParamCount: getIndexedBatteryParamCount()
31 function getIndexedBatteryParamCount() {
34 if (!controller.parameterExists(-1, "BAT#_SOURCE".replace("#", batteryIndex))) {
35 return batteryIndex - 1
41 PowerComponentController {
43 onOldFirmware: QGroundControl.showMessageDialog(powerPage, qsTr("ESC Calibration"), qsTr("%1 cannot perform ESC Calibration with this version of firmware. You will need to upgrade to a newer firmware.").arg(QGroundControl.appName))
44 onNewerFirmware: QGroundControl.showMessageDialog(powerPage, qsTr("ESC Calibration"), qsTr("%1 cannot perform ESC Calibration with this version of firmware. You will need to upgrade %1.").arg(QGroundControl.appName))
45 onDisconnectBattery: QGroundControl.showMessageDialog(powerPage, qsTr("ESC Calibration failed"), qsTr("You must disconnect the battery prior to performing ESC Calibration. Disconnect your battery and try again."))
46 onConnectBattery: escCalibrationDlgFactory.open()
51 anchors.horizontalCenter: parent.horizontalCenter
52 spacing: ScreenTools.defaultFontPixelHeight
54 function drawArrowhead(ctx, x, y, radians)
68 function drawLineWithArrow(ctx, x1, y1, x2, y2)
74 var rd = Math.atan((y2 - y1) / (x2 - x1));
75 rd += ((x2 > x1) ? 90 : -90) * Math.PI/180;
76 drawArrowhead(ctx, x2, y2, rd);
80 id: batterySetupRepeater
81 model: _indexedBatteryParamCount
84 sourceComponent: batterySetupComponent
86 property int batteryIndex: index + 1
87 property bool showBatteryIndex: batterySetupRepeater.count > 1
93 Layout.fillWidth: true
94 title: qsTr("ESC PWM Minimum and Maximum Calibration")
97 anchors.left: parent.left
98 anchors.right: parent.right
99 spacing: ScreenTools.defaultFontPixelWidth
102 color: qgcPal.warningText
103 wrapMode: Text.WordWrap
104 text: qsTr("WARNING: Propellers must be removed from vehicle prior to performing ESC calibration.")
105 Layout.fillWidth: true
109 text: qsTr("You must use USB connection for this operation.")
113 text: qsTr("Calibrate")
114 width: ScreenTools.defaultFontPixelWidth * 20
115 onClicked: controller.calibrateEsc()
122 text: qsTr("Show UAVCAN Settings")
123 checked: _uavcanEnable ? _uavcanEnable.rawValue !== 0 : false
127 Layout.fillWidth: true
128 title: qsTr("UAVCAN Bus Configuration")
129 visible: showUAVCAN.checked
133 spacing: ScreenTools.defaultFontPixelWidth
136 id: _uavcanEnabledCheckBox
137 width: ScreenTools.defaultFontPixelWidth * 20
143 anchors.verticalCenter: parent.verticalCenter
144 text: qsTr("Change required restart")
150 Layout.fillWidth: true
151 title: qsTr("UAVCAN Motor Index and Direction Assignment")
152 visible: showUAVCAN.checked
155 anchors.left: parent.left
156 anchors.right: parent.right
157 spacing: ScreenTools.defaultFontPixelWidth
160 wrapMode: Text.WordWrap
161 color: qgcPal.warningText
162 text: qsTr("WARNING: Propellers must be removed from vehicle prior to performing UAVCAN ESC configuration.")
163 Layout.fillWidth: true
167 wrapMode: Text.WordWrap
168 text: qsTr("ESC parameters will only be accessible in the editor after assignment.")
169 Layout.fillWidth: true
173 wrapMode: Text.WordWrap
174 text: qsTr("Start the process, then turn each motor into its turn direction, in the order of their motor indices.")
175 Layout.fillWidth: true
179 text: qsTr("Start Assignment")
180 width: ScreenTools.defaultFontPixelWidth * 20
181 onClicked: controller.startBusConfigureActuators()
185 text: qsTr("Stop Assignment")
186 width: ScreenTools.defaultFontPixelWidth * 20
187 onClicked: controller.stopBusConfigureActuators()
195 id: batterySetupComponent
198 Layout.fillWidth: true
199 title: qsTr("Battery ") + (showBatteryIndex ? batteryIndex : "")
201 property var _controller: controller
202 property int _batteryIndex: batteryIndex
206 controller: _controller
207 batteryIndex: _batteryIndex
210 property bool battNumCellsAvailable: batParams.battNumCellsAvailable
211 property bool battHighVoltAvailable: batParams.battHighVoltAvailable
212 property bool battLowVoltAvailable: batParams.battLowVoltAvailable
213 property bool battVoltLoadDropAvailable: batParams.battVoltLoadDropAvailable
214 property bool battVoltageDividerAvailable: batParams.battVoltageDividerAvailable
215 property bool battAmpsPerVoltAvailable: batParams.battAmpsPerVoltAvailable
217 property Fact battSource: batParams.battSource
218 property Fact battNumCells: batParams.battNumCells
219 property Fact battHighVolt: batParams.battHighVolt
220 property Fact battLowVolt: batParams.battLowVolt
221 property Fact battVoltLoadDrop: batParams.battVoltLoadDrop
222 property Fact battVoltageDivider: batParams.battVoltageDivider
223 property Fact battAmpsPerVolt: batParams.battAmpsPerVolt
225 function getBatteryImage() {
226 switch(battNumCells.value) {
227 case 1: return "/qmlimages/PowerComponentBattery_01cell.svg";
228 case 2: return "/qmlimages/PowerComponentBattery_02cell.svg"
229 case 3: return "/qmlimages/PowerComponentBattery_03cell.svg"
230 case 4: return "/qmlimages/PowerComponentBattery_04cell.svg"
231 case 5: return "/qmlimages/PowerComponentBattery_05cell.svg"
232 case 6: return "/qmlimages/PowerComponentBattery_06cell.svg"
233 default: return "/qmlimages/PowerComponentBattery_01cell.svg";
240 spacing: ScreenTools.defaultFontPixelWidth
241 visible: battSource.rawValue == -1
243 QGCLabel { text: qsTr("Source") }
245 width: _textEditWidth
255 columnSpacing: ScreenTools.defaultFontPixelWidth
256 visible: battSource.rawValue != -1
258 QGCLabel { text: qsTr("Source") }
260 width: _textEditWidth
271 sourceSize.height: height
272 fillMode: Image.PreserveAspectFit
276 source: getBatteryImage(batteryIndex)
277 visible: battNumCellsAvailable && battLowVoltAvailable && battHighVoltAvailable
283 Layout.columnSpan: battImage.visible ? 2 : 3
287 text: qsTr("Number of Cells (in Series)")
288 visible: battNumCellsAvailable
291 width: _textEditWidth
294 visible: battNumCellsAvailable
297 text: qsTr("Battery Max:")
298 visible: battImage.visible
301 text: visible ? (battNumCells.value * battHighVolt.value).toFixed(1) + ' V' : ""
302 visible: battImage.visible
308 visible: !battImage.visible
312 text: qsTr("Empty Voltage (per cell)")
313 visible: battLowVoltAvailable
316 width: _textEditWidth
319 visible: battLowVoltAvailable
322 text: qsTr("Battery Min:")
323 visible: battImage.visible
326 text: visible ? (battNumCells.value * battLowVolt.value).toFixed(1) + ' V' : ""
327 visible: battImage.visible
333 visible: battLowVoltAvailable && !battImage.visible
337 text: qsTr("Full Voltage (per cell)")
338 visible: battHighVoltAvailable
341 width: _textEditWidth
344 visible: battHighVoltAvailable
349 Layout.columnSpan: battImage.visible ? 2 : 3
350 visible: battHighVoltAvailable
354 text: qsTr("Voltage divider")
355 visible: battVoltageDividerAvailable
358 fact: battVoltageDivider
359 visible: battVoltageDividerAvailable
362 text: qsTr("Calculate")
363 visible: battVoltageDividerAvailable
364 onClicked: calcVoltageDividerDlgFactory.open({ batteryIndex: _batteryIndex })
366 Item { width: 1; height: 1; Layout.columnSpan: 2; visible: battVoltageDividerAvailable }
369 Layout.columnSpan: batteryGrid.columns
370 Layout.fillWidth: true
371 font.pointSize: ScreenTools.smallFontPointSize
372 wrapMode: Text.WordWrap
373 text: qsTr("If the battery voltage reported by the vehicle is largely different than the voltage read externally using a voltmeter you can adjust the voltage multiplier value to correct this. ") +
374 qsTr("Click the Calculate button for help with calculating a new value.")
375 visible: battVoltageDividerAvailable
378 text: qsTr("Amps per volt")
379 visible: battAmpsPerVoltAvailable
382 fact: battAmpsPerVolt
383 visible: battAmpsPerVoltAvailable
386 text: qsTr("Calculate")
387 visible: battAmpsPerVoltAvailable
388 onClicked: calcAmpsPerVoltDlgFactory.open({ batteryIndex: _batteryIndex })
390 Item { width: 1; height: 1; Layout.columnSpan: 2; visible: battAmpsPerVoltAvailable }
393 Layout.columnSpan: batteryGrid.columns
394 Layout.fillWidth: true
395 font.pointSize: ScreenTools.smallFontPointSize
396 wrapMode: Text.WordWrap
397 text: qsTr("If the current draw reported by the vehicle is largely different than the current read externally using a current meter you can adjust the amps per volt value to correct this. ") +
398 qsTr("Click the Calculate button for help with calculating a new value.")
399 visible: battAmpsPerVoltAvailable
404 Layout.columnSpan: batteryGrid.columns
405 text: qsTr("Show Advanced Settings")
406 visible: battVoltLoadDropAvailable
410 text: qsTr("Voltage Drop on Full Load (per cell)")
411 visible: showAdvanced.checked
415 fact: battVoltLoadDrop
417 visible: showAdvanced.checked
419 Item { width: 1; height: 1; Layout.columnSpan: 3; visible: showAdvanced.checked }
422 Layout.columnSpan: batteryGrid.columns
423 Layout.fillWidth: true
424 wrapMode: Text.WordWrap
425 font.pointSize: ScreenTools.smallFontPointSize
426 text: qsTr("Batteries show less voltage at high throttle. Enter the difference in Volts between idle throttle and full ") +
427 qsTr("throttle, divided by the number of battery cells. Leave at the default if unsure. ") +
428 _highlightPrefix + qsTr("If this value is set too high, the battery might be deep discharged and damaged.") + _highlightSuffix
429 visible: showAdvanced.checked
433 text: qsTr("Compensated Minimum Voltage:")
434 visible: showAdvanced.checked
437 text: visible ? ((battNumCells.value * battLowVolt.value) - (battNumCells.value * battVoltLoadDrop.value)).toFixed(1) + qsTr(" V") : ""
438 visible: showAdvanced.checked
440 Item { width: 1; height: 1; Layout.columnSpan: 3; visible: showAdvanced.checked }
443 } // QGCGroupBox - Battery settings
444 } // Component - batterySetupComponent
446 QGCPopupDialogFactory {
447 id: calcVoltageDividerDlgFactory
449 dialogComponent: calcVoltageDividerDlgComponent
453 id: calcVoltageDividerDlgComponent
456 title: qsTr("Calculate Voltage Divider")
457 buttons: Dialog.Close
459 property alias batteryIndex: batParams.batteryIndex
461 property var _controller: controller
462 property FactGroup _batteryFactGroup: controller.vehicle.getFactGroup("battery" + (batteryIndex - 1))
466 controller: _controller
470 spacing: ScreenTools.defaultFontPixelHeight
473 Layout.preferredWidth: gridLayout.width
474 wrapMode: Text.WordWrap
475 text: qsTr("Measure battery voltage using an external voltmeter and enter the value below. Click Calculate to set the new voltage multiplier.")
482 QGCLabel { text: qsTr("Measured voltage:") }
483 QGCTextField { id: measuredVoltage; numericValuesOnly: true }
485 QGCLabel { text: qsTr("Vehicle voltage:") }
486 QGCLabel { text: _batteryFactGroup.voltage.valueString }
488 QGCLabel { text: qsTr("Voltage divider:") }
489 FactLabel { fact: batParams.battVoltageDivider }
493 text: qsTr("Calculate")
496 var measuredVoltageValue = parseFloat(measuredVoltage.text)
497 if (measuredVoltageValue === 0 || isNaN(measuredVoltageValue)) {
500 var newVoltageDivider = (measuredVoltageValue * batParams.battVoltageDivider.value) / _batteryFactGroup.voltage.value
501 if (newVoltageDivider > 0) {
502 batParams.battVoltageDivider.value = newVoltageDivider
510 QGCPopupDialogFactory {
511 id: calcAmpsPerVoltDlgFactory
513 dialogComponent: calcAmpsPerVoltDlgComponent
517 id: calcAmpsPerVoltDlgComponent
520 title: qsTr("Calculate Amps per Volt")
521 buttons: Dialog.Close
523 property alias batteryIndex: batParams.batteryIndex
525 property var _controller: controller
526 property FactGroup _batteryFactGroup: controller.vehicle.getFactGroup("battery" + (batteryIndex - 1))
530 controller: _controller
534 spacing: ScreenTools.defaultFontPixelHeight
537 Layout.preferredWidth: gridLayout.width
538 wrapMode: Text.WordWrap
539 text: qsTr("Measure current draw using an external current meter and enter the value below. Click Calculate to set the new amps per volt value.")
546 QGCLabel { text: qsTr("Measured current:") }
547 QGCTextField { id: measuredCurrent; numericValuesOnly: true }
549 QGCLabel { text: qsTr("Vehicle current:") }
550 QGCLabel { text: _batteryFactGroup.current.valueString }
552 QGCLabel { text: qsTr("Amps per volt:") }
553 FactLabel { fact: batParams.battAmpsPerVolt }
557 text: qsTr("Calculate")
560 var measuredCurrentValue = parseFloat(measuredCurrent.text)
561 if (measuredCurrentValue === 0 || isNaN(measuredCurrentValue)) {
564 var newAmpsPerVolt = (measuredCurrentValue * batParams.battAmpsPerVolt.value) / _batteryFactGroup.current.value
565 if (newAmpsPerVolt != 0) {
566 batParams.battAmpsPerVolt.value = newAmpsPerVolt
574 QGCPopupDialogFactory {
575 id: escCalibrationDlgFactory
577 dialogComponent: escCalibrationDlgComponent
581 id: escCalibrationDlgComponent
584 id: escCalibrationDlg
585 title: qsTr("ESC Calibration")
587 acceptButtonEnabled: false
592 onBatteryConnected: textLabel.text = qsTr("Performing calibration. This will take a few seconds..")
593 onCalibrationFailed: { escCalibrationDlg.acceptButtonEnabled = true; textLabel.text = _highlightPrefix + qsTr("ESC Calibration failed. ") + _highlightSuffix + errorMessage }
594 onCalibrationSuccess: { escCalibrationDlg.acceptButtonEnabled = true; textLabel.text = qsTr("Calibration complete. You can disconnect your battery now if you like.") }
600 wrapMode: Text.WordWrap
601 text: _highlightPrefix + qsTr("WARNING: Props must be removed from vehicle prior to performing ESC calibration.") + _highlightSuffix + qsTr(" Connect the battery now and calibration will begin.")
602 Layout.fillWidth: true
603 Layout.maximumWidth: mainWindow.width / 2