QGroundControl
Ground Control Station for MAVLink Drones
Loading...
Searching...
No Matches
APMPowerComponent.qml
Go to the documentation of this file.
1import QtQuick
2import QtQuick.Controls
3import QtQuick.Dialogs
4import QtQuick.Layouts
5
6import QGroundControl
7import QGroundControl.FactControls
8import QGroundControl.Controls
9
10SetupPage {
11 id: powerPage
12 pageComponent: powerPageComponent
13
14 FactPanelController {
15 id: controller
16 }
17
18 Component {
19 id: powerPageComponent
20
21 Flow {
22 id: flowLayout
23 width: availableWidth
24 spacing: _margins
25
26 property Fact _batt1Monitor: controller.getParameterFact(-1, "BATT_MONITOR")
27 property Fact _batt2Monitor: controller.getParameterFact(-1, "BATT2_MONITOR", false /* reportMissing */)
28 property bool _batt2MonitorAvailable: controller.parameterExists(-1, "BATT2_MONITOR")
29 property bool _batt1MonitorEnabled: _batt1Monitor.rawValue !== 0
30 property bool _batt2MonitorEnabled: _batt2MonitorAvailable && _batt2Monitor.rawValue !== 0
31 property bool _batt1ParamsAvailable: controller.parameterExists(-1, "BATT_CAPACITY")
32 property bool _batt2ParamsAvailable: controller.parameterExists(-1, "BATT2_CAPACITY")
33 property bool _showBatt1Reboot: _batt1MonitorEnabled && !_batt1ParamsAvailable
34 property bool _showBatt2Reboot: _batt2MonitorEnabled && !_batt2ParamsAvailable
35 property bool _escCalibrationAvailable: controller.parameterExists(-1, "ESC_CALIBRATION")
36 property Fact _escCalibration: controller.getParameterFact(-1, "ESC_CALIBRATION", false /* reportMissing */)
37
38 property string _restartRequired: qsTr("Requires vehicle reboot")
39
40 QGCPalette { id: ggcPal; colorGroupEnabled: true }
41
42 // Battery1 Monitor settings only - used when only monitor param is available
43 Column {
44 spacing: _margins / 2
45 visible: !_batt1MonitorEnabled || !_batt1ParamsAvailable
46
47 QGCLabel {
48 text: qsTr("Battery 1")
49 font.bold: true
50 }
51
52 Rectangle {
53 width: batt1Column.x + batt1Column.width + _margins
54 height: batt1Column.y + batt1Column.height + _margins
55 color: ggcPal.windowShade
56
57 ColumnLayout {
58 id: batt1Column
59 anchors.margins: _margins
60 anchors.top: parent.top
61 anchors.left: parent.left
62 spacing: ScreenTools.defaultFontPixelWidth
63
64 RowLayout {
65 id: batt1MonitorRow
66 spacing: ScreenTools.defaultFontPixelWidth
67
68 QGCLabel { text: qsTr("Battery1 monitor:") }
69 FactComboBox {
70 id: monitor1Combo
71 fact: _batt1Monitor
72 indexModel: false
73 sizeToContents: true
74 }
75 }
76
77 QGCLabel {
78 text: _restartRequired
79 visible: _showBatt1Reboot
80 }
81
82 QGCButton {
83 text: qsTr("Reboot vehicle")
84 visible: _showBatt1Reboot
85 onClicked: controller.vehicle.rebootVehicle()
86 }
87 }
88 }
89 }
90
91 // Battery 1 settings
92 Column {
93 id: _batt1FullSettings
94 spacing: _margins / 2
95 visible: _batt1MonitorEnabled && _batt1ParamsAvailable
96
97 QGCLabel {
98 text: qsTr("Battery 1")
99 font.bold: true
100 }
101
102 Rectangle {
103 width: battery1Loader.x + battery1Loader.width + _margins
104 height: battery1Loader.y + battery1Loader.height + _margins
105 color: ggcPal.windowShade
106
107 Loader {
108 id: battery1Loader
109 anchors.margins: _margins
110 anchors.top: parent.top
111 anchors.left: parent.left
112 sourceComponent: _batt1FullSettings.visible ? powerSetupComponent : undefined
113
114 property Fact armVoltMin: controller.getParameterFact(-1, "r.BATT_ARM_VOLT", false /* reportMissing */)
115 property Fact battAmpPerVolt: controller.getParameterFact(-1, "r.BATT_AMP_PERVLT", false /* reportMissing */)
116 property Fact battAmpOffset: controller.getParameterFact(-1, "BATT_AMP_OFFSET", false /* reportMissing */)
117 property Fact battCapacity: controller.getParameterFact(-1, "BATT_CAPACITY", false /* reportMissing */)
118 property Fact battCurrPin: controller.getParameterFact(-1, "BATT_CURR_PIN", false /* reportMissing */)
119 property Fact battMonitor: controller.getParameterFact(-1, "BATT_MONITOR", false /* reportMissing */)
120 property Fact battVoltMult: controller.getParameterFact(-1, "BATT_VOLT_MULT", false /* reportMissing */)
121 property Fact battVoltPin: controller.getParameterFact(-1, "BATT_VOLT_PIN", false /* reportMissing */)
122 property FactGroup _batteryFactGroup: _batt1FullSettings.visible ? controller.vehicle.getFactGroup("battery0") : null
123 property Fact vehicleVoltage: _batteryFactGroup ? _batteryFactGroup.voltage : null
124 property Fact vehicleCurrent: _batteryFactGroup ? _batteryFactGroup.current : null
125 }
126 }
127 }
128
129 // Battery2 Monitor settings only - used when only monitor param is available
130 Column {
131 spacing: _margins / 2
132 visible: !_batt2MonitorEnabled || !_batt2ParamsAvailable
133
134 QGCLabel {
135 text: qsTr("Battery 2")
136 font.bold: true
137 }
138
139 Rectangle {
140 width: batt2Column.x + batt2Column.width + _margins
141 height: batt2Column.y + batt2Column.height + _margins
142 color: ggcPal.windowShade
143
144 ColumnLayout {
145 id: batt2Column
146 anchors.margins: _margins
147 anchors.top: parent.top
148 anchors.left: parent.left
149 spacing: ScreenTools.defaultFontPixelWidth
150
151 RowLayout {
152 id: batt2MonitorRow
153 spacing: ScreenTools.defaultFontPixelWidth
154
155 QGCLabel { text: qsTr("Battery2 monitor:") }
156 FactComboBox {
157 id: monitor2Combo
158 fact: _batt2Monitor
159 indexModel: false
160 sizeToContents: true
161 }
162 }
163
164 QGCLabel {
165 text: _restartRequired
166 visible: _showBatt2Reboot
167 }
168
169 QGCButton {
170 text: qsTr("Reboot vehicle")
171 visible: _showBatt2Reboot
172 onClicked: controller.vehicle.rebootVehicle()
173 }
174 }
175 }
176 }
177
178 // Battery 2 settings - Used when full params are available
179 Column {
180 id: batt2FullSettings
181 spacing: _margins / 2
182 visible: _batt2MonitorEnabled && _batt2ParamsAvailable
183
184 QGCLabel {
185 text: qsTr("Battery 2")
186 font.bold: true
187 }
188
189 Rectangle {
190 width: battery2Loader.x + battery2Loader.width + _margins
191 height: battery2Loader.y + battery2Loader.height + _margins
192 color: ggcPal.windowShade
193
194 Loader {
195 id: battery2Loader
196 anchors.margins: _margins
197 anchors.top: parent.top
198 anchors.left: parent.left
199 sourceComponent: batt2FullSettings.visible ? powerSetupComponent : undefined
200
201 property Fact armVoltMin: controller.getParameterFact(-1, "r.BATT2_ARM_VOLT", false /* reportMissing */)
202 property Fact battAmpPerVolt: controller.getParameterFact(-1, "r.BATT2_AMP_PERVLT", false /* reportMissing */)
203 property Fact battAmpOffset: controller.getParameterFact(-1, "BATT2_AMP_OFFSET", false /* reportMissing */)
204 property Fact battCapacity: controller.getParameterFact(-1, "BATT2_CAPACITY", false /* reportMissing */)
205 property Fact battCurrPin: controller.getParameterFact(-1, "BATT2_CURR_PIN", false /* reportMissing */)
206 property Fact battMonitor: controller.getParameterFact(-1, "BATT2_MONITOR", false /* reportMissing */)
207 property Fact battVoltMult: controller.getParameterFact(-1, "BATT2_VOLT_MULT", false /* reportMissing */)
208 property Fact battVoltPin: controller.getParameterFact(-1, "BATT2_VOLT_PIN", false /* reportMissing */)
209 property FactGroup _batteryFactGroup: batt2FullSettings.visible ? controller.vehicle.getFactGroup("battery1") : null
210 property Fact vehicleVoltage: _batteryFactGroup ? _batteryFactGroup.voltage : null
211 property Fact vehicleCurrent: _batteryFactGroup ? _batteryFactGroup.current : null
212 }
213 }
214 }
215
216 Column {
217 spacing: _margins / 2
218 visible: _escCalibrationAvailable
219
220 QGCLabel {
221 text: qsTr("ESC Calibration")
222 font.bold: true
223 }
224
225 Rectangle {
226 width: escCalibrationHolder.x + escCalibrationHolder.width + _margins
227 height: escCalibrationHolder.y + escCalibrationHolder.height + _margins
228 color: ggcPal.windowShade
229
230 Column {
231 id: escCalibrationHolder
232 x: _margins
233 y: _margins
234 spacing: _margins
235
236 Column {
237 spacing: _margins
238
239 QGCLabel {
240 text: qsTr("WARNING: Remove props prior to calibration!")
241 color: qgcPal.warningText
242 }
243
244 Row {
245 spacing: _margins
246
247 QGCButton {
248 text: qsTr("Calibrate")
249 enabled: _escCalibration && _escCalibration.rawValue === 0
250 onClicked: if(_escCalibration) _escCalibration.rawValue = 3
251 }
252
253 Column {
254 enabled: _escCalibration && _escCalibration.rawValue === 3
255 QGCLabel { text: _escCalibration ? (_escCalibration.rawValue === 3 ? qsTr("Now perform these steps:") : qsTr("Click Calibrate to start, then:")) : "" }
256 QGCLabel { text: qsTr("- Disconnect USB and battery so flight controller powers down") }
257 QGCLabel { text: qsTr("- Connect the battery") }
258 QGCLabel { text: qsTr("- The arming tone will be played (if the vehicle has a buzzer attached)") }
259 QGCLabel { text: qsTr("- If using a flight controller with a safety button press it until it displays solid red") }
260 QGCLabel { text: qsTr("- You will hear a musical tone then two beeps") }
261 QGCLabel { text: qsTr("- A few seconds later you should hear a number of beeps (one for each battery cell you're using)") }
262 QGCLabel { text: qsTr("- And finally a single long beep indicating the end points have been set and the ESC is calibrated") }
263 QGCLabel { text: qsTr("- Disconnect the battery and power up again normally") }
264 }
265 }
266 }
267 }
268 }
269 }
270 } // Flow
271 } // Component - powerPageComponent
272
273 Component {
274 id: powerSetupComponent
275
276 Column {
277 spacing: _margins
278
279 property real _margins: ScreenTools.defaultFontPixelHeight / 2
280 property bool _showAdvanced: sensorCombo.currentIndex === sensorModel.count - 1
281 property real _fieldWidth: ScreenTools.defaultFontPixelWidth * 25
282
283 Component.onCompleted: calcSensor()
284
285 function calcSensor() {
286 for (var i=0; i<sensorModel.count - 1; i++) {
287 if (sensorModel.get(i).voltPin === battVoltPin.value &&
288 sensorModel.get(i).currPin === battCurrPin.value &&
289 Math.abs(sensorModel.get(i).voltMult - battVoltMult.value) < 0.001 &&
290 Math.abs(sensorModel.get(i).ampPerVolt - battAmpPerVolt.value) < 0.0001 &&
291 Math.abs(sensorModel.get(i).ampOffset - battAmpOffset.value) < 0.0001) {
292 sensorCombo.currentIndex = i
293 return
294 }
295 }
296 sensorCombo.currentIndex = sensorModel.count - 1
297 }
298
299 QGCPalette { id: qgcPal; colorGroupEnabled: true }
300
301 ListModel {
302 id: sensorModel
303
304 ListElement {
305 text: qsTr("Power Module 90A")
306 voltPin: 2
307 currPin: 3
308 voltMult: 10.1
309 ampPerVolt: 17.0
310 ampOffset: 0
311 }
312
313 ListElement {
314 text: qsTr("Power Module HV")
315 voltPin: 2
316 currPin: 3
317 voltMult: 12.02
318 ampPerVolt: 39.877
319 ampOffset: 0
320 }
321
322 ListElement {
323 text: qsTr("3DR Iris")
324 voltPin: 2
325 currPin: 3
326 voltMult: 12.02
327 ampPerVolt: 17.0
328 ampOffset: 0
329 }
330
331 ListElement {
332 text: qsTr("Blue Robotics Power Sense Module")
333 voltPin: 2
334 currPin: 3
335 voltMult: 11.000
336 ampPerVolt: 37.8788
337 ampOffset: 0.330
338 }
339
340 ListElement {
341 text: qsTr("Navigator w/ Blue Robotics Power Sense Module")
342 voltPin: 5
343 currPin: 4
344 voltMult: 11.000
345 ampPerVolt: 37.8788
346 ampOffset: 0.330
347 }
348
349 ListElement {
350 text: qsTr("Other")
351 }
352 }
353
354
355 GridLayout {
356 columns: 3
357 rowSpacing: _margins
358 columnSpacing: _margins
359
360 QGCLabel { text: qsTr("Battery monitor:") }
361
362 FactComboBox {
363 id: monitorCombo
364 fact: battMonitor
365 indexModel: false
366 sizeToContents: true
367 }
368
369 QGCLabel {
370 Layout.row: 1
371 Layout.column: 0
372 text: qsTr("Battery capacity:")
373 }
374
375 FactTextField {
376 id: capacityField
377 width: _fieldWidth
378 fact: battCapacity
379 }
380
381 QGCLabel {
382 Layout.row: 2
383 Layout.column: 0
384 text: qsTr("Minimum arming voltage:")
385 }
386
387 FactTextField {
388 id: armVoltField
389 width: _fieldWidth
390 fact: armVoltMin
391 }
392
393 QGCLabel {
394 Layout.row: 3
395 Layout.column: 0
396 text: qsTr("Power sensor:")
397 }
398
399 QGCComboBox {
400 id: sensorCombo
401 Layout.minimumWidth: _fieldWidth
402 model: sensorModel
403 textRole: "text"
404
405 onActivated: (index) => {
406 if (index < sensorModel.count - 1) {
407 battVoltPin.value = sensorModel.get(index).voltPin
408 battCurrPin.value = sensorModel.get(index).currPin
409 battVoltMult.value = sensorModel.get(index).voltMult
410 battAmpPerVolt.value = sensorModel.get(index).ampPerVolt
411 battAmpOffset.value = sensorModel.get(index).ampOffset
412 } else {
413
414 }
415 }
416 }
417
418 QGCLabel {
419 Layout.row: 4
420 Layout.column: 0
421 text: qsTr("Current pin:")
422 visible: _showAdvanced
423 }
424
425 FactComboBox {
426 Layout.minimumWidth: _fieldWidth
427 fact: battCurrPin
428 indexModel: false
429 visible: _showAdvanced
430 sizeToContents: true
431 }
432
433 QGCLabel {
434 Layout.row: 5
435 Layout.column: 0
436 text: qsTr("Voltage pin:")
437 visible: _showAdvanced
438 }
439
440 FactComboBox {
441 Layout.minimumWidth: _fieldWidth
442 fact: battVoltPin
443 indexModel: false
444 visible: _showAdvanced
445 sizeToContents: true
446 }
447
448 QGCLabel {
449 Layout.row: 6
450 Layout.column: 0
451 text: qsTr("Voltage multiplier:")
452 visible: _showAdvanced
453 }
454
455 FactTextField {
456 width: _fieldWidth
457 fact: battVoltMult
458 visible: _showAdvanced
459 }
460
461 QGCButton {
462 text: qsTr("Calculate")
463 visible: _showAdvanced
464 onClicked: calcVoltageMultiplierDlgFactory.open({ vehicleVoltageFact: vehicleVoltage, battVoltMultFact: battVoltMult })
465 }
466
467 QGCLabel {
468 Layout.columnSpan: 3
469 Layout.fillWidth: true
470 font.pointSize: ScreenTools.smallFontPointSize
471 wrapMode: Text.WordWrap
472 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. Click the Calculate button for help with calculating a new value.")
473 visible: _showAdvanced
474 }
475
476 QGCLabel {
477 text: qsTr("Amps per volt:")
478 visible: _showAdvanced
479 }
480
481 FactTextField {
482 width: _fieldWidth
483 fact: battAmpPerVolt
484 visible: _showAdvanced
485 }
486
487 QGCButton {
488 text: qsTr("Calculate")
489 visible: _showAdvanced
490 onClicked: calcAmpsPerVoltDlgFactory.open({ vehicleCurrentFact: vehicleCurrent, battAmpPerVoltFact: battAmpPerVolt })
491 }
492
493 QGCLabel {
494 Layout.columnSpan: 3
495 Layout.fillWidth: true
496 font.pointSize: ScreenTools.smallFontPointSize
497 wrapMode: Text.WordWrap
498 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. Click the Calculate button for help with calculating a new value.")
499 visible: _showAdvanced
500 }
501
502 QGCLabel {
503 text: qsTr("Amps Offset:")
504 visible: _showAdvanced
505 }
506
507 FactTextField {
508 width: _fieldWidth
509 fact: battAmpOffset
510 visible: _showAdvanced
511 }
512
513 QGCLabel {
514 Layout.columnSpan: 3
515 Layout.fillWidth: true
516 font.pointSize: ScreenTools.smallFontPointSize
517 wrapMode: Text.WordWrap
518 text: qsTr("If the vehicle reports a high current read when there is little or no current going through it, adjust the Amps Offset. It should be equal to the voltage reported by the sensor when the current is zero.")
519 visible: _showAdvanced
520 }
521
522 } // GridLayout
523 } // Column
524 } // Component - powerSetupComponent
525
526 QGCPopupDialogFactory {
527 id: calcVoltageMultiplierDlgFactory
528
529 dialogComponent: calcVoltageMultiplierDlgComponent
530 }
531
532 Component {
533 id: calcVoltageMultiplierDlgComponent
534
535 QGCPopupDialog {
536 title: qsTr("Calculate Voltage Multiplier")
537 buttons: Dialog.Close
538
539 property Fact vehicleVoltageFact
540 property Fact battVoltMultFact
541
542 ColumnLayout {
543 spacing: ScreenTools.defaultFontPixelHeight
544
545 QGCLabel {
546 Layout.preferredWidth: gridLayout.width
547 wrapMode: Text.WordWrap
548 text: qsTr("Measure battery voltage using an external voltmeter and enter the value below. Click Calculate to set the new adjusted voltage multiplier.")
549 }
550
551 GridLayout {
552 id: gridLayout
553 columns: 2
554
555 QGCLabel {
556 text: qsTr("Measured voltage:")
557 }
558 QGCTextField { id: measuredVoltage }
559
560 QGCLabel { text: qsTr("Vehicle voltage:") }
561 FactLabel { fact: vehicleVoltageFact }
562
563 QGCLabel { text: qsTr("Voltage multiplier:") }
564 FactLabel { fact: battVoltMultFact }
565 }
566
567 QGCButton {
568 text: qsTr("Calculate And Set")
569
570 onClicked: {
571 var measuredVoltageValue = parseFloat(measuredVoltage.text)
572 if (measuredVoltageValue === 0 || isNaN(measuredVoltageValue) || !vehicleVoltageFact || !battVoltMultFact) {
573 return
574 }
575 var newVoltageMultiplier = (vehicleVoltageFact.value !== 0) ? (measuredVoltageValue * battVoltMultFact.value) / vehicleVoltageFact.value : 0
576 if (newVoltageMultiplier > 0) {
577 battVoltMultFact.value = newVoltageMultiplier
578 }
579 }
580 }
581 }
582 }
583 }
584
585 QGCPopupDialogFactory {
586 id: calcAmpsPerVoltDlgFactory
587
588 dialogComponent: calcAmpsPerVoltDlgComponent
589 }
590
591 Component {
592 id: calcAmpsPerVoltDlgComponent
593
594 QGCPopupDialog {
595 title: qsTr("Calculate Amps per Volt")
596 buttons: Dialog.Close
597
598 property Fact vehicleCurrentFact
599 property Fact battAmpPerVoltFact
600
601 ColumnLayout {
602 spacing: ScreenTools.defaultFontPixelHeight
603
604 QGCLabel {
605 Layout.preferredWidth: gridLayout.width
606 wrapMode: Text.WordWrap
607 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.")
608 }
609
610 GridLayout {
611 id: gridLayout
612 columns: 2
613
614 QGCLabel {
615 text: qsTr("Measured current:")
616 }
617 QGCTextField { id: measuredCurrent }
618
619 QGCLabel { text: qsTr("Vehicle current:") }
620 FactLabel { fact: vehicleCurrentFact }
621
622 QGCLabel { text: qsTr("Amps per volt:") }
623 FactLabel { fact: battAmpPerVoltFact }
624 }
625
626 QGCButton {
627 text: qsTr("Calculate And Set")
628
629 onClicked: {
630 var measuredCurrentValue = parseFloat(measuredCurrent.text)
631 if (measuredCurrentValue === 0 || isNaN(measuredCurrentValue) || !vehicleCurrentFact || !battAmpPerVoltFact) {
632 return
633 }
634 var newAmpsPerVolt = (vehicleCurrentFact.value !== 0) ? (measuredCurrentValue * battAmpPerVoltFact.value) / vehicleCurrentFact.value : 0
635 if (newAmpsPerVolt !== 0) {
636 battAmpPerVoltFact.value = newAmpsPerVolt
637 }
638 }
639 }
640 }
641 }
642 }
643
644} // SetupPage