diff --git a/locales/en/messages.json b/locales/en/messages.json
index ae156dc2bf..7d606011f0 100644
--- a/locales/en/messages.json
+++ b/locales/en/messages.json
@@ -3638,6 +3638,15 @@
"pidTuningVbatPidCompensationHelp": {
"message": "Increases the PID values to compensate when Vbat gets lower. This will give more constant flight characteristics throughout the flight. The amount of compensation that is applied is calculated from the $t(powerBatteryMaximum.message) set in the $t(tabPower.message) page, so make sure that is set to something appropriate."
},
+ "pidTuningVbatSagCompensation": {
+ "message": "Vbat Sag Compensation"
+ },
+ "pidTuningVbatSagCompensationHelp": {
+ "message": "Gives consistent throttle and PID performance over the usable battery voltage range by compensating for battery sag. The amount of compensation can be varied between 0 and 100%. Full compensation (100%) is recommended.
Visit this wiki entry for more info."
+ },
+ "pidTuningVbatSagValue": {
+ "message": "%"
+ },
"pidTuningItermRotation": {
"message": "I Term Rotation"
},
diff --git a/src/js/fc.js b/src/js/fc.js
index d0cc31510d..18588d45be 100644
--- a/src/js/fc.js
+++ b/src/js/fc.js
@@ -461,6 +461,7 @@ var FC = {
ff_interpolate_sp: 0,
ff_smooth_factor: 0,
ff_boost: 0,
+ vbat_sag_compensation: 0,
};
ADVANCED_TUNING_ACTIVE = { ...ADVANCED_TUNING };
diff --git a/src/js/msp/MSPHelper.js b/src/js/msp/MSPHelper.js
index 3872c6b4c4..83d2a9739d 100644
--- a/src/js/msp/MSPHelper.js
+++ b/src/js/msp/MSPHelper.js
@@ -1157,6 +1157,7 @@ MspHelper.prototype.process_data = function(dataHandler) {
ADVANCED_TUNING.ff_interpolate_sp = data.readU8();
ADVANCED_TUNING.ff_smooth_factor = data.readU8();
ADVANCED_TUNING.ff_boost = data.readU8();
+ ADVANCED_TUNING.vbat_sag_compensation = data.readU8();
}
}
}
@@ -2096,7 +2097,8 @@ MspHelper.prototype.crunch = function(code) {
if(semver.gte(CONFIG.apiVersion, API_VERSION_1_44)) {
buffer.push8(ADVANCED_TUNING.ff_interpolate_sp)
.push8(ADVANCED_TUNING.ff_smooth_factor)
- .push8(ADVANCED_TUNING.ff_boost);
+ .push8(ADVANCED_TUNING.ff_boost)
+ .push8(ADVANCED_TUNING.vbat_sag_compensation);
}
}
}
diff --git a/src/js/tabs/pid_tuning.js b/src/js/tabs/pid_tuning.js
index a29a6e89ea..73cbe71295 100644
--- a/src/js/tabs/pid_tuning.js
+++ b/src/js/tabs/pid_tuning.js
@@ -448,11 +448,21 @@ TABS.pid_tuning.initialize = function (callback) {
ffInterpolateCheck.change(function() {
const checked = $(this).is(':checked');
$('.ffInterpolateSp .suboption').toggle(checked);
- });
- ffInterpolateCheck.change();
+ }).change();
+
+ // Vbat Sag Compensation
+ const vbatSagCompensationCheck = $('input[id="vbatSagCompensation"]');
+ vbatSagCompensationCheck.prop('checked', ADVANCED_TUNING.vbat_sag_compensation !== 0);
+ $('input[name="vbatSagValue"]').val(ADVANCED_TUNING.vbat_sag_compensation > 0 ? ADVANCED_TUNING.vbat_sag_compensation : 100);
+
+ vbatSagCompensationCheck.change(function() {
+ const checked = $(this).is(':checked');
+ $('.vbatSagCompensation .suboption').toggle(checked);
+ }).change();
} else {
$('.ffInterpolateSp').hide();
+ $('.vbatSagCompensation').hide();
}
$('input[id="useIntegratedYaw"]').change(function() {
@@ -921,6 +931,7 @@ TABS.pid_tuning.initialize = function (callback) {
ADVANCED_TUNING.ff_smooth_factor = parseInt($('input[name="ffSmoothFactor"]').val());
ADVANCED_TUNING.ff_boost = parseInt($('input[name="ffBoost"]').val());
FILTER_CONFIG.dyn_lpf_curve_expo = parseInt($('.pid_filter input[name="dtermLowpassDynExpo"]').val());
+ ADVANCED_TUNING.vbat_sag_compensation = $('input[id="vbatSagCompensation"]').is(':checked') ? parseInt($('input[name="vbatSagValue"]').val()) : 0;
}
}
diff --git a/src/tabs/pid_tuning.html b/src/tabs/pid_tuning.html
index 2d02017448..e96edfa687 100644
--- a/src/tabs/pid_tuning.html
+++ b/src/tabs/pid_tuning.html
@@ -573,6 +573,21 @@
+