diff --git a/locales/en/messages.json b/locales/en/messages.json
index c63f6e154e..3d741b49e5 100755
--- a/locales/en/messages.json
+++ b/locales/en/messages.json
@@ -1393,8 +1393,20 @@
"configurationOtherFeaturesHelp": {
"message": "Note: Not all features are supported by all flight controllers. If you enable a specific feature, and it is disabled after you hit 'Save and Reboot', it means that this feature is not supported on your board."
},
+ "configurationMagAlignmentHelp": {
+ "message": "The magnetometer alignment is the orientation of the magnetometer sensor on the flight controller board. The default is usually correct, but if you have a custom build or a flight controller with a different magnetometer orientation, you may need to adjust this setting."
+ },
+ "configurationMagDeclination": {
+ "message": "Magnetometer Declination"
+ },
+ "configurationMagDeclinationInput": {
+ "message": "Declination Degrees"
+ },
+ "configurationMagDeclinationHelp": {
+ "message": "The magnetic declination is the angle between magnetic north and true north. It is different for every location on earth. You can find the declination for your location on the internet"
+ },
"configurationBoardAlignment": {
- "message": "Board and Sensor Alignment"
+ "message": "Board Alignment"
},
"configurationBoardAlignmentRoll": {
"message": "Roll Degrees"
@@ -1405,6 +1417,36 @@
"configurationBoardAlignmentYaw": {
"message": "Yaw Degrees"
},
+ "configurationGyroAlignment": {
+ "message": "Gyro Alignment"
+ },
+ "configurationGyroAlignmentHelp": {
+ "message": "The gyro alignment is the orientation of the gyro sensor on the flight controller board. The default is usually correct, but if you have a custom build or a flight controller with a different gyro orientation, you may need to adjust this setting."
+ },
+ "configurationGyroAlignmentRoll": {
+ "message": "$t(configurationBoardAlignmentRoll.message)"
+ },
+ "configurationGyroAlignmentPitch": {
+ "message": "$t(configurationBoardAlignmentPitch.message)"
+ },
+ "configurationGyroAlignmentYaw": {
+ "message": "$t(configurationBoardAlignmentYaw.message)"
+ },
+ "configurationMagAlignment": {
+ "message": "Magnetometer Alignment"
+ },
+ "configurationBoardAlignmentHelp": {
+ "message": "Arbitrary board rotation in degrees, to allow mounting it sideways / upside down / rotated etc. When running external sensors, use the sensor alignments (Gyro, Acc, Mag) to define sensor position independent from board orientation. "
+ },
+ "configurationMagAlignmentRoll": {
+ "message": "$t(configurationBoardAlignmentRoll.message)"
+ },
+ "configurationMagAlignmentPitch": {
+ "message": "$t(configurationBoardAlignmentPitch.message)"
+ },
+ "configurationMagAlignmentYaw": {
+ "message": "$t(configurationBoardAlignmentYaw.message)"
+ },
"configurationSensorAlignmentGyro": {
"message": "GYRO Alignment"
},
@@ -1432,9 +1474,6 @@
"configurationSensorAlignmentAcc": {
"message": "ACCEL Alignment"
},
- "configurationSensorAlignmentMag": {
- "message": "MAG Alignment"
- },
"configurationSensorAlignmentDefaultOption": {
"message": "Default"
},
@@ -1453,9 +1492,6 @@
"configurationArmingHelp": {
"message": "Some Arming options may require accelerometer be enabled"
},
- "configurationMagDeclination": {
- "message": "Magnetometer Declination [deg]"
- },
"configurationReverseMotorSwitch": {
"message": "Motor direction is reversed"
},
@@ -4655,9 +4691,6 @@
"pidTuningIntegratedYawHelp": {
"message": "Integrated Yaw integrates yaw P, I and D values, allowing yaw P, I and D to be tuned a bit like you'd tune pitch and roll.
Very little I is required, because the integrated P acts like I, and integrated D acts like P.
NOTE: Integrated Yaw requires use of Absolute Control, since no I is needed with Integrated Yaw."
},
- "configHelp2": {
- "message": "Arbitrary board rotation in degrees, to allow mounting it sideways / upside down / rotated etc. When running external sensors, use the sensor alignments (Gyro, Acc, Mag) to define sensor position independent from board orientation. "
- },
"failsafeFeaturesHelpOld": {
"message": "Failsafe configuration has changed considerably. Use Betaflight v1.12.0+ to enable the improved configuration panel."
},
diff --git a/src/css/tabs/configuration.less b/src/css/tabs/configuration.less
index ab14554a6c..e7afb15c50 100644
--- a/src/css/tabs/configuration.less
+++ b/src/css/tabs/configuration.less
@@ -19,24 +19,19 @@
background-repeat: no-repeat;
background-position: center;
}
- .board_align_content {
+ .sensor_align_content {
display: flex;
justify-content: space-between;
width: 100%;
flex-wrap: wrap;
gap: 0.5rem;
- .board_align_inputs {
+ .sensor_align_inputs {
display: flex;
label {
white-space: nowrap;
}
}
}
- .gyro_align_content {
- display: flex;
- flex-direction: column;
- gap: 1rem;
- }
table {
td {
height: 1.75rem;
diff --git a/src/js/fc.js b/src/js/fc.js
index 4734eb8639..97512fe872 100644
--- a/src/js/fc.js
+++ b/src/js/fc.js
@@ -474,6 +474,12 @@ const FC = {
gyro_to_use: 0,
gyro_1_align: 0,
gyro_2_align: 0,
+ gyro_align_roll: 0,
+ gyro_align_pitch: 0,
+ gyro_align_yaw: 0,
+ mag_align_roll: 0,
+ mag_align_pitch: 0,
+ mag_align_yaw: 0,
};
this.PID_ADVANCED_CONFIG = {
diff --git a/src/js/msp/MSPHelper.js b/src/js/msp/MSPHelper.js
index cd43b4055a..8aea533504 100644
--- a/src/js/msp/MSPHelper.js
+++ b/src/js/msp/MSPHelper.js
@@ -514,7 +514,9 @@ MspHelper.prototype.process_data = function (dataHandler) {
FC.MOTOR_CONFIG.use_esc_sensor = data.readU8() != 0;
break;
case MSPCodes.MSP_COMPASS_CONFIG:
- FC.COMPASS_CONFIG.mag_declination = data.read16() / 10;
+ if (semver.gte(FC.CONFIG.apiVersion, API_VERSION_1_46)) {
+ FC.COMPASS_CONFIG.mag_declination = data.read16() / 10;
+ }
break;
case MSPCodes.MSP_GPS_CONFIG:
FC.GPS_CONFIG.provider = data.readU8();
@@ -633,6 +635,15 @@ MspHelper.prototype.process_data = function (dataHandler) {
FC.SENSOR_ALIGNMENT.gyro_to_use = data.readU8();
FC.SENSOR_ALIGNMENT.gyro_1_align = data.readU8();
FC.SENSOR_ALIGNMENT.gyro_2_align = data.readU8();
+ if (semver.gte(FC.CONFIG.apiVersion, API_VERSION_1_47)) {
+ FC.SENSOR_ALIGNMENT.gyro_align_roll = data.read16() / 10;
+ FC.SENSOR_ALIGNMENT.gyro_align_pitch = data.read16() / 10;
+ FC.SENSOR_ALIGNMENT.gyro_align_yaw = data.read16() / 10;
+
+ FC.SENSOR_ALIGNMENT.mag_align_roll = data.read16() / 10;
+ FC.SENSOR_ALIGNMENT.mag_align_pitch = data.read16() / 10;
+ FC.SENSOR_ALIGNMENT.mag_align_yaw = data.read16() / 10;
+ }
break;
case MSPCodes.MSP_DISPLAYPORT:
break;
@@ -773,14 +784,13 @@ MspHelper.prototype.process_data = function (dataHandler) {
FC.CONFIG.apiVersion = `${data.readU8()}.${data.readU8()}.0`;
break;
- case MSPCodes.MSP_FC_VARIANT: {
+ case MSPCodes.MSP_FC_VARIANT:
let fcVariantIdentifier = "";
for (let i = 0; i < 4; i++) {
fcVariantIdentifier += String.fromCharCode(data.readU8());
}
FC.CONFIG.flightControllerIdentifier = fcVariantIdentifier;
break;
- }
case MSPCodes.MSP_FC_VERSION:
FC.CONFIG.flightControllerVersion = `${data.readU8()}.${data.readU8()}.${data.readU8()}`;
@@ -899,7 +909,7 @@ MspHelper.prototype.process_data = function (dataHandler) {
console.log("Channel forwarding saved");
break;
- case MSPCodes.MSP_CF_SERIAL_CONFIG: {
+ case MSPCodes.MSP_CF_SERIAL_CONFIG:
FC.SERIAL_CONFIG.ports = [];
const bytesPerPort = 1 + 2 + 1 * 4;
@@ -917,7 +927,6 @@ MspHelper.prototype.process_data = function (dataHandler) {
FC.SERIAL_CONFIG.ports.push(serialPort);
}
break;
- }
case MSPCodes.MSP2_COMMON_SERIAL_CONFIG:
FC.SERIAL_CONFIG.ports = [];
@@ -1897,7 +1906,9 @@ MspHelper.prototype.crunch = function (code, modifierCode = undefined) {
buffer.push16(FC.GPS_RESCUE.initialClimbM);
break;
case MSPCodes.MSP_SET_COMPASS_CONFIG:
- buffer.push16(Math.round(10.0 * parseFloat(FC.COMPASS_CONFIG.mag_declination)));
+ if (semver.gte(FC.CONFIG.apiVersion, API_VERSION_1_46)) {
+ buffer.push16(Math.round(10.0 * parseFloat(FC.COMPASS_CONFIG.mag_declination)));
+ }
break;
case MSPCodes.MSP_SET_RSSI_CONFIG:
buffer.push8(FC.RSSI_CONFIG.channel);
@@ -2045,6 +2056,15 @@ MspHelper.prototype.crunch = function (code, modifierCode = undefined) {
.push8(FC.SENSOR_ALIGNMENT.gyro_to_use)
.push8(FC.SENSOR_ALIGNMENT.gyro_1_align)
.push8(FC.SENSOR_ALIGNMENT.gyro_2_align);
+ if (semver.gte(FC.CONFIG.apiVersion, API_VERSION_1_47)) {
+ buffer.push16(FC.SENSOR_ALIGNMENT.gyro_align_roll * 10);
+ buffer.push16(FC.SENSOR_ALIGNMENT.gyro_align_pitch * 10);
+ buffer.push16(FC.SENSOR_ALIGNMENT.gyro_align_yaw * 10);
+
+ buffer.push16(FC.SENSOR_ALIGNMENT.mag_align_roll * 10);
+ buffer.push16(FC.SENSOR_ALIGNMENT.mag_align_pitch * 10);
+ buffer.push16(FC.SENSOR_ALIGNMENT.mag_align_yaw * 10);
+ }
break;
case MSPCodes.MSP_SET_ADVANCED_CONFIG:
buffer
diff --git a/src/js/tabs/configuration.js b/src/js/tabs/configuration.js
index 719bb37264..b7339f1c50 100644
--- a/src/js/tabs/configuration.js
+++ b/src/js/tabs/configuration.js
@@ -6,9 +6,10 @@ import { mspHelper } from "../msp/MSPHelper";
import FC from "../fc";
import MSP from "../msp";
import MSPCodes from "../msp/MSPCodes";
-import { API_VERSION_1_45, API_VERSION_1_46 } from "../data_storage";
+import { API_VERSION_1_45, API_VERSION_1_46, API_VERSION_1_47 } from "../data_storage";
import { updateTabList } from "../utils/updateTabList";
import $ from "jquery";
+import { have_sensor } from "../sensor_helpers";
const configuration = {
analyticsChanges: {},
@@ -53,6 +54,11 @@ configuration.initialize = function (callback) {
: Promise.resolve(true),
)
.then(() => MSP.promise(MSPCodes.MSP_ADVANCED_CONFIG))
+ .then(() =>
+ semver.gte(FC.CONFIG.apiVersion, API_VERSION_1_46)
+ ? MSP.promise(MSPCodes.MSP_COMPASS_CONFIG)
+ : Promise.resolve(true),
+ )
.then(() => load_html());
}
@@ -116,53 +122,27 @@ configuration.initialize = function (callback) {
"Custom",
];
- const gyro_align_content_e = $(".tab-configuration .gyro_align_content");
- const legacy_gyro_alignment_e = $(".tab-configuration .legacy_gyro_alignment");
- const legacy_accel_alignment_e = $(".tab-configuration .legacy_accel_alignment");
-
- const orientation_gyro_e = $("select.gyroalign");
- const orientation_acc_e = $("select.accalign");
const orientation_mag_e = $("select.magalign");
const orientation_gyro_to_use_e = $("select.gyro_to_use");
const orientation_gyro_1_align_e = $("select.gyro_1_align");
const orientation_gyro_2_align_e = $("select.gyro_2_align");
- gyro_align_content_e.hide(); // default value
+ const hasMag =
+ have_sensor(FC.CONFIG.activeSensors, "mag") && semver.gte(FC.CONFIG.apiVersion, API_VERSION_1_46);
+
+ if (hasMag) {
+ $('input[name="mag_declination"]').val(FC.COMPASS_CONFIG.mag_declination.toFixed(1));
+ } else {
+ $("div.mag_declination").parent().parent().hide();
+ }
+
for (let i = 0; i < alignments.length; i++) {
- orientation_gyro_e.append(``);
- orientation_acc_e.append(``);
orientation_mag_e.append(``);
}
- orientation_gyro_e.val(FC.SENSOR_ALIGNMENT.align_gyro);
- orientation_acc_e.val(FC.SENSOR_ALIGNMENT.align_acc);
orientation_mag_e.val(FC.SENSOR_ALIGNMENT.align_mag);
- orientation_gyro_e.change(function () {
- let value = parseInt($(this).val());
-
- let newValue = undefined;
- if (value !== FC.SENSOR_ALIGNMENT.align_gyro) {
- newValue = $(this).find("option:selected").text();
- }
- self.analyticsChanges["GyroAlignment"] = newValue;
-
- FC.SENSOR_ALIGNMENT.align_gyro = value;
- });
-
- orientation_acc_e.change(function () {
- let value = parseInt($(this).val());
-
- let newValue = undefined;
- if (value !== FC.SENSOR_ALIGNMENT.align_acc) {
- newValue = $(this).find("option:selected").text();
- }
- self.analyticsChanges["AccAlignment"] = newValue;
-
- FC.SENSOR_ALIGNMENT.align_acc = value;
- });
-
orientation_mag_e.change(function () {
let value = parseInt($(this).val());
@@ -173,14 +153,12 @@ configuration.initialize = function (callback) {
self.analyticsChanges["MagAlignment"] = newValue;
FC.SENSOR_ALIGNMENT.align_mag = value;
+
+ toggleMagCustomAlignmentInputs();
});
// Multi gyro config
- gyro_align_content_e.show();
- legacy_gyro_alignment_e.hide();
- legacy_accel_alignment_e.hide();
-
const GYRO_DETECTION_FLAGS = {
DETECTED_GYRO_1: 1 << 0,
DETECTED_GYRO_2: 1 << 1,
@@ -217,6 +195,45 @@ configuration.initialize = function (callback) {
orientation_gyro_1_align_e.val(FC.SENSOR_ALIGNMENT.gyro_1_align);
orientation_gyro_2_align_e.val(FC.SENSOR_ALIGNMENT.gyro_2_align);
+ function toggleGyroCustomAlignmentInputs() {
+ if (semver.gte(FC.CONFIG.apiVersion, API_VERSION_1_47)) {
+ const customEnabled =
+ orientation_gyro_to_use_e.val() === "1" // 0 = gyro 1, 1 = gyro 2, 2 = both
+ ? FC.SENSOR_ALIGNMENT.gyro_2_align !== 9
+ : FC.SENSOR_ALIGNMENT.gyro_1_align !== 9;
+
+ $('input[name="gyro_align_roll"]').attr("disabled", customEnabled);
+ $('input[name="gyro_align_pitch"]').attr("disabled", customEnabled);
+ $('input[name="gyro_align_yaw"]').attr("disabled", customEnabled);
+ }
+ }
+
+ function toggleMagCustomAlignmentInputs() {
+ if (semver.gte(FC.CONFIG.apiVersion, API_VERSION_1_47)) {
+ $('input[name="mag_align_roll"]').attr("disabled", FC.SENSOR_ALIGNMENT.align_mag !== 9);
+ $('input[name="mag_align_pitch"]').attr("disabled", FC.SENSOR_ALIGNMENT.align_mag !== 9);
+ $('input[name="mag_align_yaw"]').attr("disabled", FC.SENSOR_ALIGNMENT.align_mag !== 9);
+ }
+ }
+
+ if (semver.gte(FC.CONFIG.apiVersion, API_VERSION_1_47)) {
+ $(".tab-configuration .gyro_align_custom").show();
+ $('input[name="gyro_align_roll"]').val(FC.SENSOR_ALIGNMENT.gyro_align_roll);
+ $('input[name="gyro_align_pitch"]').val(FC.SENSOR_ALIGNMENT.gyro_align_pitch);
+ $('input[name="gyro_align_yaw"]').val(FC.SENSOR_ALIGNMENT.gyro_align_yaw);
+
+ $(".tab-configuration .mag_align_custom").show();
+ $('input[name="mag_align_roll"]').val(FC.SENSOR_ALIGNMENT.mag_align_roll);
+ $('input[name="mag_align_pitch"]').val(FC.SENSOR_ALIGNMENT.mag_align_pitch);
+ $('input[name="mag_align_yaw"]').val(FC.SENSOR_ALIGNMENT.mag_align_yaw);
+
+ toggleGyroCustomAlignmentInputs();
+ toggleMagCustomAlignmentInputs();
+ } else {
+ $(".tab-configuration .gyro_align_custom").hide();
+ $(".tab-configuration .mag_align_custom").hide();
+ }
+
$(".gyro_alignment_inputs_first").toggle(detected_gyro_1);
$(".gyro_alignment_inputs_second").toggle(detected_gyro_2);
$(".gyro_alignment_inputs_selection").toggle(detected_gyro_1 || detected_gyro_2);
@@ -230,8 +247,9 @@ configuration.initialize = function (callback) {
newValue = $(this).find("option:selected").text();
}
self.analyticsChanges["Gyro1Alignment"] = newValue;
-
FC.SENSOR_ALIGNMENT.gyro_1_align = value;
+
+ toggleGyroCustomAlignmentInputs();
});
orientation_gyro_2_align_e.change(function () {
@@ -242,8 +260,9 @@ configuration.initialize = function (callback) {
newValue = $(this).find("option:selected").text();
}
self.analyticsChanges["Gyro2Alignment"] = newValue;
-
FC.SENSOR_ALIGNMENT.gyro_2_align = value;
+
+ toggleGyroCustomAlignmentInputs();
});
// Gyro and PID update
@@ -395,6 +414,16 @@ configuration.initialize = function (callback) {
FC.BOARD_ALIGNMENT_CONFIG.pitch = parseInt($('input[name="board_align_pitch"]').val());
FC.BOARD_ALIGNMENT_CONFIG.yaw = parseInt($('input[name="board_align_yaw"]').val());
+ if (semver.gte(FC.CONFIG.apiVersion, API_VERSION_1_47)) {
+ FC.SENSOR_ALIGNMENT.gyro_align_roll = parseInt($('input[name="gyro_align_roll"]').val());
+ FC.SENSOR_ALIGNMENT.gyro_align_pitch = parseInt($('input[name="gyro_align_pitch"]').val());
+ FC.SENSOR_ALIGNMENT.gyro_align_yaw = parseInt($('input[name="gyro_align_yaw"]').val());
+
+ FC.SENSOR_ALIGNMENT.mag_align_roll = parseInt($('input[name="mag_align_roll"]').val());
+ FC.SENSOR_ALIGNMENT.mag_align_pitch = parseInt($('input[name="mag_align_pitch"]').val());
+ FC.SENSOR_ALIGNMENT.mag_align_yaw = parseInt($('input[name="mag_align_yaw"]').val());
+ }
+
FC.CONFIG.accelerometerTrims[1] = parseInt($('input[name="roll"]').val());
FC.CONFIG.accelerometerTrims[0] = parseInt($('input[name="pitch"]').val());
@@ -407,6 +436,12 @@ configuration.initialize = function (callback) {
FC.ARMING_CONFIG.auto_disarm_delay = parseInt($('input[id="configurationAutoDisarmDelay"]').val());
}
}
+
+ // declination added first in #3676
+ if (hasMag) {
+ FC.COMPASS_CONFIG.mag_declination = $('input[name="mag_declination"]').val();
+ }
+
FC.ARMING_CONFIG.small_angle = parseInt($('input[id="configurationSmallAngle"]').val());
FC.SENSOR_ALIGNMENT.gyro_to_use = parseInt(orientation_gyro_to_use_e.val());
@@ -498,6 +533,14 @@ configuration.initialize = function (callback) {
: Promise.resolve(true),
)
.then(() => MSP.promise(MSPCodes.MSP_SET_RX_CONFIG, mspHelper.crunch(MSPCodes.MSP_SET_RX_CONFIG)))
+ .then(() =>
+ semver.gte(FC.CONFIG.apiVersion, API_VERSION_1_46)
+ ? MSP.promise(
+ MSPCodes.MSP_SET_COMPASS_CONFIG,
+ mspHelper.crunch(MSPCodes.MSP_SET_COMPASS_CONFIG),
+ )
+ : Promise.resolve(true),
+ )
.then(() => mspHelper.writeConfiguration(true));
}
diff --git a/src/js/tabs/gps.js b/src/js/tabs/gps.js
index a48e327be0..99d84c0379 100644
--- a/src/js/tabs/gps.js
+++ b/src/js/tabs/gps.js
@@ -23,10 +23,6 @@ gps.initialize = async function (callback) {
// mag support added in 1.46
const hasMag = have_sensor(FC.CONFIG.activeSensors, "mag") && semver.gte(FC.CONFIG.apiVersion, API_VERSION_1_46);
- if (hasMag) {
- await MSP.promise(MSPCodes.MSP_COMPASS_CONFIG);
- }
-
await MSP.promise(MSPCodes.MSP_GPS_CONFIG);
load_html();
@@ -64,15 +60,7 @@ gps.initialize = async function (callback) {
}
function get_attitude_data() {
- MSP.send_message(MSPCodes.MSP_ATTITUDE, false, false, load_compass_config);
- }
-
- function load_compass_config() {
- if (hasMag) {
- MSP.send_message(MSPCodes.MSP_COMPASS_CONFIG, false, false, get_imu_data);
- } else {
- get_imu_data();
- }
+ MSP.send_message(MSPCodes.MSP_ATTITUDE, false, false, get_imu_data);
}
function get_imu_data() {
@@ -198,13 +186,6 @@ gps.initialize = async function (callback) {
gpsBaudrateElement.prop("disabled", true);
gpsBaudrateElement.parent().hide();
- // fill magnetometer
- if (hasMag) {
- $('input[name="mag_declination"]').val(FC.COMPASS_CONFIG.mag_declination.toFixed(1));
- } else {
- $("div.mag_declination").hide();
- }
-
if (semver.lt(FC.CONFIG.apiVersion, API_VERSION_1_46)) {
$(".GPS_info td.positionalDop").parent().hide();
}
@@ -427,12 +408,8 @@ gps.initialize = async function (callback) {
// fill some data
FC.GPS_CONFIG.auto_baud = $('input[name="gps_auto_baud"]').is(":checked") ? 1 : 0;
FC.GPS_CONFIG.auto_config = $('input[name="gps_auto_config"]').is(":checked") ? 1 : 0;
- FC.COMPASS_CONFIG.mag_declination = $('input[name="mag_declination"]').val();
await MSP.promise(MSPCodes.MSP_SET_FEATURE_CONFIG, mspHelper.crunch(MSPCodes.MSP_SET_FEATURE_CONFIG));
- if (hasMag) {
- await MSP.promise(MSPCodes.MSP_SET_COMPASS_CONFIG, mspHelper.crunch(MSPCodes.MSP_SET_COMPASS_CONFIG));
- }
await MSP.promise(MSPCodes.MSP_SET_GPS_CONFIG, mspHelper.crunch(MSPCodes.MSP_SET_GPS_CONFIG));
mspHelper.writeConfiguration(true);
diff --git a/src/tabs/configuration.html b/src/tabs/configuration.html
index f1c3c90b19..8b731a95c5 100644
--- a/src/tabs/configuration.html
+++ b/src/tabs/configuration.html
@@ -151,28 +151,29 @@