1
0
Fork 0
mirror of https://github.com/betaflight/betaflight-configurator.git synced 2025-07-23 08:15:22 +03:00

Auto merged - #2436 at Sat, 26 Jun 2021 01:13:51 GMT

Validate motor outputs and reset mixer if not enough resources available
This commit is contained in:
J Blackman 2021-06-26 11:13:51 +10:00 committed by GitHub
commit d024dd4fbc
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 101 additions and 20 deletions

View file

@ -2555,6 +2555,9 @@
"motorsEnableControl": { "motorsEnableControl": {
"message": "<strong>I understand the risks</strong>, the propellers are removed - enable motor control and arming, and disable Runaway Takeoff Prevention." "message": "<strong>I understand the risks</strong>, the propellers are removed - enable motor control and arming, and disable Runaway Takeoff Prevention."
}, },
"motorsDialogMixerReset": {
"message": "<strong>Invalid mixer mode selected.</strong><br /><br />The {{mixerName}} model needs {{mixerMotors}} motor resources.<br /><br />If using a custom mixer mode you need to define a custom mmix before changing mixer mode. If you come back to the motor tab after setting a mmix for your mode it won't reset the mode anymore. Please see the wiki for more information how to set this up.<br /><br />You are not able to test any motors or fly because firmware has {{outputs}} outputs for the selected mode.<br /><br />Resetting to default mixer mode"
},
"motorsDialogSettingsChanged": { "motorsDialogSettingsChanged": {
"message": "Configuration changes have been detected.<br /><br /><strong class=\"message-negative-italic\">Motor Test Mode is disabled until the settings have seen saved.</strong>" "message": "Configuration changes have been detected.<br /><br /><strong class=\"message-negative-italic\">Motor Test Mode is disabled until the settings have seen saved.</strong>"
}, },

View file

@ -314,6 +314,11 @@
flex-grow: 1; flex-grow: 1;
} }
.tab-motors #dialog-mixer-reset {
width: 400px;
height: fit-content;
}
.tab-motors #dialog-settings-changed { .tab-motors #dialog-settings-changed {
height: 120px; height: 120px;
} }

View file

@ -362,8 +362,38 @@ TABS.motors.initialize = function (callback) {
// select current mixer configuration // select current mixer configuration
mixerListElement.val(FC.MIXER_CONFIG.mixer).change(); mixerListElement.val(FC.MIXER_CONFIG.mixer).change();
function validateMixerOutputs() {
MSP.promise(MSPCodes.MSP_MOTOR).then(() => {
const mixer = FC.MIXER_CONFIG.mixer;
const motors = mixerList[mixer - 1].motors;
// initialize for models with zero motors
self.numberOfValidOutputs = motors;
for (let i = 0; i < FC.MOTOR_DATA.length; i++) {
if (FC.MOTOR_DATA[i] === 0) {
self.numberOfValidOutputs = i;
if (motors > self.numberOfValidOutputs && motors > 0) {
const msg = i18n.getMessage('motorsDialogMixerReset', {
mixerName: mixerList[mixer - 1].name,
mixerMotors: motors,
outputs: self.numberOfValidOutputs,
});
showDialogMixerReset(msg);
}
return;
}
}
});
}
update_model(FC.MIXER_CONFIG.mixer); update_model(FC.MIXER_CONFIG.mixer);
// Reference: src/main/drivers/motor.h for motorPwmProtocolTypes_e;
const ESC_PROTOCOL_UNDEFINED = 9;
if (FC.PID_ADVANCED_CONFIG.fast_pwm_protocol !== ESC_PROTOCOL_UNDEFINED) {
validateMixerOutputs();
}
// Always start with default/empty sensor data array, clean slate all // Always start with default/empty sensor data array, clean slate all
initSensorData(); initSensorData();
@ -563,7 +593,6 @@ TABS.motors.initialize = function (callback) {
accelOffsetEstablished = false; accelOffsetEstablished = false;
}); });
self.numberOfValidOutputs = (FC.MOTOR_DATA.indexOf(0) > -1) ? FC.MOTOR_DATA.indexOf(0) : 8;
let rangeMin; let rangeMin;
let rangeMax; let rangeMax;
let neutral3d; let neutral3d;
@ -714,6 +743,7 @@ TABS.motors.initialize = function (callback) {
} }
escProtocolElement.val(FC.PID_ADVANCED_CONFIG.fast_pwm_protocol + 1); escProtocolElement.val(FC.PID_ADVANCED_CONFIG.fast_pwm_protocol + 1);
console.log(FC.PID_ADVANCED_CONFIG.fast_pwm_protocol);
escProtocolElement.on("change", function () { escProtocolElement.on("change", function () {
const escProtocolValue = parseInt($(this).val()) - 1; const escProtocolValue = parseInt($(this).val()) - 1;
@ -841,7 +871,7 @@ TABS.motors.initialize = function (callback) {
$('div.values li').eq(index).text($(this).val()); $('div.values li').eq(index).text($(this).val());
for (let i = 0; i < 8; i++) { for (let i = 0; i < self.numberOfValidOutputs; i++) {
const val = parseInt($('div.sliders input').eq(i).val()); const val = parseInt($('div.sliders input').eq(i).val());
buffer.push16(val); buffer.push16(val);
} }
@ -930,14 +960,26 @@ TABS.motors.initialize = function (callback) {
} }
} }
function getMotorOutputs() {
const motorData = [];
const motorsTesting = motorsEnableTestModeElement.is(':checked');
for (let i = 0; i < self.numberOfValidOutputs; i++) {
motorData[i] = motorsTesting ? FC.MOTOR_DATA[i] : rangeMin;
}
return motorData;
}
const fullBlockScale = rangeMax - rangeMin; const fullBlockScale = rangeMax - rangeMin;
function update_ui() { function update_ui() {
const previousArmState = self.armed; const previousArmState = self.armed;
const blockHeight = $('div.m-block:first').height(); const blockHeight = $('div.m-block:first').height();
const motorValues = getMotorOutputs();
for (let i = 0; i < FC.MOTOR_DATA.length; i++) { for (let i = 0; i < motorValues.length; i++) {
const motorValue = FC.MOTOR_DATA[i]; const motorValue = motorValues[i];
const barHeight = motorValue - rangeMin, const barHeight = motorValue - rangeMin,
marginTop = blockHeight - (barHeight * (blockHeight / fullBlockScale)).clamp(0, blockHeight), marginTop = blockHeight - (barHeight * (blockHeight / fullBlockScale)).clamp(0, blockHeight),
height = (barHeight * (blockHeight / fullBlockScale)).clamp(0, blockHeight), height = (barHeight * (blockHeight / fullBlockScale)).clamp(0, blockHeight),
@ -1018,22 +1060,20 @@ TABS.motors.initialize = function (callback) {
FC.PID_ADVANCED_CONFIG.motor_pwm_rate = parseInt($('input[name="unsyncedpwmfreq"]').val()); FC.PID_ADVANCED_CONFIG.motor_pwm_rate = parseInt($('input[name="unsyncedpwmfreq"]').val());
FC.PID_ADVANCED_CONFIG.digitalIdlePercent = parseFloat($('input[name="digitalIdlePercent"]').val()); FC.PID_ADVANCED_CONFIG.digitalIdlePercent = parseFloat($('input[name="digitalIdlePercent"]').val());
Promise if (semver.gte(FC.CONFIG.apiVersion, "1.25.0") && semver.lt(FC.CONFIG.apiVersion, API_VERSION_1_41)) {
.resolve(true) FC.PID_ADVANCED_CONFIG.gyroUse32kHz = $('input[id="gyroUse32kHz"]').is(':checked') ? 1 : 0;
.then(() => { return MSP.promise(MSPCodes.MSP_SET_FEATURE_CONFIG, mspHelper.crunch(MSPCodes.MSP_SET_FEATURE_CONFIG)); }) }
.then(() => { return MSP.promise(MSPCodes.MSP_SET_MIXER_CONFIG, mspHelper.crunch(MSPCodes.MSP_SET_MIXER_CONFIG)); })
.then(() => { return MSP.promise(MSPCodes.MSP_SET_MOTOR_CONFIG, mspHelper.crunch(MSPCodes.MSP_SET_MOTOR_CONFIG)); }) MSP.promise(MSPCodes.MSP_SET_FEATURE_CONFIG, mspHelper.crunch(MSPCodes.MSP_SET_FEATURE_CONFIG))
.then(() => { return MSP.promise(MSPCodes.MSP_SET_MOTOR_3D_CONFIG, mspHelper.crunch(MSPCodes.MSP_SET_MOTOR_3D_CONFIG)); }) .then(() => MSP.promise(MSPCodes.MSP_SET_MIXER_CONFIG, mspHelper.crunch(MSPCodes.MSP_SET_MIXER_CONFIG)))
.then(() => { return MSP.promise(MSPCodes.MSP_SET_ADVANCED_CONFIG, mspHelper.crunch(MSPCodes.MSP_SET_ADVANCED_CONFIG)); }) .then(() => MSP.promise(MSPCodes.MSP_SET_MOTOR_CONFIG, mspHelper.crunch(MSPCodes.MSP_SET_MOTOR_CONFIG)))
.then(() => { return MSP.promise(MSPCodes.MSP_SET_ARMING_CONFIG, mspHelper.crunch(MSPCodes.MSP_SET_ARMING_CONFIG)); }) .then(() => MSP.promise(MSPCodes.MSP_SET_MOTOR_3D_CONFIG, mspHelper.crunch(MSPCodes.MSP_SET_MOTOR_3D_CONFIG)))
.then(() => { return (semver.gte(FC.CONFIG.apiVersion, API_VERSION_1_42)) ? MSP.promise(MSPCodes.MSP_SET_FILTER_CONFIG, .then(() => MSP.promise(MSPCodes.MSP_SET_ADVANCED_CONFIG, mspHelper.crunch(MSPCodes.MSP_SET_ADVANCED_CONFIG)))
mspHelper.crunch(MSPCodes.MSP_SET_FILTER_CONFIG)) : true; }) .then(() => MSP.promise(MSPCodes.MSP_SET_ARMING_CONFIG, mspHelper.crunch(MSPCodes.MSP_SET_ARMING_CONFIG)))
.then(() => { return MSP.promise(MSPCodes.MSP_EEPROM_WRITE); }) .then(() => semver.gte(FC.CONFIG.apiVersion, API_VERSION_1_42) ?
.then(() => { MSP.promise(MSPCodes.MSP_SET_FILTER_CONFIG, mspHelper.crunch(MSPCodes.MSP_SET_FILTER_CONFIG)) : true)
GUI.log(i18n.getMessage('configurationEepromSaved')); .then(() => MSP.promise(MSPCodes.MSP_EEPROM_WRITE))
MSP.send_message(MSPCodes.MSP_SET_REBOOT, false, false); .then(() => reboot());
reinitialiseConnection(self);
});
analytics.sendChangeEvents(analytics.EVENT_CATEGORIES.FLIGHT_CONTROLLER, self.analyticsChanges); analytics.sendChangeEvents(analytics.EVENT_CATEGORIES.FLIGHT_CONTROLLER, self.analyticsChanges);
self.analyticsChanges = {}; self.analyticsChanges = {};
@ -1062,6 +1102,30 @@ TABS.motors.initialize = function (callback) {
GUI.content_ready(callback); GUI.content_ready(callback);
} }
function reboot() {
GUI.log(i18n.getMessage('configurationEepromSaved'));
MSP.promise(MSPCodes.MSP_SET_REBOOT, false, false).then(() => reinitialiseConnection());
}
function showDialogMixerReset(message) {
const dialogMixerReset = $('#dialog-mixer-reset')[0];
$('#dialog-mixer-reset-content').html(message);
if (!dialogMixerReset.hasAttribute('open')) {
dialogMixerReset.showModal();
$('#dialog-mixer-reset-confirmbtn').click(function() {
dialogMixerReset.close();
FC.MIXER_CONFIG.mixer = 3;
MSP.promise(MSPCodes.MSP_SET_MIXER_CONFIG, mspHelper.crunch(MSPCodes.MSP_SET_MIXER_CONFIG))
.then(() => MSP.promise(MSPCodes.MSP_EEPROM_WRITE))
.then(() => reboot());
});
}
}
function showDialogSettingsChanged(message) { function showDialogSettingsChanged(message) {
const dialogSettingsChanged = $('#dialog-settings-changed')[0]; const dialogSettingsChanged = $('#dialog-settings-changed')[0];

View file

@ -373,6 +373,15 @@
</div> <!-- END CONTENT_WRAPPER --> </div> <!-- END CONTENT_WRAPPER -->
<dialog id="dialog-mixer-reset">
<div id="dialog-mixer-reset-content-wrapper">
<div id="dialog-mixer-reset-content"></div>
<div class="btn dialog-buttons">
<a href="#" id="dialog-mixer-reset-confirmbtn" class="regular-button right" i18n="motorsDialogSettingsChangedOk"></a>
</div>
</div>
</dialog>
<dialog id="dialog-settings-changed"> <dialog id="dialog-settings-changed">
<div id="dialog-settings-changed-content-wrapper"> <div id="dialog-settings-changed-content-wrapper">
<div id="dialog-settings-changed-content"></div> <div id="dialog-settings-changed-content"></div>