Validate motor outputs and reset mixer if not

10.8-maintenance
Mark Haslinghuis 2021-03-08 23:07:06 +01:00
parent b5e253c179
commit 6fca8ad5e1
4 changed files with 101 additions and 20 deletions

View File

@ -2551,6 +2551,9 @@
"motorsEnableControl": {
"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": {
"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

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

View File

@ -365,8 +365,38 @@ TABS.motors.initialize = function (callback) {
// select current mixer configuration
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);
// 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
initSensorData();
@ -566,7 +596,6 @@ TABS.motors.initialize = function (callback) {
accelOffsetEstablished = false;
});
self.numberOfValidOutputs = (FC.MOTOR_DATA.indexOf(0) > -1) ? FC.MOTOR_DATA.indexOf(0) : 8;
let rangeMin;
let rangeMax;
let neutral3d;
@ -710,6 +739,7 @@ TABS.motors.initialize = function (callback) {
}
escProtocolElement.val(FC.PID_ADVANCED_CONFIG.fast_pwm_protocol + 1);
console.log(FC.PID_ADVANCED_CONFIG.fast_pwm_protocol);
escProtocolElement.on("change", function () {
const escProtocolValue = parseInt($(this).val()) - 1;
@ -837,7 +867,7 @@ TABS.motors.initialize = function (callback) {
$('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());
buffer.push16(val);
}
@ -926,14 +956,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;
function update_ui() {
const previousArmState = self.armed;
const blockHeight = $('div.m-block:first').height();
const motorValues = getMotorOutputs();
for (let i = 0; i < FC.MOTOR_DATA.length; i++) {
const motorValue = FC.MOTOR_DATA[i];
for (let i = 0; i < motorValues.length; i++) {
const motorValue = motorValues[i];
const barHeight = motorValue - rangeMin,
marginTop = blockHeight - (barHeight * (blockHeight / fullBlockScale)).clamp(0, blockHeight),
height = (barHeight * (blockHeight / fullBlockScale)).clamp(0, blockHeight),
@ -1014,22 +1056,20 @@ TABS.motors.initialize = function (callback) {
FC.PID_ADVANCED_CONFIG.motor_pwm_rate = parseInt($('input[name="unsyncedpwmfreq"]').val());
FC.PID_ADVANCED_CONFIG.digitalIdlePercent = parseFloat($('input[name="digitalIdlePercent"]').val());
Promise
.resolve(true)
.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)); })
.then(() => { return MSP.promise(MSPCodes.MSP_SET_MOTOR_3D_CONFIG, mspHelper.crunch(MSPCodes.MSP_SET_MOTOR_3D_CONFIG)); })
.then(() => { return MSP.promise(MSPCodes.MSP_SET_ADVANCED_CONFIG, mspHelper.crunch(MSPCodes.MSP_SET_ADVANCED_CONFIG)); })
.then(() => { return MSP.promise(MSPCodes.MSP_SET_ARMING_CONFIG, mspHelper.crunch(MSPCodes.MSP_SET_ARMING_CONFIG)); })
.then(() => { return (semver.gte(FC.CONFIG.apiVersion, API_VERSION_1_42)) ? MSP.promise(MSPCodes.MSP_SET_FILTER_CONFIG,
mspHelper.crunch(MSPCodes.MSP_SET_FILTER_CONFIG)) : true; })
.then(() => { return MSP.promise(MSPCodes.MSP_EEPROM_WRITE); })
.then(() => {
GUI.log(i18n.getMessage('configurationEepromSaved'));
MSP.send_message(MSPCodes.MSP_SET_REBOOT, false, false);
reinitialiseConnection(self);
});
if (semver.gte(FC.CONFIG.apiVersion, "1.25.0") && semver.lt(FC.CONFIG.apiVersion, API_VERSION_1_41)) {
FC.PID_ADVANCED_CONFIG.gyroUse32kHz = $('input[id="gyroUse32kHz"]').is(':checked') ? 1 : 0;
}
MSP.promise(MSPCodes.MSP_SET_FEATURE_CONFIG, mspHelper.crunch(MSPCodes.MSP_SET_FEATURE_CONFIG))
.then(() => MSP.promise(MSPCodes.MSP_SET_MIXER_CONFIG, mspHelper.crunch(MSPCodes.MSP_SET_MIXER_CONFIG)))
.then(() => MSP.promise(MSPCodes.MSP_SET_MOTOR_CONFIG, mspHelper.crunch(MSPCodes.MSP_SET_MOTOR_CONFIG)))
.then(() => MSP.promise(MSPCodes.MSP_SET_MOTOR_3D_CONFIG, mspHelper.crunch(MSPCodes.MSP_SET_MOTOR_3D_CONFIG)))
.then(() => MSP.promise(MSPCodes.MSP_SET_ADVANCED_CONFIG, mspHelper.crunch(MSPCodes.MSP_SET_ADVANCED_CONFIG)))
.then(() => MSP.promise(MSPCodes.MSP_SET_ARMING_CONFIG, mspHelper.crunch(MSPCodes.MSP_SET_ARMING_CONFIG)))
.then(() => semver.gte(FC.CONFIG.apiVersion, API_VERSION_1_42) ?
MSP.promise(MSPCodes.MSP_SET_FILTER_CONFIG, mspHelper.crunch(MSPCodes.MSP_SET_FILTER_CONFIG)) : true)
.then(() => MSP.promise(MSPCodes.MSP_EEPROM_WRITE))
.then(() => reboot());
analytics.sendChangeEvents(analytics.EVENT_CATEGORIES.FLIGHT_CONTROLLER, self.analyticsChanges);
self.analyticsChanges = {};
@ -1058,6 +1098,30 @@ TABS.motors.initialize = function (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) {
const dialogSettingsChanged = $('#dialog-settings-changed')[0];

View File

@ -373,6 +373,15 @@
</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">
<div id="dialog-settings-changed-content-wrapper">
<div id="dialog-settings-changed-content"></div>