PowerComponent.qml 24.1 KB
Newer Older
1 2
/****************************************************************************
 *
Gus Grubba's avatar
Gus Grubba committed
3
 * (c) 2009-2020 QGROUNDCONTROL PROJECT <http://www.qgroundcontrol.org>
4 5 6 7 8
 *
 * 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
            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
91 92 93 94 95 96 97
                    onOldFirmware:          mainWindow.showMessageDialog(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))
                    onNewerFirmware:        mainWindow.showMessageDialog(qsTr("ESC Calibration"), qsTr("%1 cannot perform ESC Calibration with this version of firmware. You will need to upgrade %1.").arg(QGroundControl.appName))
                    onBatteryConnected:     mainWindow.showMessageDialog(qsTr("ESC Calibration"), qsTr("Performing calibration. This will take a few seconds.."))
                    onCalibrationFailed:    mainWindow.showMessageDialog(qsTr("ESC Calibration failed"), errorMessage)
                    onCalibrationSuccess:   mainWindow.showMessageDialog(qsTr("ESC Calibration"), qsTr("Calibration complete. You can disconnect your battery now if you like."))
                    onConnectBattery:       mainWindow.showMessageDialog(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."))
                    onDisconnectBattery:    mainWindow.showMessageDialog(qsTr("ESC Calibration failed"), qsTr("You must disconnect the battery prior to performing ESC Calibration. Disconnect your battery and try again."))
Don Gagne's avatar
Don Gagne committed
98 99 100 101 102 103 104
                }

                Component {
                    id: calcVoltageDividerDlgComponent

                    QGCViewDialog {
                        id: calcVoltageDividerDlg
105

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

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

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

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

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

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

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

Don Gagne's avatar
Don Gagne committed
139 140 141 142 143
                                QGCButton {
                                    text: "Calculate"

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

Don Gagne's avatar
Don Gagne committed
158 159
                Component {
                    id: calcAmpsPerVoltDlgComponent
160

Don Gagne's avatar
Don Gagne committed
161 162
                    QGCViewDialog {
                        id: calcAmpsPerVoltDlg
163

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

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

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

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

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

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

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

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

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

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

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

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

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

Don Gagne's avatar
Don Gagne committed
236 237 238 239 240 241 242 243 244 245 246 247
                        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();
                        }
248

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

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

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

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

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

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

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

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

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

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

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

Don Gagne's avatar
Don Gagne committed
300 301
                        QGCButton {
                            id:                 voltMultCalculateButton
302
                            text:               qsTr("Calculate")
303
                            onClicked:          mainWindow.showComponentDialog(calcVoltageDividerDlgComponent, qsTr("Calculate Voltage Divider"), mainWindow.showDialogDefaultWidth, StandardButton.Close)
Don Gagne's avatar
Don Gagne committed
304
                        }
Don Gagne's avatar
Don Gagne committed
305

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

Don Gagne's avatar
Don Gagne committed
308 309 310 311 312 313
                        QGCLabel {
                            id:                 voltMultHelp
                            Layout.columnSpan:  batteryGrid.columns
                            Layout.fillWidth:   true
                            font.pointSize:     ScreenTools.smallFontPointSize
                            wrapMode:           Text.WordWrap
314 315
                            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
316
                        }
Don Gagne's avatar
Don Gagne committed
317

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

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

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

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

Don Gagne's avatar
Don Gagne committed
336 337 338 339 340 341
                        QGCLabel {
                            id:                 ampPerVoltHelp
                            Layout.columnSpan:  batteryGrid.columns
                            Layout.fillWidth:   true
                            font.pointSize:     ScreenTools.smallFontPointSize
                            wrapMode:           Text.WordWrap
342 343
                            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
344 345 346
                        }
                    } // Grid
                } // QGCGroupBox - Battery settings
347

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

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

Don Gagne's avatar
Don Gagne committed
358 359 360 361 362 363 364 365 366 367
                        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.")
                        }
368

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

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

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

                    Row {
                        id:         uavCanConfigRow
                        spacing:    ScreenTools.defaultFontPixelWidth

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

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

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

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

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

425
                        QGCLabel {
Don Gagne's avatar
Don Gagne committed
426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446
                            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()
447 448
                        }
                    }
449
                }
Don Gagne's avatar
Don Gagne committed
450 451 452 453 454 455 456

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

                QGCGroupBox {
457 458 459 460
                    Layout.maximumWidth:    batteryGroup.width
                    Layout.fillWidth:       true
                    title:                  qsTr("Advanced Power Settings")
                    visible:                showAdvanced.checked
Don Gagne's avatar
Don Gagne committed
461 462 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

                    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
488
                            Layout.maximumWidth: ScreenTools.defaultFontPixelWidth * 60
Don Gagne's avatar
Don Gagne committed
489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505
                        }

                        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
506 507
    } // Component
} // SetupPage