PowerComponent.qml 24.1 KB
Newer Older
1 2 3 4 5 6 7 8
/****************************************************************************
 *
 *   (c) 2009-2016 QGROUNDCONTROL PROJECT <http://www.qgroundcontrol.org>
 *
 * QGroundControl is licensed according to the terms in the file
 * COPYING.md in the root of the source code directory.
 *
 ****************************************************************************/
dogmaphobic's avatar
dogmaphobic committed
9

10 11
import QtQuick          2.3
import QtQuick.Controls 1.2
12
import QtQuick.Dialogs  1.2
13
import QtQuick.Layouts  1.2
dogmaphobic's avatar
dogmaphobic committed
14

15
import QGroundControl               1.0
16 17 18 19 20
import QGroundControl.FactSystem    1.0
import QGroundControl.FactControls  1.0
import QGroundControl.Controls      1.0
import QGroundControl.ScreenTools   1.0
import QGroundControl.Controllers   1.0
dogmaphobic's avatar
dogmaphobic committed
21

22 23 24
SetupPage {
    id:             powerPage
    pageComponent:  pageComponent
25

26
    Component {
27 28
        id: pageComponent

Don Gagne's avatar
Don Gagne committed
29 30 31 32
        Item {
            width:  Math.max(availableWidth, innerColumn.width)
            height: innerColumn.height

33 34 35 36 37 38 39 40 41 42 43 44 45
            property int textEditWidth:    ScreenTools.defaultFontPixelWidth * 8

            property Fact battNumCells:         controller.getParameterFact(-1, "BAT_N_CELLS")
            property Fact battHighVolt:         controller.getParameterFact(-1, "BAT_V_CHARGED")
            property Fact battLowVolt:          controller.getParameterFact(-1, "BAT_V_EMPTY")
            property Fact battVoltLoadDrop:     controller.getParameterFact(-1, "BAT_V_LOAD_DROP")
            property Fact battVoltageDivider:   controller.getParameterFact(-1, "BAT_V_DIV")
            property Fact battAmpsPerVolt:      controller.getParameterFact(-1, "BAT_A_PER_V")
            property Fact uavcanEnable:         controller.getParameterFact(-1, "UAVCAN_ENABLE", false)

            readonly property string highlightPrefix:   "<font color=\"" + qgcPal.warningText + "\">"
            readonly property string highlightSuffix:   "</font>"

Gus Grubba's avatar
Gus Grubba committed
46 47 48 49 50 51 52 53 54 55 56 57 58
            function getBatteryImage()
            {
                switch(battNumCells.value) {
                case 1:  return "/qmlimages/PowerComponentBattery_01cell.svg";
                case 2:  return "/qmlimages/PowerComponentBattery_02cell.svg"
                case 3:  return "/qmlimages/PowerComponentBattery_03cell.svg"
                case 4:  return "/qmlimages/PowerComponentBattery_04cell.svg"
                case 5:  return "/qmlimages/PowerComponentBattery_05cell.svg"
                case 6:  return "/qmlimages/PowerComponentBattery_06cell.svg"
                default: return "/qmlimages/PowerComponentBattery_01cell.svg";
                }
            }

Don Gagne's avatar
Don Gagne committed
59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92
            ColumnLayout {
                id:                         innerColumn
                anchors.horizontalCenter:   parent.horizontalCenter
                spacing:                    ScreenTools.defaultFontPixelHeight

                function drawArrowhead(ctx, x, y, radians)
                {
                    ctx.save();
                    ctx.beginPath();
                    ctx.translate(x,y);
                    ctx.rotate(radians);
                    ctx.moveTo(0,0);
                    ctx.lineTo(5,10);
                    ctx.lineTo(-5,10);
                    ctx.closePath();
                    ctx.restore();
                    ctx.fill();
                }

                function drawLineWithArrow(ctx, x1, y1, x2, y2)
                {
                    ctx.beginPath();
                    ctx.moveTo(x1, y1);
                    ctx.lineTo(x2, y2);
                    ctx.stroke();
                    var rd = Math.atan((y2 - y1) / (x2 - x1));
                    rd += ((x2 > x1) ? 90 : -90) * Math.PI/180;
                    drawArrowhead(ctx, x2, y2, rd);
                }

                PowerComponentController {
                    id:         controller
                    factPanel:  powerPage.viewPanel

93 94
                    onOldFirmware:          showMessage(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), StandardButton.Ok)
                    onNewerFirmware:        showMessage(qsTr("ESC Calibration"), qsTr("%1 cannot perform ESC Calibration with this version of firmware. You will need to upgrade %1.").arg(QGroundControl.appName), StandardButton.Ok)
Don Gagne's avatar
Don Gagne committed
95 96 97 98 99 100 101 102 103 104 105 106
                    onBatteryConnected:     showMessage(qsTr("ESC Calibration"), qsTr("Performing calibration. This will take a few seconds.."), 0)
                    onCalibrationFailed:    showMessage(qsTr("ESC Calibration failed"), errorMessage, StandardButton.Ok)
                    onCalibrationSuccess:   showMessage(qsTr("ESC Calibration"), qsTr("Calibration complete. You can disconnect your battery now if you like."), StandardButton.Ok)
                    onConnectBattery:       showMessage(qsTr("ESC Calibration"), highlightPrefix + qsTr("WARNING: Props must be removed from vehicle prior to performing ESC calibration.") + highlightSuffix + qsTr(" Connect the battery now and calibration will begin."), 0)
                    onDisconnectBattery:    showMessage(qsTr("ESC Calibration failed"), qsTr("You must disconnect the battery prior to performing ESC Calibration. Disconnect your battery and try again."), StandardButton.Ok)
                }

                Component {
                    id: calcVoltageDividerDlgComponent

                    QGCViewDialog {
                        id: calcVoltageDividerDlg
107

Don Gagne's avatar
Don Gagne committed
108 109 110 111 112 113 114 115 116
                        QGCFlickable {
                            anchors.fill:   parent
                            contentHeight:  column.height
                            contentWidth:   column.width

                            Column {
                                id:         column
                                width:      calcVoltageDividerDlg.width
                                spacing:    ScreenTools.defaultFontPixelHeight
117

118
                                QGCLabel {
Don Gagne's avatar
Don Gagne committed
119 120
                                    width:      parent.width
                                    wrapMode:   Text.WordWrap
121
                                    text:       qsTr("Measure battery voltage using an external voltmeter and enter the value below. Click Calculate to set the new voltage multiplier.")
122
                                }
123

Don Gagne's avatar
Don Gagne committed
124 125 126 127
                                Grid {
                                    columns: 2
                                    spacing: ScreenTools.defaultFontPixelHeight / 2
                                    verticalItemAlignment: Grid.AlignVCenter
128

Don Gagne's avatar
Don Gagne committed
129
                                    QGCLabel {
130
                                        text: qsTr("Measured voltage:")
Don Gagne's avatar
Don Gagne committed
131 132
                                    }
                                    QGCTextField { id: measuredVoltage }
133

134
                                    QGCLabel { text: qsTr("Vehicle voltage:") }
Don Gagne's avatar
Don Gagne committed
135
                                    QGCLabel { text: controller.vehicle.battery.voltage.valueString }
136

137
                                    QGCLabel { text: qsTr("Voltage divider:") }
Don Gagne's avatar
Don Gagne committed
138
                                    FactLabel { fact: battVoltageDivider }
139
                                }
140

Don Gagne's avatar
Don Gagne committed
141 142 143 144 145
                                QGCButton {
                                    text: "Calculate"

                                    onClicked:  {
                                        var measuredVoltageValue = parseFloat(measuredVoltage.text)
146
                                        if (measuredVoltageValue === 0 || isNaN(measuredVoltageValue)) {
Don Gagne's avatar
Don Gagne committed
147 148 149 150 151 152 153 154 155 156 157 158
                                            return
                                        }
                                        var newVoltageDivider = (measuredVoltageValue * battVoltageDivider.value) / controller.vehicle.battery.voltage.value
                                        if (newVoltageDivider > 0) {
                                            battVoltageDivider.value = newVoltageDivider
                                        }
                                    }
                                }
                            } // Column
                        } // QGCFlickable
                    } // QGCViewDialog
                } // Component - calcVoltageDividerDlgComponent
159

Don Gagne's avatar
Don Gagne committed
160 161
                Component {
                    id: calcAmpsPerVoltDlgComponent
162

Don Gagne's avatar
Don Gagne committed
163 164
                    QGCViewDialog {
                        id: calcAmpsPerVoltDlg
165

Don Gagne's avatar
Don Gagne committed
166 167 168 169
                        QGCFlickable {
                            anchors.fill:   parent
                            contentHeight:  column.height
                            contentWidth:   column.width
170

Don Gagne's avatar
Don Gagne committed
171 172 173 174
                            Column {
                                id:         column
                                width:      calcAmpsPerVoltDlg.width
                                spacing:    ScreenTools.defaultFontPixelHeight
175

176
                                QGCLabel {
Don Gagne's avatar
Don Gagne committed
177 178
                                    width:      parent.width
                                    wrapMode:   Text.WordWrap
179
                                    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.")
180
                                }
181

Don Gagne's avatar
Don Gagne committed
182 183 184 185
                                Grid {
                                    columns: 2
                                    spacing: ScreenTools.defaultFontPixelHeight / 2
                                    verticalItemAlignment: Grid.AlignVCenter
186

Don Gagne's avatar
Don Gagne committed
187
                                    QGCLabel {
188
                                        text: qsTr("Measured current:")
Don Gagne's avatar
Don Gagne committed
189 190
                                    }
                                    QGCTextField { id: measuredCurrent }
191

192
                                    QGCLabel { text: qsTr("Vehicle current:") }
Don Gagne's avatar
Don Gagne committed
193
                                    QGCLabel { text: controller.vehicle.battery.current.valueString }
194

195
                                    QGCLabel { text: qsTr("Amps per volt:") }
Don Gagne's avatar
Don Gagne committed
196 197 198 199
                                    FactLabel { fact: battAmpsPerVolt }
                                }

                                QGCButton {
200
                                    text: qsTr("Calculate")
Don Gagne's avatar
Don Gagne committed
201 202 203

                                    onClicked:  {
                                        var measuredCurrentValue = parseFloat(measuredCurrent.text)
204
                                        if (measuredCurrentValue === 0) {
Don Gagne's avatar
Don Gagne committed
205 206 207 208 209 210
                                            return
                                        }
                                        var newAmpsPerVolt = (measuredCurrentValue * battAmpsPerVolt.value) / controller.vehicle.battery.current.value
                                        if (newAmpsPerVolt != 0) {
                                            battAmpsPerVolt.value = newAmpsPerVolt
                                        }
211 212
                                    }
                                }
Don Gagne's avatar
Don Gagne committed
213 214 215 216
                            } // Column
                        } // QGCFlickable
                    } // QGCViewDialog
                } // Component - calcAmpsPerVoltDlgComponent
217

Don Gagne's avatar
Don Gagne committed
218 219 220
                QGCGroupBox {
                    id:     batteryGroup
                    title:  qsTr("Battery")
221

Don Gagne's avatar
Don Gagne committed
222 223 224 225
                    GridLayout {
                        id:             batteryGrid
                        columns:        5
                        columnSpacing:  ScreenTools.defaultFontPixelWidth
226

Don Gagne's avatar
Don Gagne committed
227 228 229
                        QGCLabel {
                            text:               qsTr("Number of Cells (in Series)")
                        }
230

Don Gagne's avatar
Don Gagne committed
231 232 233 234 235 236
                        FactTextField {
                            id:         cellsField
                            width:      textEditWidth
                            fact:       battNumCells
                            showUnits:  true
                        }
237

Don Gagne's avatar
Don Gagne committed
238 239 240 241 242 243 244 245 246 247 248 249
                        QGCColoredImage {
                            id:                     batteryImage
                            Layout.rowSpan:         3
                            width:                  height * 0.75
                            height:                 100
                            sourceSize.height:      height
                            fillMode:               Image.PreserveAspectFit
                            smooth:                 true
                            color:                  qgcPal.text
                            cache:                  false
                            source:                 getBatteryImage();
                        }
250

Don Gagne's avatar
Don Gagne committed
251
                        Item { width: 1; height: 1; Layout.columnSpan: 2 }
252

Don Gagne's avatar
Don Gagne committed
253 254 255 256
                        QGCLabel {
                            id:                 battHighLabel
                            text:               qsTr("Full Voltage (per cell)")
                        }
257

Don Gagne's avatar
Don Gagne committed
258 259 260 261 262 263
                        FactTextField {
                            id:         battHighField
                            width:      textEditWidth
                            fact:       battHighVolt
                            showUnits:  true
                        }
264

Don Gagne's avatar
Don Gagne committed
265 266 267
                        QGCLabel {
                            text:   qsTr("Battery Max:")
                        }
268

Don Gagne's avatar
Don Gagne committed
269 270 271
                        QGCLabel {
                            text:   (battNumCells.value * battHighVolt.value).toFixed(1) + ' V'
                        }
272

Don Gagne's avatar
Don Gagne committed
273 274 275 276
                        QGCLabel {
                            id:                 battLowLabel
                            text:               qsTr("Empty Voltage (per cell)")
                        }
277

Don Gagne's avatar
Don Gagne committed
278 279 280 281 282 283
                        FactTextField {
                            id:         battLowField
                            width:      textEditWidth
                            fact:       battLowVolt
                            showUnits:  true
                        }
284

Don Gagne's avatar
Don Gagne committed
285 286 287
                        QGCLabel {
                            text:   qsTr("Battery Min:")
                        }
288

Don Gagne's avatar
Don Gagne committed
289 290 291
                        QGCLabel {
                            text:   (battNumCells.value * battLowVolt.value).toFixed(1) + ' V'
                        }
292

Don Gagne's avatar
Don Gagne committed
293 294 295
                        QGCLabel {
                            text:               qsTr("Voltage divider")
                        }
296

Don Gagne's avatar
Don Gagne committed
297 298 299 300
                        FactTextField {
                            id:                 voltMultField
                            fact:               battVoltageDivider
                        }
Don Gagne's avatar
Don Gagne committed
301

Don Gagne's avatar
Don Gagne committed
302 303
                        QGCButton {
                            id:                 voltMultCalculateButton
304
                            text:               qsTr("Calculate")
Don Gagne's avatar
Don Gagne committed
305 306
                            onClicked:          showDialog(calcVoltageDividerDlgComponent, qsTr("Calculate Voltage Divider"), powerPage.showDialogDefaultWidth, StandardButton.Close)
                        }
Don Gagne's avatar
Don Gagne committed
307

Don Gagne's avatar
Don Gagne committed
308
                        Item { width: 1; height: 1; Layout.columnSpan: 2 }
Don Gagne's avatar
Don Gagne committed
309

Don Gagne's avatar
Don Gagne committed
310 311 312 313 314 315
                        QGCLabel {
                            id:                 voltMultHelp
                            Layout.columnSpan:  batteryGrid.columns
                            Layout.fillWidth:   true
                            font.pointSize:     ScreenTools.smallFontPointSize
                            wrapMode:           Text.WordWrap
316 317
                            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. ") +
                                                qsTr("Click the Calculate button for help with calculating a new value.")
Don Gagne's avatar
Don Gagne committed
318
                        }
Don Gagne's avatar
Don Gagne committed
319

Don Gagne's avatar
Don Gagne committed
320 321 322 323
                        QGCLabel {
                            id:                 ampPerVoltLabel
                            text:               qsTr("Amps per volt")
                        }
324

Don Gagne's avatar
Don Gagne committed
325 326 327 328
                        FactTextField {
                            id:                 ampPerVoltField
                            fact:               battAmpsPerVolt
                        }
329

Don Gagne's avatar
Don Gagne committed
330 331
                        QGCButton {
                            id:                 ampPerVoltCalculateButton
332
                            text:               qsTr("Calculate")
Don Gagne's avatar
Don Gagne committed
333 334
                            onClicked:          showDialog(calcAmpsPerVoltDlgComponent, qsTr("Calculate Amps per Volt"), powerPage.showDialogDefaultWidth, StandardButton.Close)
                        }
335

Don Gagne's avatar
Don Gagne committed
336
                        Item { width: 1; height: 1; Layout.columnSpan: 2 }
Don Gagne's avatar
Don Gagne committed
337

Don Gagne's avatar
Don Gagne committed
338 339 340 341 342 343
                        QGCLabel {
                            id:                 ampPerVoltHelp
                            Layout.columnSpan:  batteryGrid.columns
                            Layout.fillWidth:   true
                            font.pointSize:     ScreenTools.smallFontPointSize
                            wrapMode:           Text.WordWrap
344 345
                            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. ") +
                                                qsTr("Click the Calculate button for help with calculating a new value.")
Don Gagne's avatar
Don Gagne committed
346 347 348
                        }
                    } // Grid
                } // QGCGroupBox - Battery settings
349

Don Gagne's avatar
Don Gagne committed
350
                QGCGroupBox {
351 352 353
                    Layout.maximumWidth:    batteryGroup.width
                    Layout.fillWidth:       true
                    title:                  qsTr("ESC PWM Minimum and Maximum Calibration")
dogmaphobic's avatar
dogmaphobic committed
354

Don Gagne's avatar
Don Gagne committed
355 356 357 358
                    ColumnLayout {
                        anchors.left:   parent.left
                        anchors.right:  parent.right
                        spacing:        ScreenTools.defaultFontPixelWidth
359

Don Gagne's avatar
Don Gagne committed
360 361 362 363 364 365 366 367 368 369
                        QGCLabel {
                            color:              qgcPal.warningText
                            wrapMode:           Text.WordWrap
                            text:               qsTr("WARNING: Propellers must be removed from vehicle prior to performing ESC calibration.")
                            Layout.fillWidth:   true
                        }

                        QGCLabel {
                            text: qsTr("You must use USB connection for this operation.")
                        }
370

Don Gagne's avatar
Don Gagne committed
371 372 373 374 375
                        QGCButton {
                            text:       qsTr("Calibrate")
                            width:      ScreenTools.defaultFontPixelWidth * 20
                            onClicked:  controller.calibrateEsc()
                        }
376
                    }
377
                }
378

Don Gagne's avatar
Don Gagne committed
379 380 381
                QGCCheckBox {
                    id:         showUAVCAN
                    text:       qsTr("Show UAVCAN Settings")
Gus Grubba's avatar
Gus Grubba committed
382
                    checked:    uavcanEnable ? uavcanEnable.rawValue !== 0 : false
Don Gagne's avatar
Don Gagne committed
383
                }
384

Don Gagne's avatar
Don Gagne committed
385
                QGCGroupBox {
386 387 388 389
                    Layout.maximumWidth:    batteryGroup.width
                    Layout.fillWidth:       true
                    title:                  qsTr("UAVCAN Bus Configuration")
                    visible:                showUAVCAN.checked
Don Gagne's avatar
Don Gagne committed
390 391 392 393 394 395 396 397 398 399

                    Row {
                        id:         uavCanConfigRow
                        spacing:    ScreenTools.defaultFontPixelWidth

                        FactComboBox {
                            id:                 uavcanEnabledCheckBox
                            width:              ScreenTools.defaultFontPixelWidth * 20
                            fact:               uavcanEnable
                            indexModel:         false
400 401
                        }

Don Gagne's avatar
Don Gagne committed
402 403 404
                        QGCLabel {
                            anchors.verticalCenter: parent.verticalCenter
                            text:                   qsTr("Change required restart")
405
                        }
406
                    }
Don Gagne's avatar
Don Gagne committed
407
                }
408

Don Gagne's avatar
Don Gagne committed
409
                QGCGroupBox {
410 411 412 413
                    Layout.maximumWidth:    batteryGroup.width
                    Layout.fillWidth:       true
                    title:                  qsTr("UAVCAN Motor Index and Direction Assignment")
                    visible:                showUAVCAN.checked
414

Don Gagne's avatar
Don Gagne committed
415 416 417 418
                    ColumnLayout {
                        anchors.left:   parent.left
                        anchors.right:  parent.right
                        spacing:        ScreenTools.defaultFontPixelWidth
419

420
                        QGCLabel {
Don Gagne's avatar
Don Gagne committed
421 422 423 424
                            wrapMode:           Text.WordWrap
                            color:              qgcPal.warningText
                            text:               qsTr("WARNING: Propellers must be removed from vehicle prior to performing UAVCAN ESC configuration.")
                            Layout.fillWidth:   true
425 426
                        }

427
                        QGCLabel {
Don Gagne's avatar
Don Gagne committed
428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448
                            wrapMode:           Text.WordWrap
                            text:               qsTr("ESC parameters will only be accessible in the editor after assignment.")
                            Layout.fillWidth:   true
                        }

                        QGCLabel {
                            wrapMode:           Text.WordWrap
                            text:               qsTr("Start the process, then turn each motor into its turn direction, in the order of their motor indices.")
                            Layout.fillWidth:   true
                        }

                        QGCButton {
                            text:       qsTr("Start Assignment")
                            width:      ScreenTools.defaultFontPixelWidth * 20
                            onClicked:  controller.busConfigureActuators()
                        }

                        QGCButton {
                            text:       qsTr("Stop Assignment")
                            width:      ScreenTools.defaultFontPixelWidth * 20
                            onClicked:  controller.stopBusConfigureActuators()
449 450
                        }
                    }
451
                }
Don Gagne's avatar
Don Gagne committed
452 453 454 455 456 457 458

                QGCCheckBox {
                    id:     showAdvanced
                    text:   qsTr("Show Advanced Settings")
                }

                QGCGroupBox {
459 460 461 462
                    Layout.maximumWidth:    batteryGroup.width
                    Layout.fillWidth:       true
                    title:                  qsTr("Advanced Power Settings")
                    visible:                showAdvanced.checked
Don Gagne's avatar
Don Gagne committed
463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489

                    ColumnLayout {
                        anchors.left:   parent.left
                        anchors.right:  parent.right
                        spacing:        ScreenTools.defaultFontPixelWidth

                        Row {
                            spacing: ScreenTools.defaultFontPixelWidth

                            QGCLabel {
                                text:               qsTr("Voltage Drop on Full Load (per cell)")
                                anchors.baseline:   battDropField.baseline
                            }

                            FactTextField {
                                id:         battDropField
                                width:      textEditWidth
                                fact:       battVoltLoadDrop
                                showUnits:  true
                            }
                        }

                        QGCLabel {
                            wrapMode:           Text.WordWrap
                            text:               qsTr("Batteries show less voltage at high throttle. Enter the difference in Volts between idle throttle and full ") +
                                                qsTr("throttle, divided by the number of battery cells. Leave at the default if unsure. ") +
                                                highlightPrefix + qsTr("If this value is set too high, the battery might be deep discharged and damaged.") + highlightSuffix
490
                            Layout.maximumWidth: ScreenTools.defaultFontPixelWidth * 60
Don Gagne's avatar
Don Gagne committed
491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507
                        }

                        Row {
                            spacing: ScreenTools.defaultFontPixelWidth

                            QGCLabel {
                                text: qsTr("Compensated Minimum Voltage:")
                            }

                            QGCLabel {
                                text: ((battNumCells.value * battLowVolt.value) - (battNumCells.value * battVoltLoadDrop.value)).toFixed(1) + qsTr(" V")
                            }
                        }
                    } // Column
                } // QGCGroupBox - Advanced power settings
            } // Column
        } // Item
508 509
    } // Component
} // SetupPage