Warning: Some commands in CLI can result in arbitrary signals being sent on the motor output pins. This can cause motors to spin up if a battery is connected. Therefore it is highly recommended to make sure that no battery is connected before entering commands in CLI." + "message": "Note: Leaving CLI tab or pressing Disconnect will automatically send \"exit\" to the board. With the latest firmware this will make the controller restart and unsaved changes will be lost.
Warning: Some commands in CLI can result in arbitrary signals being sent on the motor output pins. This can cause motors to spin up if a battery is connected. Therefore it is highly recommended to make sure that no battery is connected before entering commands in CLI."
},
"cliInputPlaceholder": {
"message": "Write your command here. Press Tab for AutoComplete."
@@ -2870,7 +2884,7 @@
"message": "Save flash to file... (unsupported)"
},
"dataflashSavetoFileNote": {
- "message": "Directly saving flash to file is slow and inherently prone to error / file corruption.
In some cases it will work for small files, but this is not supported and support requests for it will be closed without comment - use Mass Storage mode instead."
+ "message": "Directly saving flash to file is slow and inherently prone to error / file corruption.
In some cases it will work for small files, but this is not supported and support requests for it will be closed without comment - use Mass Storage mode instead."
},
"dataflashSaveFileDepreciationHint": {
"message": "This method is slow and inherently prone to error / file corruption, because the MSP connection itself has intrinsic, fundamental limitations that make it unsuitable for file transfers. It may work for small log files only. Do not create support requests if file transfers fail when saved using this method. The recommended method is to use '$t(onboardLoggingRebootMscText.message)' (below) to activate the Mass Storage Mode, and access your flight controller as a storage device to download the log files."
@@ -2913,7 +2927,7 @@
"message": "No card inserted"
},
"sdcardStatusReboot": {
- "message": "Fatal error
Reboot to retry"
+ "message": "Fatal error
Reboot to retry"
},
"sdcardStatusReady": {
"message": "Card ready"
@@ -2965,7 +2979,7 @@
"message": "Download manually."
},
"firmwareFlasherTargetWarning": {
- "message": "IMPORTANT: Ensure you flash a file appropriate for your target. Flashing a binary for the wrong target can cause bad things to happen."
+ "message": "IMPORTANT: Ensure you flash a file appropriate for your target. Flashing a binary for the wrong target can cause bad things to happen."
},
"firmwareFlasherPath": {
@@ -2996,7 +3010,7 @@
"message": "Select or auto-detect your board to see available online firmware releases - Select the correct firmware appropriate for your board."
},
"firmwareFlasherOnlineSelectBoardHint": {
- "message": "Starting with Betaflight 4.1, Betaflight is introducing support for Unified Targets. The concept of Unified Targets means that the same firmware .hex file can be used for all boards using the same MCU (F4, F7). To make the different boards work with the same firmware, a specific configuration file is deployed alongside the firmware when a Unified Target is flashed.
This version of Betaflight configurator supports flashing of Unified Targets with the respective board specific configurations in one step. The different firmware types that are available for each board are shown in the drop-down as follows:
<board name> or
<board name> (Legacy):
non-unified target, or pre-4.1 versions of the firmware for Unified Targets.
<board name> (<manufacturer id>):
(4 character manufacturer id)
Unified Target.
Please use Unified Targets where available. If you encounter problems using a Unified Target, please open an issue and then use the non-unified target until the issue has been resolved."
+ "message": "Starting with Betaflight 4.1, Betaflight is introducing support for Unified Targets. The concept of Unified Targets means that the same firmware .hex file can be used for all boards using the same MCU (F4, F7). To make the different boards work with the same firmware, a specific configuration file is deployed alongside the firmware when a Unified Target is flashed.
This version of Betaflight configurator supports flashing of Unified Targets with the respective board specific configurations in one step. The different firmware types that are available for each board are shown in the drop-down as follows:
<board name> or
<board name> (Legacy):
non-unified target, or pre-4.1 versions of the firmware for Unified Targets.
<board name> (<manufacturer id>):
(4 character manufacturer id)
Unified Target.
Please use Unified Targets where available. If you encounter problems using a Unified Target, please open an issue and then use the non-unified target until the issue has been resolved."
},
"firmwareFlasherOnlineSelectFirmwareVersionDescription": {
"message": "Select firmware version for your board."
@@ -3567,7 +3581,7 @@
"message": "Scale Factor [%]"
},
"pidTuningMotorLimitHelp": {
- "message": "Motor output linear scale factor (as percentage). Reduces ESC current and motor heat when using higher cell count batteries, e.g. When using a 6S battery on a craft that has motors, props and tuning designed for 4S, try setting the value at 66%; when using a 4S battery on a craft intended for 3S, try 75%.
Always make sure that all of your components can support the voltage of the battery you are using."
+ "message": "Motor output linear scale factor (as percentage). Reduces ESC current and motor heat when using higher cell count batteries, e.g. When using a 6S battery on a craft that has motors, props and tuning designed for 4S, try setting the value at 66%; when using a 4S battery on a craft intended for 3S, try 75%.
Always make sure that all of your components can support the voltage of the battery you are using."
},
"pidTuningCellCount": {
"message": "Cell Count"
@@ -3579,8 +3593,7 @@
"message": "Profile independent Filter Settings"
},
"pidTuningFilterSlidersHelp": {
- "message": "Sliders to adjust the quad gyro and D-term filtering.
More Filtering gives you smoother flight, but also increases gyro signal delay (Phase Delay) to the PID loop which will result in worse aggressive flight performance, prop-wash handling, stick response and if excessive can cause oscillations.
Less Filtering reduces the gyro signal delay, but can increase motor temperatures due to the D-term reacting to the high frequency motor vibrations (noise).
Additionally, if filtering is excessively low, it will cause a decrease in flight performance (higher noise to signal ratio).",
- "description": "Overall helpicon message for filter tuning sliders"
+ "message": "Sliders to adjust the gyro and D-term filters.
Stronger filtering (sliders to left, lower cutoff frequencies) keeps motors cooler by removing more noise, but also increases gyro signal delay (phase delay) to the PID loop. This may worsen prop-wash and can make resonant oscillations worse. Less responsive quads eg X-Class often do well with stronger filtering.
Less Filtering (sliders to the right, higher cutoff frequencies) reduces gyro signal delay, and often improves propwash. Moving the gyro lowpass filter right is usually OK, but motors may get warm. Moving the D filter to the right is usually not required, and can quickly result in very hot motors."
},
"pidTuningSliderLowFiltering": {
"message": "Less Filtering",
@@ -3599,7 +3612,7 @@
"description": "Gyro filter tuning slider label"
},
"pidTuningGyroFilterSliderHelp": {
- "message": "Raises or Lowers the default Gyro Lowpass Filters in proportion to each-other. The gyro filtering is applied before the PID loop.
General motor noise ranges per quad class:
6\"+ quads - generally within 100hz to 330hz
5\" quads - generally within 220hz to 500hz
Whoop to 3\" quads - generally within 300hz to 850hz
Generally, you want to set the slider to have the Gyro Lowpass 1 Dynamic Min/Max Cutoff range cover the above.
However, for smoother flights use More Filtering on the slider. To get a more aggressive filter tune, use Less Filtering on the slider.
With Less Filtering BE CAREFUL to not get radical as to cause a fly-away or burn out motors.
Note frame resonance issues, bad bearings, and beat up props may cause you to need more filtering.",
+ "message": "Raises or Lowers the default Gyro Lowpass Filters in proportion to each-other. The gyro filtering is applied before the PID loop.
General motor noise ranges per quad class:
6\"+ quads - generally within 100hz to 330hz
5\" quads - generally within 220hz to 500hz
Whoop to 3\" quads - generally within 300hz to 850hz
Generally, you want to set the slider to have the Gyro Lowpass 1 Dynamic Min/Max Cutoff range cover the above.
However, for smoother flights use More Filtering on the slider. To get a more aggressive filter tune, use Less Filtering on the slider.
With Less Filtering BE CAREFUL to not get radical as to cause a fly-away or burn out motors.
Note frame resonance issues, bad bearings, and beat up props may cause you to need more filtering.",
"description": "Gyro filtering tuning slider helpicon message"
},
"pidTuningDTermFilterSlider": {
@@ -3607,11 +3620,11 @@
"description": "D Term filter tuning slider label"
},
"pidTuningDTermFilterSliderHelp": {
- "message": "Raises or Lower the default D-term Lowpass Filters in proportion to each-other.
The D-term filtering is applied after the PID loop, ONLY on the D-term, since it is the term most sensitive to noise and can amplify any high frequency noise by 10x to 100x plus.
Generally you want to move the D-term Filter slider up with the Gyro Filter slider. You want to have the D-term filter cutoffs well below the motor noise range for harder D-term filtering then what is applied on the entire gyro signal with the Gyro Filter Multiplier.
That recommended differential is built into the default and slider scaling.",
+ "message": "Changes the D-term Lowpass Filter cutoffs.
Moving the slider to the left gives stronger D filtering (lower cutoff frequency); to the right gives less filtering (higher cutoff frequency).
D-term is the most sensitive PID element to noise and resonance. It can amplify any high frequency noise by 10x to 100x plus. That's why the cutoffs for the D filters are much lower than the gyro filters.
D-term filtering is applied after - in addition to - the gyro filtering. Strong D filtering will reduce motor heat on noisy quads and can be useful with high PID 'D' values to minimise D resonance at medium to high frequencies. However, strong D filtering may delay the D signal, worsening propwash handling and encouraging lower frequency D resonances. The default D filtering is optimal for most quads. Larger machines with high D may do better with stronger D filtering than defaults. Moving the D lowpass filter slider to the right is generally not required. On very clean builds, going to the right can attenuate propwash. It should be done very cautiously since having less filtering on D can result in sudden resonances (including motor grinding or taking off on arming) and extreme motor heat.",
"description": "D Term filtering tuning slider helpicon message"
},
"pidTuningPidSlidersHelp": {
- "message": "Sliders to adjust the quad flight characteristics (PID gains)
Master Multiplier: Raises or Lowers all the PID gains (above) holding the proportional difference between the gains.
PD Balance: Adjusts the balance (ratio \\ proportional difference) between the P and D terms ('the spring' [p-term] and 'shock absorber' [d-term]).
PD Gain: Raises or Lowers the P&D gains together - holding the ratio (balance) between the two - for more (or less) PID control authority.
Stick Response Gain: Raises or Lowers the FeedForward gains to control the stick response feel of the quad.",
+ "message": "Sliders to adjust the quad flight characteristics (PID gains)
Damping (D gain): Resists fast movement, minimises P oscillation.
Tracking (P and I gain): Enchances the responsiveness of the quad, if too high may cause trilling or oscillation.
Stick Response (Feedforward): Increases the responsiveness of the quad to faster stick movements.
Drift - Wobble (I gain, expert): Fine adjustment of I.
Dynamic D (D Max, expert): Sets the maximum amount that D can be boosted to during fast movements.
Pitch Damping (Pitch:Roll D ratio, expert): Increases the amount of damping on pitch relative to roll.
Pitch Tracking (Pitch:Roll P, I and F ratio, expert): Increases stabilising strenght on pitch relative to roll.
Master Multiplier (all gains, expert): Raises or Lowers all the PID gains, keeping their proportions constant.",
"description": "Overall helpicon message for PID tuning sliders"
},
"pidTuningSliderWarning": {
@@ -3646,58 +3659,91 @@
"message": "Master Multiplier:",
"description": "Master tuning slider label"
},
- "pidTuningRollPitchRatioSlider": {
- "message": "Pitch-Roll Ratio:",
- "description": "Pitch-Roll Ratio slider label"
- },
- "pidTuningRollPitchRatioSliderHelp": {
- "message": "The Pitch-Roll Ratio is the balance of Moment of Inertia (MoI) between the Pitch and Roll axis.
Generally, the Pitch axis has a higher MoI and therefore it may be appropriate to have PID gains higher on the Pitch axis vs the Roll axis. However, on 'Stretched X', or other configurations, this may not be the case.
Generally for tuning, you are moving up the 'P and D Gain' slider until one axis begins to show D-term oscillation (a 'trilling' noise) and then back it down some. Blackbox is the easies method to determine which axis is 'trilling'. Once you find which axis is at the D-term limit, you can use the Pitch-Roll Gain slider to bring the other axis to just short of the same limit to balance out the quad for peak flight performance.",
- "description": "Pitch-Roll Ratio tuning slider helpicon message"
- },
- "pidTuningIGainSlider": {
- "message": "I-term Gain:",
- "description": "I-term slider label"
- },
- "pidTuningIGainSliderHelp": {
- "message": "I-term needs to be in balance with the P-term; similar to how the P-term needs to be in balance with the D-term (Tuning sequence: Filters -> D-term -> P-term -> I-term).
The I-term Gain sliders adjust I-term gains while holding P-term gains constant to adjust the ratio between the two terms.
If you are getting slow wobbles when you drop to 0% throttle, that is an idication the I-term gains is too high and you should lower the I-term Gain slider OR raise the P and D Gain slider if you have not tuned D-term and PD Balance yet (which you should first before loweing I-Term).
This said, genereally you want the I-term gains as strong as they can be (but within balance) to keep the quad tracking on the sticks in spirrel turns, orbits, ect...",
- "description": "I-gain Gain tuning slider helpicon message"
+ "pidTuningMasterSliderHelp": {
+ "message": "Increases all PID parameters equally. Don't change this slider unless you run out of adjustment on the other sliders. Typically this is only needed for low authority or high moment of inertia (MoI) quads like X-Class or cinelifter builds. Too much master gain may cause trilling oscillations or hot motors.",
+ "description": "Master Gain tuning slider helpicon message"
},
"pidTuningPDRatioSlider": {
"message": "PD Balance:",
"description": "PD balance tuning slider label"
},
+ "pidTuningPDRatioSliderHelp": {
+ "message": "Changes D and D max. Relatively high D will dampen stick responsiveness and may make motors hot, but should help control P-term oscillations and will improve prop-wash oscillation.
Relatively low D-term gives quicker stick responsiveness, but will weaken prop-wash performance and reacting to external forces (wind).",
+ "description": "D_term tuning slider helpicon message"
+ },
"pidTuningPDGainSlider": {
"message": "P and D Gain:",
"description": "P and D Gain tuning slider label"
},
- "pidTuningDMinRatioSlider": {
- "message": "D_min Gain drop:",
- "description": "D Min slider label"
- },
- "pidTuningDMinRatioSliderHelp": {
- "message": "Controls how much D-gains are suppressed in normal forward flight. Lower the slider to drop the D-gains MORE in normal forward flight. Raise the slider to drop D-gains LESS in normal forward flight.
With D_min enabled, the Active D-gain changes during flight. In normal forward flight (with D_min enabled) the Active D-gain hovers just above the D_min Gain values. During sharp stick moves or prop-wash, the Active D-gain raises to the D_max gains. See the D_min / D_max tips above for more detials.
Lower D-gains can help smooth out forward flight, negating the need to increase filtering on the Gyro and/or D-term in the Filters Setting tab; while it boost the Active D-gains to the D_max values when more D-term is needed to control overshooting and/or to stabiliize the quad in prop-wash conditions or to resist outside forces (wind).",
- "description": "D_min slider helpicon message"
- },
- "pidTuningResponseSlider": {
- "message": "Stick Response Gain:",
- "description": "Response tuning slider label"
- },
- "pidTuningMasterSliderHelp": {
- "message": "Generally larger quads need higher PID gains due to having a lower power to Moment of Inertia (MoI) ratio.
Smaller quads (micros) generally need lower PID gains due to a higher power to MoI ratio.
Higher values are for lower authority quads. Lower values are for higher authority quads.",
- "description": "Master Gain tuning slider helpicon message"
- },
- "pidTuningPDRatioSliderHelp":{
- "message": "Relatively high D-term will dampen stick responsiveness and may make motors hot, but should help control P-term oscillations and will improve prop-wash oscillation.
Relatively low D-term gives quicker stick responsiveness, but will weaken prop-wash performance and reacting to external forces (wind).",
- "description": "PD balance tuning slider helpicon message"
- },
"pidTuningPDGainSliderHelp":{
"message": "Lower P and D Gain will result in cooler motors but also in more prop-wash oscillation. Too low value may cause the quad to be unstable.
P and D terms work together to reduce prop-wash.
Higher values will increase motor heat and could increase oscillations during smooth forward flight due to higher D term gains.",
"description": "P and D gain tuning slider helpicon message"
},
- "pidTuningResponseSliderHelp":{
+ "pidTuningResponseSliderLegacy": {
+ "message": "Stick Response Gain:",
+ "description": "Response tuning slider label"
+ },
+ "pidTuningResponseSliderLegacyHelp": {
"message": "Lower FF values will worsen the stick response and may result in slow bounceback at the end of a flip or roll due to the quad lagging the sticks too much and I-term winding up and cousing 'I-term Bounceback'.
Higher FF values will give snappier stick responses in sharp moves. Excessively high FF values can cause overshoots and fast bounceback at the end of a flip or roll.
Note:
The feature I-term Relax can stop the I-term from winding up on stick move for a low authority quads or if low Stick Response Gains are used.",
"description": "Stick response gain tuning slider helpicon message"
},
+
+ "pidTuningDGainSlider": {
+ "message": "Damping:
D Gains",
+ "description": "D Gain (Damping) tuning slider label"
+ },
+ "pidTuningDGainSliderHelp": {
+ "message": "Relatively high D-gain will dampen stick responsiveness and may make motors hot, but should help control fast oscillations and willimprove prop-wash.
Relatively low D-term gives quicker stick responsiveness, but will weaken prop-wash performance and reacting to external forces (wind).",
+ "description": "D gain balance tuning slider helpicon message"
+ },
+ "pidTuningPIGainSlider": {
+ "message": "Tracking:
P & I Gains",
+ "description": "P and I Gain (Stability) tuning slider label"
+ },
+ "pidTuningPIGainSliderHelp": {
+ "message": "Increase the Tracking slider to sharpen the quads response to your commands and also outside influences; avoiding the nose of the quad going off course in any condition.
Lower ‘Tracking’ values will have lots of bobbles and will go off course on stick moves and in prop wash. High ‘Tracking’ may result in oscillation and fast bounceback (hard to see, but you canhear). Excessive Tracking may result in oscillations and hot motors.",
+ "description": "P and I gain tuning slider helpicon message"
+ },
+ "pidTuningResponseSlider": {
+ "message": "Stick Response:
FF Gains",
+ "description": "Response tuning slider label"
+ },
+ "pidTuningResponseSliderHelp": {
+ "message": "Lower Stick Response will increase the latency of the quad movements to commands and may result in slow bounceback at the end of a flip or roll. Higher Stick Response will give snappier quad response to sharp stick moves. Excessively high Stick Response can cause overshoots and fast bounceback at the end of a flip or roll.
Note:
The feature “I-term Relax” can stop bounceback for low authority quads or if low Stick Response Gains are used.",
+ "description": "Stick response gain tuning slider helpicon message"
+ },
+ "pidTuningIGainSlider": {
+ "message": "Drift - Wobble:
I Gains",
+ "description": "I-term slider label"
+ },
+ "pidTuningIGainSliderHelp": {
+ "message": "Increases or decreases I. Higher I may improve tracking in spiral turns, orbits, or 0% throttle commands. Too much I, particularly with not enough P, may cause wobbles or bounceback after flips/rolls or on chopping the throttle to 0%.
Generally you want the ‘Drift – Wobble’ slider to be as high as it can be to keep the quad tracking in spiral turns, orbits, ect... but not so high that you start to see wobbles on chopping the throttleto 0%.
Note:
If you experience bounceback at any time that is easy to see, make sure that “I-term Relax” is enabled, and try lowering the iterm_relax_cutoff value.",
+ "description": "I-gain Gain tuning slider helpicon message"
+ },
+ "pidTuningDMaxGainSlider": {
+ "message": "Dynamic Damping:
D Max",
+ "description": "D Min slider label"
+ },
+ "pidTuningDMaxGainSliderHelp": {
+ "message": "Increases D max, the maximum amount that D can increase to during faster movements.
For race quads, where the main Damping slider has been set low to minimize motor heat, moving this slider to the right will improve overshoot control for quick direction changes.
For HD or cinematic quads, instability in forward flight is best addressed by moving the Damping slider (not the Damping Boost slider) to the right. Always check for motor heat and listen for weird noises during quick inputs when adjusting this slider to the right.
For freestyle quads, especially heavier builds, moving this slider to the right may help control overshoot in flips and rolls.
Note:
Generally overshoot in flips and rolls is due to not enough 'i-Term Relax', or motor desyncs, or inadequate authority (a.k.a. Motor Saturation). If you find that moving the Damping Boost slider to the right doesn't improve flip or roll overshoot, put it back to the normal position, and seek out the reason for the overshoot or wobble.",
+ "description": "D_min slider helpicon message"
+ },
+ "pidTuningRollPitchRatioSlider": {
+ "message": "Pitch Damping:
Pitch:Roll D",
+ "description": "Pitch-Roll Ratio slider label"
+ },
+ "pidTuningRollPitchRatioSliderHelp": {
+ "message": "Increases Damping (D) on the Pitch axis ONLY, i.e, for Pitch relative to Roll. Helps control Pitch specific overshooting or bounce-back.
Quads with 'heavier' moment of inertia on the Pitch axis generally need more Damping authority (since Pitch has more inertia and accumulates more momentum).
Tune the master 'Damping' and/or 'Tracking' sliders first, until you get good Roll axis behavior. Then use the Pitch sliders (increase or decrease) to fine tune the Pitch axis without affecting Roll.",
+ "description": "Pitch-Roll Ratio tuning slider helpicon message"
+ },
+ "pidTuningPitchPIGainSlider": {
+ "message": "Pitch Tracking:
Pitch:Roll P & I",
+ "description": "Pitch P & I slider label"
+ },
+ "pidTuningPitchPIGainSliderHelp": {
+ "message": "Increases the Tracking strength on the Pitch axis ONLY, by changing Pitch P and I values relative to Roll. Allows stronger tracking authority on the Pitch axis relative to Roll.
Increase to stabilise pitch (nose) bobble with sharp pitch inputs or throttle chops. Also consider raising Anti-Gravity gains.
Tune the master 'Damping' and/or 'Tracking' sliders first, until you get good Roll axis behaviour. Then use the Pitch sliders (increase or decrease) to fine tune the Pitch axis without affecting Roll.",
+ "description": "Pitch P & I Gain tuning slider helpicon message"
+ },
"pidTuningGyroLowpassFiltersGroup": {
"message": "Gyro Lowpass Filters"
},
@@ -3722,8 +3768,11 @@
"pidTuningGyroLowpass2Type": {
"message": "Gyro Lowpass 2 Filter Type"
},
- "pidTuningLowpassFilterHelp": {
- "message": "The Lowpass Filters can have two variants: static and dynamic. For a determined lowpass filter number only one (static or dynamic) can be enabled at the same time. The static only has a Cutoff that is a value that defines in some way where the filter starts. The dynamic defines a min and max values, that is the range where the Cutoff is placed. This Cutoff moves from min to max at the same time than you move the throttle stick."
+ "pidTuningGyroLowpassFilterHelp": {
+ "message": "Gyro lowpass filters attenuate higher frequency noise to keep it out of the PID loop. There are two independently configurable gyro filters; by default both are active.
The first D lowpass can be static (fixed cutoff) or dynamic; the second D lowpass is always static. When a lowpass is in dynamic mode, filter will be stronger at low throttle, and the cutoff will go higher (less filtering) as throttle increases.
Without RPM filtering, both PT1 filters should be enabled at default (or stronger) cutoffs, with lowpass 1 in dynamic mode.
With RPM filtering, the gyro filter slider can often be moved some way to the right. On clean quads it can go all the way right, or alternatively a single static gyro lowpass filter at 500hz may be sufficient.
A quad will have less propwash with the least gyro filter delay (sliders to the right, higher cutoff values).
Always check for motor heat when shifting to less gyro filtering (sliders to the right). With minimal gyro filtering, it is essential to have enough D filtering! Take care!"
+ },
+ "pidTuningDTermLowpassFilterHelp": {
+ "message": "D-term lowpass filters attenuate higher frequency noise and resonances that would otherwise be amplified by D gain.
There are two D filters, and their effects are additive. By default, both are active and the filter type is PT1. Both are required in nearly all quads, though a single PT2 may be used in place of dual PT1's.
The first D lowpass can be static (fixed frequency) or dynamic; the second D lowpass is always static. When a lowpass is in dynamic mode, filtering will be stronger (lower cutoff frequency) at low throttle, and the cutoff will go higher (less filtering and less delay) as throttle increases.
Dynamic lowpass filtering is useful to provide strong D filtering at idle, where there is a risk of 'motor grinding' or unexpected flyways on arming, while giving less delay once in the air, for better propwash performance.
The transition from low to high cutoff will happen earlier, as throttle is increased, with higher D-term lowpass expo values. D lowpass expo can be used to fine-tune the amount of D filtering at different throttle points.
Generally, the quad will fly best and have least propwash with the lowest filter delay (sliders to the right, higher cutoff values), BUT, particularly with D filters, this will greatly increase the chance of getting hot motors.
It is very easy to burn motors if you don't have enough D filtering. Take care!"
},
"pidTuningGyroNotchFiltersGroup": {
"message": "Gyro Notch Filters"
@@ -3933,7 +3982,7 @@
"description": "Cutoff value of the I Term Relax"
},
"pidTuningItermRelaxCutoffHelp": {
- "message": "Lower values suppress bounce-back after flips in low authority quads, high values increase high-rate turn precision for racing.
Set to 30-40 for racing, 15 for responsive freestyle builds, 10 for heavier freestyle quads, 3-5 for X-class."
+ "message": "Lower values suppress bounce-back after flips in low authority quads, high values increase high-rate turn precision for racing.
Set to 30-40 for racing, 15 for responsive freestyle builds, 10 for heavier freestyle quads, 3-5 for X-class."
},
"pidTuningAbsoluteControlGain": {
"message": "Absolute Control"
@@ -4186,7 +4235,7 @@
"message": "To calibrate, use a multimeter to measure the actual voltage / current draw on your craft (with a battery plugged in), and enter the values below. Then, with the same battery still plugged in, click [Calibrate]."
},
"powerCalibrationManagerNote": {
- "message": "Note: Before calibrating the scale make sure that divider and multiplier for voltage and offset for amperage is set properly.
Leaving the values at 0 will not apply calibration.Remember to remove propellers before plugging in a battery!"
+ "message": "Note: Before calibrating the scale make sure that divider and multiplier for voltage and offset for amperage is set properly.
Leaving the values at 0 will not apply calibration.Remember to remove propellers before plugging in a battery!"
},
"powerCalibrationManagerWarning": {
"message": "Warning: The battery is not plugged in or voltage and amperage meter sources are not set properly. Make sure that the voltage and/or amperage are reading a value above 0. Otherwise you will not be able to calibrate using this tool."
@@ -4207,7 +4256,7 @@
"message": "Discard Calibration"
},
"powerCalibrationConfirmHelp": {
- "message": "New calibrated scales are shown here.
Applying them will set the scales but will not save them.
After saving make sure that the new voltage and current are correct."
+ "message": "New calibrated scales are shown here.
Applying them will set the scales but will not save them.
After saving make sure that the new voltage and current are correct."
},
"powerVoltageHead": {
"message": "Voltage Meter"
@@ -5087,7 +5136,7 @@
"description": "One of the elements of the OSD"
},
"osdDescElementEfficiency": {
- "message": "Instantaneous battery consumption in mAh/distance. (Requires valid GPS fix)"
+ "message": "Instantaneous battery consumption in mAh/distance. (Requires valid GPS fix)"
},
"osdTextTotalFlights": {
"message": "Total flights",
@@ -5535,7 +5584,7 @@
},
"vtxHelp": {
- "message": "Here you can configure the values for your Video Transmitter (VTX). You can view and change the transmission values, including the VTX Tables, if the flight controller and the VTX support it.
To set up your VTX use the following steps:
1. Go to this page;
2. Find the appropriate VTX configuration file for your country and your VTX model and download it;
3. Click '$t(vtxButtonLoadFile.message)' below, select the VTX configuration file, load it;
4. Verify that the settings are correct;
5. Click '$t(vtxButtonSave.message)' to store the VTX settings on the flight controller.
6. Optionally click '$t(vtxButtonSaveLua.message)' to save a lua configuration file you can use with the betaflight lua scripts (See more here.)",
+ "message": "Here you can configure the values for your Video Transmitter (VTX). You can view and change the transmission values, including the VTX Tables, if the flight controller and the VTX support it.
To set up your VTX use the following steps:
1. Go to this page;
2. Find the appropriate VTX configuration file for your country and your VTX model and download it;
3. Click '$t(vtxButtonLoadFile.message)' below, select the VTX configuration file, load it;
4. Verify that the settings are correct;
5. Click '$t(vtxButtonSave.message)' to store the VTX settings on the flight controller.
6. Optionally click '$t(vtxButtonSaveLua.message)' to save a lua configuration file you can use with the betaflight lua scripts (See more here.)",
"description": "Introduction message in the VTX tab"
},
"vtxMessageNotSupported": {
@@ -5703,7 +5752,7 @@
"description": "Help for the number of power levels field of the VTX Table element in the VTX tab"
},
"vtxTablePowerLevelsTableHelp": {
- "message": "This table represents the different values of power that can be used for the VTX. They are divided into two:
- $t(vtxTablePowerLevelsValue.message): each power level requires a value that is defined by the hardware manufacturer. Ask your manufacturer for the correct value or consult the Betaflight wiki of VTX Tables to grab some samples.
- $t(vtxTablePowerLevelsLabel.message): you can put here the label you want for each power level value. It can be numbers (25, 200, 600, 1.2), letters (OFF, MIN, MAX) or a mix of them.
You must configure only the power levels that are legal at your country.",
+ "message": "This table represents the different values of power that can be used for the VTX. They are divided into two:
- $t(vtxTablePowerLevelsValue.message): each power level requires a value that is defined by the hardware manufacturer. Ask your manufacturer for the correct value or consult the Betaflight wiki of VTX Tables to grab some samples.
- $t(vtxTablePowerLevelsLabel.message): you can put here the label you want for each power level value. It can be numbers (25, 200, 600, 1.2), letters (OFF, MIN, MAX) or a mix of them.
You must configure only the power levels that are legal at your country.",
"description": "Help for the table of power levels (value-label) that appears in the VTX tab"
},
"vtxTablePowerLevelsValue": {
@@ -5739,7 +5788,7 @@
"description": "Text of one of the titles of the VTX Table element in the VTX tab"
},
"vtxTableBandsChannelsTableHelp": {
- "message": "This table represents all the frequencies that can be used for your VTX. You can have several bands and for each band you must configure:
- $t(vtxTableBandTitleName.message): Name that you want to assign to this band, like BOSCAM_A, FATSHARK or RACEBAND.
- $t(vtxTableBandTitleLetter.message): Short letter that references the band.
- $t(vtxTableBandTitleFactory.message): This indicates if it is a factory band. If enabled Betaflight sends to the VTX a band and channel number. The VTX will then use its built-in frequency table and the frequencies configured here are only to show the value in the OSD and other places. If it is not enabled, then Betaflight will send to the VTX the real frequency configured here.
- Frequencies: Frequencies for this band.
Remember that not all frequencies are legal at your country. You must put a value of zero to each frequency index that you are not allowed to use to disable it.",
+ "message": "This table represents all the frequencies that can be used for your VTX. You can have several bands and for each band you must configure:
- $t(vtxTableBandTitleName.message): Name that you want to assign to this band, like BOSCAM_A, FATSHARK or RACEBAND.
- $t(vtxTableBandTitleLetter.message): Short letter that references the band.
- $t(vtxTableBandTitleFactory.message): This indicates if it is a factory band. If enabled Betaflight sends to the VTX a band and channel number. The VTX will then use its built-in frequency table and the frequencies configured here are only to show the value in the OSD and other places. If it is not enabled, then Betaflight will send to the VTX the real frequency configured here.
- Frequencies: Frequencies for this band.
Remember that not all frequencies are legal at your country. You must put a value of zero to each frequency index that you are not allowed to use to disable it.",
"description": "Help for the table of bands-channels that appears in the VTX tab"
},
@@ -5776,7 +5825,7 @@
"description": "Save Lua script button in the VTX tab"
},
"vtxLuaFileHelp" :{
- "message": "The '$t(vtxButtonSaveLua.message)' button will allow you to save a mcuid.lua file containing the VTX table configuration that can be used with the Betaflight TX Lua Scripts.
Version 1.6.0 and above can use the file as is, but for older versions of the scripts it should be renamed to match the modelname on the TX.",
+ "message": "The '$t(vtxButtonSaveLua.message)' button will allow you to save a mcuid.lua file containing the VTX table configuration that can be used with the Betaflight TX Lua Scripts.
Version 1.6.0 and above can use the file as is, but for older versions of the scripts it should be renamed to match the modelname on the TX.",
"description": "Tooltip message for the Save Lua script button in the VTX tab"
},
"vtxButtonLoadFile": {
@@ -5813,10 +5862,10 @@
"message": "ESC/Motor protocol"
},
"configurationEscProtocolHelp": {
- "message": "Select your motor protocol.
Make sure to verify the protocol is supported by your ESC, this information should be on the makers website.
Be carefull using DSHOT900 and DSHOT1200 as not many ESC's support it!"
+ "message": "Select your motor protocol.
Make sure to verify the protocol is supported by your ESC, this information should be on the makers website.
Be carefull using DSHOT900 and DSHOT1200 as not many ESC's support it!"
},
"configurationEscProtocolHelpNoDSHOT1200": {
- "message": "Select your motor protocol.
Make sure to verify the protocol is supported by your ESC, this information should be on the makers website."
+ "message": "Select your motor protocol.
Make sure to verify the protocol is supported by your ESC, this information should be on the makers website."
},
"configurationunsyndePwm": {
"message": "Motor PWM speed Separated from PID speed"
@@ -5829,7 +5878,7 @@
"description": "Feature for the ESC/Motor"
},
"configurationDshotBidirHelp": {
- "message": "Sends ESC data to the FC via DShot telemetry. Required by RPM Filtering and dynamic idle.
Note: Requires a compatible ESC with appropriate firmware, eg JESC, Jazzmac, BLHeli-32.",
+ "message": "Sends ESC data to the FC via DShot telemetry. Required by RPM Filtering and dynamic idle.
Note: Requires a compatible ESC with appropriate firmware, eg JESC, Jazzmac, BLHeli-32.",
"description": "Description of the Bidirectional DShot feature of the ESC/Motor"
},
"configurationGyroSyncDenom": {
@@ -5930,10 +5979,10 @@
"message": "Derivative from Error provides more direct stick response and is mostly prefered for Racing.
Derivative from Measurement provides smoother stick response what is more usefull for freestyling"
},
"pidTuningPidControllerTip": {
- "message": "Legacy vs Betaflight (float): PID scaling and PID logic is exactly the same. Not necessarily retune needed. Legacy is old betaflight evolved rewrite, which is basic PID controller based on integer math. Betaflight PID controller uses floating point math and has many new features specifically designed for multirotor applications
Float vs Integer: PID scaling and PID logic is exactly the same. No retune needed. F1 boards have no onboard FPU and floating point math increases CPU load and integer math will improve performance, but float math might gain slightly more precision."
+ "message": "Legacy vs Betaflight (float): PID scaling and PID logic is exactly the same. Not necessarily retune needed. Legacy is old betaflight evolved rewrite, which is basic PID controller based on integer math. Betaflight PID controller uses floating point math and has many new features specifically designed for multirotor applications
Float vs Integer: PID scaling and PID logic is exactly the same. No retune needed. F1 boards have no onboard FPU and floating point math increases CPU load and integer math will improve performance, but float math might gain slightly more precision."
},
"pidTuningFilterTip": {
- "message": "Gyro Soft Filter: Lowpass filter for gyro. Use lower value for more filtering.
D Term Filter: Lowpass filter for Dterm. Can affect D tuning. Use lower value for more filtering.
Yaw Filter: Filters yaw output. It can help on setups with noisy yaw axis."
+ "message": "Gyro Soft Filter: Lowpass filter for gyro. Use lower value for more filtering.
D Term Filter: Lowpass filter for Dterm. Can affect D tuning. Use lower value for more filtering.
Yaw Filter: Filters yaw output. It can help on setups with noisy yaw axis."
},
"pidTuningRatesTip": {
"message": "Play with the rates and see how those affect the stick curve"
diff --git a/src/css/tabs/pid_tuning.css b/src/css/tabs/pid_tuning.css
index 61d80af0..cf5297ee 100644
--- a/src/css/tabs/pid_tuning.css
+++ b/src/css/tabs/pid_tuning.css
@@ -93,6 +93,12 @@
border-bottom: 0 solid var(--subtleAccent);
}
+.tab-pid_tuning .sliderDivider {
+ padding: 3px;
+ border-top: 1px solid var(--subtleAccent);
+ border-bottom: 1px solid var(--subtleAccent);
+}
+
.tab-pid_tuning table th {
padding: 0;
border: 0;
diff --git a/src/js/TuningSliders.js b/src/js/TuningSliders.js
index ecc8cb0b..6687d5d1 100644
--- a/src/js/TuningSliders.js
+++ b/src/js/TuningSliders.js
@@ -1,14 +1,22 @@
'use strict';
const TuningSliders = {
- sliderPidsMode: 2,
- sliderMasterMultiplier: 1,
- sliderRollPitchRatio: 1,
- sliderIGain: 1,
+ // Legacy Sliders
+ sliderMasterMultiplierLegacy: 1,
sliderPDRatio: 1,
sliderPDGain: 1,
- sliderDMinRatio: 1,
+ sliderFeedforwardGainLegacy: 1,
+ // Firmware Sliders introduced in API 1.44
+ sliderPidsMode: 2,
+ sliderDGain: 1,
+ sliderPIGain: 1,
sliderFeedforwardGain: 1,
+ sliderDMaxGain: 1,
+ sliderIGain: 1,
+ sliderRollPitchRatio: 1,
+ sliderPitchPIGain: 1,
+ sliderMasterMultiplier: 1,
+
pidSlidersUnavailable: false,
GyroSliderUnavailable: false,
DTermSliderUnavailable: false,
@@ -23,6 +31,8 @@ const TuningSliders = {
defaultPDRatio: 0,
PID_DEFAULT: [],
FILTER_DEFAULT: {},
+ SLIDER_DEFAULT: {},
+ initialSettings: {},
cachedPidSliderValues: false,
cachedGyroSliderValues: false,
@@ -33,6 +43,60 @@ const TuningSliders = {
const D_MIN_RATIO = 0.85;
+TuningSliders.saveInitialSettings = function () {
+ if (semver.gte(FC.CONFIG.apiVersion, API_VERSION_1_44)) {
+ this.initialSettings.sliderPidsMode = FC.TUNING_SLIDERS.slider_pids_mode;
+ this.initialSettings.sliderDGain = FC.TUNING_SLIDERS.slider_d_gain / 100;
+ this.initialSettings.sliderPIGain = FC.TUNING_SLIDERS.slider_pi_gain / 100;
+ this.initialSettings.sliderFeedforwardGain = FC.TUNING_SLIDERS.slider_feedforward_gain / 100;
+ this.initialSettings.sliderDMaxGain = FC.TUNING_SLIDERS.slider_dmax_gain / 100;
+ this.initialSettings.sliderIGain = FC.TUNING_SLIDERS.slider_i_gain / 100;
+ this.initialSettings.sliderRollPitchRatio = FC.TUNING_SLIDERS.slider_roll_pitch_ratio / 100;
+ this.initialSettings.sliderPitchPIGain = FC.TUNING_SLIDERS.slider_pitch_pi_gain / 100;
+ this.initialSettings.sliderMasterMultiplier = FC.TUNING_SLIDERS.slider_master_multiplier / 100;
+ this.initialSettings.sliderGyroFilter = FC.TUNING_SLIDERS.slider_gyro_filter;
+ this.initialSettings.sliderGyroFilterMultiplier = FC.TUNING_SLIDERS.slider_gyro_filter_multiplier / 100;
+ this.initialSettings.sliderDTermFilter = FC.TUNING_SLIDERS.slider_dterm_filter;
+ this.initialSettings.sliderDTermFilterMultiplier = FC.TUNING_SLIDERS.slider_dterm_filter_multiplier / 100;
+ }
+};
+
+TuningSliders.restoreInitialSettings = function () {
+ if (semver.gte(FC.CONFIG.apiVersion, API_VERSION_1_44)) {
+ if (this.sliderModeHasChanged && this.initialSetting.sliderPidsMode !== this.sliderPidsmode) {
+ $('#sliderPidsModeSelect').val(this.initialSettings.sliderPidsMode).trigger('change');
+ }
+
+ FC.TUNING_SLIDERS.slider_pids_mode = this.initialSettings.sliderPidsMode;
+
+ FC.TUNING_SLIDERS.slider_d_gain = Math.round(this.initialSettings.sliderDGain * 20) * 5;
+ FC.TUNING_SLIDERS.slider_pi_gain = Math.round(this.initialSettings.sliderPIGain * 20) * 5;
+ FC.TUNING_SLIDERS.slider_feedforward_gain = Math.round(this.initialSettings.sliderFeedforwardGain * 20) * 5;
+ FC.TUNING_SLIDERS.slider_dmax_gain = Math.round(this.initialSettings.sliderDMaxGain * 20) * 5;
+ FC.TUNING_SLIDERS.slider_i_gain = Math.round(this.initialSettings.sliderIGain * 20) * 5;
+ FC.TUNING_SLIDERS.slider_roll_pitch_ratio = Math.round(this.initialSettings.sliderRollPitchRatio * 20) * 5;
+ FC.TUNING_SLIDERS.slider_pitch_pi_gain = Math.round(this.initialSettings.sliderPitchPIGain * 20) * 5;
+ FC.TUNING_SLIDERS.slider_master_multiplier = Math.round(this.initialSettings.sliderMasterMultiplier * 20) * 5;
+
+ FC.TUNING_SLIDERS.slider_gyro_filter = this.initialSettings.sliderGyroFilter;
+ FC.TUNING_SLIDERS.slider_gyro_filter_multiplier = this.initialSettings.sliderGyroFilterMultiplier * 100;
+ FC.TUNING_SLIDERS.slider_dterm_filter = this.initialSettings.sliderDTermFilter;
+ FC.TUNING_SLIDERS.slider_dterm_filter_multiplier = this.initialSettings.sliderDTermFilterMultiplier * 100;
+
+ MSP.promise(MSPCodes.MSP_SET_TUNING_SLIDERS, mspHelper.crunch(MSPCodes.MSP_SET_TUNING_SLIDERS))
+ .then(() => MSP.promise(MSPCodes.MSP_PID))
+ .then(() => MSP.promise(MSPCodes.MSP_PID_ADVANCED))
+ .then(() => MSP.promise(MSPCodes.MSP_FILTER_CONFIG))
+ .then(() => {
+ TABS.pid_tuning.configChanges = {};
+ if (GUI.active_tab === 'pid_tuning') {
+ this.updateFormPids();
+ TABS.pid_tuning.updatePIDColors();
+ }
+ });
+ }
+};
+
TuningSliders.setDMinFeatureEnabled = function(dMinFeatureEnabled) {
this.dMinFeatureEnabled = dMinFeatureEnabled;
if (this.dMinFeatureEnabled) {
@@ -45,6 +109,7 @@ TuningSliders.setDMinFeatureEnabled = function(dMinFeatureEnabled) {
TuningSliders.initialize = function() {
this.PID_DEFAULT = FC.getPidDefaults();
this.FILTER_DEFAULT = FC.getFilterDefaults();
+ this.SLIDER_DEFAULT = FC.getSliderDefaults();
if (semver.lt(FC.CONFIG.apiVersion, API_VERSION_1_44)) {
this.setDMinFeatureEnabled($('#dMinSwitch').is(':checked'));
@@ -67,20 +132,27 @@ TuningSliders.initialize = function() {
TuningSliders.setExpertMode = function() {
this.expertMode = isExpertModeEnabled();
+ $('#slidersPidsBox, #slidersFilterBox').toggleClass('nonExpertModeSliders', !this.expertMode);
if (semver.gte(FC.CONFIG.apiVersion, API_VERSION_1_44)) {
- const dMinShow = parseInt($('.pid_tuning input[name="dMinRoll"]').val()) !== 0;
- $('.tab-pid_tuning .MasterSlider').toggle(this.expertMode);
- $('.tab-pid_tuning .DMinRatioSlider').toggle(this.expertMode && dMinShow);
+ // TODO: reset nonExpertModeSliders - changes after first movement
+
+ $('.tab-pid_tuning .DMaxGainSlider').toggle(this.expertMode);
$('.tab-pid_tuning .advancedSlider').toggle(this.expertMode);
+ $('.tab-pid_tuning .masterSlider').toggle(this.expertMode);
+ $('.tab-pid_tuning .legacySlider').hide();
+ $('.subtab-pid .nonExpertModeSlidersNote').toggle(!this.pidSlidersUnavailable && !this.expertMode);
+ $('.subtab-filter .nonExpertModeSlidersNote').toggle((!this.GyroSliderUnavailable || !this.DTermSliderUnavailable) && !this.expertMode);
} else {
- $('#slidersPidsBox, #slidersFilterBox').toggleClass('nonExpertModeSliders', !this.expertMode);
+ const dMinShow = parseInt($('.pid_tuning input[name="dMinRoll"]').val()) !== 0;
+ $('.tab-pid_tuning .DMaxGainSlider').toggle(this.expertMode && dMinShow);
$('.tab-pid_tuning .advancedSlider').hide();
- $('.tab-pid_tuning .DMinRatioSlider').hide();
+ $('.tab-pid_tuning .DMaxGainSlider').hide();
+ $('.tab-pid_tuning .baseSlider').hide();
}
};
TuningSliders.scaleSliderValue = function(value) {
- if (value > 1) {
+ if (value > 0) {
return Math.round(((value - 1) * 2 + 1) * 100) / 100;
} else {
return value;
@@ -88,7 +160,7 @@ TuningSliders.scaleSliderValue = function(value) {
};
TuningSliders.downscaleSliderValue = function(value) {
- if (value > 1) {
+ if (value > 0) {
return (value - 1) / 2 + 1;
} else {
return value;
@@ -96,43 +168,56 @@ TuningSliders.downscaleSliderValue = function(value) {
};
TuningSliders.initPidSlidersPosition = function() {
- if (semver.lt(FC.CONFIG.apiVersion, API_VERSION_1_44)) {
+ if (semver.gte(FC.CONFIG.apiVersion, API_VERSION_1_44)) {
+ this.sliderPidsMode = FC.TUNING_SLIDERS.slider_pids_mode;
+ this.sliderDGain = FC.TUNING_SLIDERS.slider_d_gain / 100;
+ this.sliderPIGain = FC.TUNING_SLIDERS.slider_pi_gain / 100;
+ this.sliderFeedforwardGain = FC.TUNING_SLIDERS.slider_feedforward_gain / 100;
+ this.sliderDMaxGain = FC.TUNING_SLIDERS.slider_dmax_gain / 100;
+ this.sliderIGain = FC.TUNING_SLIDERS.slider_i_gain / 100;
+ this.sliderRollPitchRatio = FC.TUNING_SLIDERS.slider_roll_pitch_ratio / 100;
+ this.sliderPitchPIGain = FC.TUNING_SLIDERS.slider_pitch_pi_gain / 100;
+ this.sliderMasterMultiplier = FC.TUNING_SLIDERS.slider_master_multiplier / 100;
+
+ $('output[name="sliderDGain-number"]').val(this.sliderDGain);
+ $('output[name="sliderPIGain-number"]').val(this.sliderPIGain);
+ $('output[name="sliderFeedforwardGain-number"]').val(this.sliderFeedforwardGain);
+ $('output[name="sliderDMaxGain-number"]').val(this.sliderDMaxGain);
+ $('output[name="sliderIGain-number"]').val(this.sliderIGain);
+ $('output[name="sliderRollPitchRatio-number"]').val(this.sliderRollPitchRatio);
+ $('output[name="sliderPitchPIGain-number"]').val(this.sliderPitchPIGain);
+ $('output[name="sliderMasterMultiplier-number"]').val(this.sliderMasterMultiplier);
+
+ $('#sliderDGain').val(this.downscaleSliderValue(this.sliderDGain));
+ $('#sliderPIGain').val(this.downscaleSliderValue(this.sliderPIGain));
+ $('#sliderFeedforwardGain').val(this.sliderFeedforwardGain);
+ $('#sliderDMaxGain').val(this.sliderDMaxGain);
+ $('#sliderIGain').val(this.downscaleSliderValue(this.sliderIGain));
+ $('#sliderRollPitchRatio').val(this.downscaleSliderValue(this.sliderRollPitchRatio));
+ $('#sliderPitchPIGain').val(this.downscaleSliderValue(this.sliderPitchPIGain));
+ $('#sliderMasterMultiplier').val(this.downscaleSliderValue(this.sliderMasterMultiplier));
+ } else {
// used to estimate PID slider positions based on PIDF values, and set respective slider position
// provides only an estimation due to limitation of feature without firmware support, to be improved in later versions
- this.sliderMasterMultiplier = Math.round(FC.PIDS[2][1] / this.PID_DEFAULT[11] * 10) / 10;
+ this.sliderMasterMultiplierLegacy = Math.round(FC.PIDS[2][1] / this.PID_DEFAULT[11] * 10) / 10;
this.sliderPDRatio = Math.round(FC.PIDS[0][2] / FC.PIDS[0][0] / this.defaultPDRatio * 10) / 10;
if (this.dMinFeatureEnabled) {
- this.sliderPDGain = Math.round(FC.ADVANCED_TUNING.dMinRoll / this.sliderPDRatio / this.sliderMasterMultiplier / this.PID_DEFAULT[3] * 10) / 10;
+ this.sliderPDGain = Math.round(FC.ADVANCED_TUNING.dMinRoll / this.sliderPDRatio / this.sliderMasterMultiplierLegacy / this.PID_DEFAULT[3] * 10) / 10;
} else {
- this.sliderPDGain = Math.round(FC.PIDS[0][0] / this.sliderMasterMultiplier / (this.PID_DEFAULT[2] * (1 / D_MIN_RATIO)) * 10) / 10;
+ this.sliderPDGain = Math.round(FC.PIDS[0][0] / this.sliderMasterMultiplierLegacy / (this.PID_DEFAULT[2] * (1 / D_MIN_RATIO)) * 10) / 10;
}
- this.sliderFeedforwardGain = Math.round(FC.ADVANCED_TUNING.feedforwardRoll / this.sliderMasterMultiplier / this.PID_DEFAULT[4] * 10) / 10;
- } else {
- this.sliderPidsMode = FC.TUNING_SLIDERS.slider_pids_mode;
- this.sliderMasterMultiplier = FC.TUNING_SLIDERS.slider_master_multiplier / 100;
- this.sliderRollPitchRatio = FC.TUNING_SLIDERS.slider_roll_pitch_ratio / 100;
- this.sliderIGain = FC.TUNING_SLIDERS.slider_i_gain / 100;
- this.sliderPDRatio = FC.TUNING_SLIDERS.slider_pd_ratio / 100;
- this.sliderPDGain = FC.TUNING_SLIDERS.slider_pd_gain / 100;
- this.sliderDMinRatio = FC.TUNING_SLIDERS.slider_dmin_ratio / 100;
- this.sliderFeedforwardGain = FC.TUNING_SLIDERS.slider_feedforward_gain / 100;
+ this.sliderFeedforwardGainLegacy = Math.round(FC.ADVANCED_TUNING.feedforwardRoll / this.sliderMasterMultiplierLegacy / this.PID_DEFAULT[4] * 10) / 10;
+
+ $('output[name="sliderMasterMultiplierLegacy-number"]').val(this.sliderMasterMultiplierLegacy);
+ $('output[name="sliderPDRatio-number"]').val(this.sliderPDRatio);
+ $('output[name="sliderPDGain-number"]').val(this.sliderPDGain);
+ $('output[name="sliderFeedforwardGainLegacy-number"]').val(this.sliderFeedforwardGainLegacy);
+
+ $('#sliderMasterMultiplierLegacy').val(this.downscaleSliderValue(this.sliderMasterMultiplierLegacy));
+ $('#sliderPDRatio').val(this.downscaleSliderValue(this.sliderPDRatio));
+ $('#sliderPDGain').val(this.downscaleSliderValue(this.sliderPDGain));
+ $('#sliderFeedforwardGainLegacy').val(this.downscaleSliderValue(this.sliderFeedforwardGainLegacy));
}
-
- $('output[name="sliderMasterMultiplier-number"]').val(this.sliderMasterMultiplier);
- $('output[name="sliderRollPitchRatio-number"]').val(this.sliderRollPitchRatio);
- $('output[name="sliderIGain-number"]').val(this.sliderIGain);
- $('output[name="sliderPDRatio-number"]').val(this.sliderPDRatio);
- $('output[name="sliderPDGain-number"]').val(this.sliderPDGain);
- $('output[name="sliderDMinRatio-number"]').val(this.sliderDMinRatio);
- $('output[name="sliderFeedforwardGain-number"]').val(this.sliderFeedforwardGain);
-
- $('#sliderMasterMultiplier').val(this.downscaleSliderValue(this.sliderMasterMultiplier));
- $('#sliderRollPitchRatio').val(this.downscaleSliderValue(this.sliderRollPitchRatio));
- $('#sliderIGain').val(this.downscaleSliderValue(this.sliderIGain));
- $('#sliderPDRatio').val(this.downscaleSliderValue(this.sliderPDRatio));
- $('#sliderPDGain').val(this.downscaleSliderValue(this.sliderPDGain));
- $('#sliderDMinRatio').val(this.downscaleSliderValue(this.sliderDMinRatio));
- $('#sliderFeedforwardGain').val(this.downscaleSliderValue(this.sliderFeedforwardGain));
};
TuningSliders.initGyroFilterSliderPosition = function() {
@@ -158,30 +243,57 @@ TuningSliders.initDTermFilterSliderPosition = function() {
}
$('output[name="sliderDTermFilterMultiplier-number"]').val(this.sliderDTermFilterMultiplier);
- $('#sliderDTermFilterMultiplier').val(this.downscaleSliderValue(this.sliderDTermFilterMultiplier));
+ $('#sliderDTermFilterMultiplier').val(this.sliderDTermFilterMultiplier);
+};
+
+TuningSliders.resetDefault = function() {
+ FC.TUNING_SLIDERS.slider_pids_mode = this.SLIDER_DEFAULT.slider_pids_mode;
+ FC.TUNING_SLIDERS.slider_d_gain = this.SLIDER_DEFAULT.slider_d_gain;
+ FC.TUNING_SLIDERS.slider_pi_gain = this.SLIDER_DEFAULT.slider_pi_gain;
+ FC.TUNING_SLIDERS.slider_feedforward_gain = this.SLIDER_DEFAULT.slider_feedforward_gain;
+ FC.TUNING_SLIDERS.slider_dmax_gain = this.SLIDER_DEFAULT.slider_dmax_gain;
+ FC.TUNING_SLIDERS.slider_i_gain = this.SLIDER_DEFAULT.slider_i_gain;
+ FC.TUNING_SLIDERS.slider_roll_pitch_ratio = this.SLIDER_DEFAULT.slider_roll_pitch_ratio;
+ FC.TUNING_SLIDERS.slider_pitch_pi_gain = this.SLIDER_DEFAULT.slider_pitch_pi_gain;
+ FC.TUNING_SLIDERS.slider_master_multiplier = this.SLIDER_DEFAULT.slider_master_multiplier;
+
+ FC.TUNING_SLIDERS.slider_gyro_filter = this.SLIDER_DEFAULT.slider_gyro_filter;
+ FC.TUNING_SLIDERS.slider_gyro_filter_multiplier = this.SLIDER_DEFAULT.slider_gyro_filter_multiplier;
+ FC.TUNING_SLIDERS.slider_dterm_filter = this.SLIDER_DEFAULT.slider_dterm_filter;
+ FC.TUNING_SLIDERS.slider_dterm_filter_multiplier = this.SLIDER_DEFAULT.slider_dterm_filter_multiplier;
};
TuningSliders.resetPidSliders = function() {
if (!this.cachedPidSliderValues) {
- this.sliderMasterMultiplier = 1;
- this.sliderRollPitchRatio = 1;
- this.sliderIGain = 1;
- this.sliderPDRatio = 1;
- this.sliderPDGain = 1;
- this.sliderDMinRatio = 1;
- this.sliderFeedforwardGain = 1;
+ if (semver.gte(FC.CONFIG.apiVersion, API_VERSION_1_44)) {
+ this.sliderDGain = this.SLIDER_DEFAULT.slider_d_gain / 100;
+ this.sliderPIGain = this.SLIDER_DEFAULT.slider_pi_gain / 100;
+ this.sliderFeedforwardGain = this.SLIDER_DEFAULT.slider_feedforward_gain / 100;
+ this.sliderDMaxGain = this.SLIDER_DEFAULT.slider_dmax_gain / 100;
+ this.sliderIGain = this.SLIDER_DEFAULT.slider_i_gain / 100;
+ this.sliderRollPitchRatio = this.SLIDER_DEFAULT.slider_roll_pitch_ratio / 100;
+ this.sliderPitchPIGain = this.SLIDER_DEFAULT.slider_pitch_pi_gain / 100;
+ this.sliderMasterMultiplier = this.SLIDER_DEFAULT.slider_master_multiplier / 100;
+ } else {
+ this.sliderMasterMultiplierLegacy = 1;
+ this.sliderPDRatio = 1;
+ this.sliderPDGain = 1;
+ this.sliderFeedforwardGainLegacy = 1;
+ }
}
- if (semver.lt(FC.CONFIG.apiVersion, API_VERSION_1_44)) {
- $('#sliderMasterMultiplier').val(this.downscaleSliderValue(this.sliderMasterMultiplier));
+ if (semver.gte(FC.CONFIG.apiVersion, API_VERSION_1_44)) {
+ this.calculateNewPids();
+ this.updateFormPids();
+ this.initPidSlidersPosition();
+ this.updatePidSlidersDisplay();
+ } else {
+ $('#sliderMasterMultiplierLegacy').val(this.downscaleSliderValue(this.sliderMasterMultiplierLegacy));
$('#sliderPDRatio').val(this.downscaleSliderValue(this.sliderPDRatio));
$('#sliderPDGain').val(this.downscaleSliderValue(this.sliderPDGain));
- $('#sliderFeedforwardGain').val(this.downscaleSliderValue(this.sliderFeedforwardGain));
- } else {
- this.initPidSlidersPosition();
+ $('#sliderFeedforwardGainLegacy').val(this.downscaleSliderValue(this.sliderFeedforwardGainLegacy));
+ this.calculateNewPids();
}
-
- this.calculateNewPids();
};
TuningSliders.resetGyroFilterSlider = function() {
@@ -252,24 +364,57 @@ TuningSliders.legacyUpdateFilterSlidersDisplay = function() {
}
};
+TuningSliders.updateSwitchBoxes = function() {
+ const FF_SWITCH = FC.ADVANCED_TUNING.feedforwardRoll || FC.ADVANCED_TUNING.feedforwardPitch || FC.ADVANCED_TUNING.feedforwardYaw;
+ $('input[id="feedforwardGroup"]').prop('checked', FF_SWITCH).trigger('change');
+
+ const DMIN_SWITCH = FC.PIDS[0][2] !== FC.ADVANCED_TUNING.dMinRoll || FC.PIDS[1][2] !== FC.ADVANCED_TUNING.dMinPitch || FC.PIDS[2][2] !== FC.ADVANCED_TUNING.dMinYaw;
+ $('#dMinSwitch').prop('checked', DMIN_SWITCH).trigger('change');
+};
+
+TuningSliders.updateSlidersWarning = function(slidersUnavailable = false) {
+ const WARNING_P_GAIN = 70;
+ let WARNING_I_GAIN = 120;
+ const WARNING_DMAX_GAIN = 60;
+ const WARNING_DMIN_GAIN = 40;
+ if (semver.gte(FC.CONFIG.apiVersion, API_VERSION_1_44)) {
+ WARNING_I_GAIN = 2.5 * FC.PIDS[1][0];
+ }
+ $('.subtab-pid .slidersWarning').toggle((FC.PIDS[1][0] > WARNING_P_GAIN || FC.PIDS[1][1] > WARNING_I_GAIN || FC.PIDS[1][2] > WARNING_DMAX_GAIN ||
+ FC.ADVANCED_TUNING.dMinPitch > WARNING_DMIN_GAIN) && !slidersUnavailable);
+};
+
+TuningSliders.updateFilterSlidersWarning = function(gyroSliderUnavailable = false, DTermSliderUnavailable = false) {
+ const WARNING_FILTER_LOW_GAIN = 0.7;
+ let WARNING_FILTER_GYRO_HIGH_GAIN = 1.4;
+ let WARNING_FILTER_DTERM_HIGH_GAIN = 1.4;
+ if (semver.gte(FC.CONFIG.apiVersion, API_VERSION_1_44)) {
+ WARNING_FILTER_GYRO_HIGH_GAIN = 1.5;
+ WARNING_FILTER_DTERM_HIGH_GAIN = 1.1;
+ }
+ $('.subtab-filter .slidersWarning').toggle(((this.sliderGyroFilterMultiplier >= WARNING_FILTER_GYRO_HIGH_GAIN ||
+ this.sliderGyroFilterMultiplier <= WARNING_FILTER_LOW_GAIN) && !gyroSliderUnavailable) ||
+ ((this.sliderDTermFilterMultiplier >= WARNING_FILTER_DTERM_HIGH_GAIN ||
+ this.sliderDTermFilterMultiplier <= WARNING_FILTER_LOW_GAIN) && !DTermSliderUnavailable));
+};
+
+
TuningSliders.updatePidSlidersDisplay = function() {
// check if pid values changed manually by comparing the current values with those calculated by the sliders,
// if all of them are equal the values haven't been changed manually
- const WARNING_P_GAIN = 70;
- const WARNING_I_GAIN = 120;
- const WARNING_DMAX_GAIN = 60;
- const WARNING_DMIN_GAIN = 40;
-
this.pidSlidersUnavailable = false;
- if (semver.lt(FC.CONFIG.apiVersion, API_VERSION_1_44)) {
+ let rows = 3;
+ if (semver.gte(FC.CONFIG.apiVersion, API_VERSION_1_44)) {
+ rows = FC.TUNING_SLIDERS.slider_pids_mode === 1 ? 2 : 3;
+ } else {
this.calculateNewPids(true);
}
FC.PID_NAMES.forEach(function (elementPid, indexPid) {
const pidElements = $(`.pid_tuning .${elementPid} input`);
pidElements.each(function (indexInput) {
- if (indexPid < 3 && indexInput < 3) {
+ if (indexPid < rows && indexInput < rows) {
if (parseInt($(this).val()) !== FC.PIDS[indexPid][indexInput]) {
TuningSliders.pidSlidersUnavailable = true;
}
@@ -281,7 +426,7 @@ TuningSliders.updatePidSlidersDisplay = function() {
this.pidSlidersUnavailable = true;
}
- if (!this.pidSlidersUnavailable && !semver.gte(FC.CONFIG.apiVersion, API_VERSION_1_44)) {
+ if (!this.pidSlidersUnavailable) {
this.cachedPidSliderValues = true;
}
@@ -294,28 +439,22 @@ TuningSliders.updatePidSlidersDisplay = function() {
$('.tuningPIDSliders').toggle(!this.pidSlidersUnavailable);
$('.subtab-pid .slidersDisabled').toggle(this.pidSlidersUnavailable);
- $('.subtab-pid .nonExpertModeSlidersNote').toggle(!this.pidSlidersUnavailable && !this.expertMode && !semver.gte(FC.CONFIG.apiVersion, API_VERSION_1_44));
- $('.subtab-pid .slidersWarning').toggle((FC.PIDS[1][0] > WARNING_P_GAIN || FC.PIDS[1][1] > WARNING_I_GAIN || FC.PIDS[1][2] > WARNING_DMAX_GAIN ||
- FC.ADVANCED_TUNING.dMinPitch > WARNING_DMIN_GAIN) && !this.pidSlidersUnavailable);
+ $('.subtab-pid .nonExpertModeSlidersNote').toggle(!this.pidSlidersUnavailable && !this.expertMode);
+
+ this.updateSlidersWarning();
};
TuningSliders.updateFilterSlidersDisplay = function() {
- // check if filters changed manually by comapring current value and those based on slider position
- const WARNING_FILTER_HIGH_GAIN = 1.4;
- const WARNING_FILTER_LOW_GAIN = 0.7;
-
+ // check if filters changed manually by comparing current value and those based on slider position
this.GyroSliderUnavailable = false;
this.DTermSliderUnavailable = false;
if (semver.gte(FC.CONFIG.apiVersion, API_VERSION_1_44)) {
- if (FC.TUNING_SLIDERS.slider_gyro_filter === 0) {
- this.GyroSliderUnavailable = true;
- }
- if (FC.TUNING_SLIDERS.slider_dterm_filter === 0) {
- this.DTermSliderUnavailable = true;
- }
+ this.GyroSliderUnavailable = !FC.TUNING_SLIDERS.slider_gyro_filter;
+ this.DTermSliderUnavailable = !FC.TUNING_SLIDERS.slider_dterm_filter;
+
if (parseInt($('.pid_filter input[name="gyroLowpassDynMinFrequency"]').val()) !==
- Math.round(this.FILTER_DEFAULT.gyro_lowpass_dyn_min_hz * this.sliderGyroFilterMultiplier) ||
+ Math.floor(this.FILTER_DEFAULT.gyro_lowpass_dyn_min_hz * this.sliderGyroFilterMultiplier) ||
parseInt($('.pid_filter input[name="gyroLowpassDynMaxFrequency"]').val()) !==
Math.floor(this.FILTER_DEFAULT.gyro_lowpass_dyn_max_hz * this.sliderGyroFilterMultiplier) ||
parseInt($('.pid_filter select[name="gyroLowpassDynType"]').val()) !== this.FILTER_DEFAULT.gyro_lowpass_type ||
@@ -346,7 +485,6 @@ TuningSliders.updateFilterSlidersDisplay = function() {
this.legacyUpdateFilterSlidersDisplay();
}
-
if (this.GyroSliderUnavailable) {
$('.tuningFilterSliders .sliderLabels tr:nth-child(2)').hide();
} else {
@@ -362,10 +500,7 @@ TuningSliders.updateFilterSlidersDisplay = function() {
$('.tuningFilterSliders').toggle(!(this.GyroSliderUnavailable && this.DTermSliderUnavailable));
$('.subtab-filter .slidersDisabled').toggle(this.GyroSliderUnavailable || this.DTermSliderUnavailable);
$('.subtab-filter .nonExpertModeSlidersNote').toggle((!this.GyroSliderUnavailable || !this.DTermSliderUnavailable) && !this.expertMode);
- $('.subtab-filter .slidersWarning').toggle(((this.sliderGyroFilterMultiplier >= WARNING_FILTER_HIGH_GAIN ||
- this.sliderGyroFilterMultiplier <= WARNING_FILTER_LOW_GAIN) && !this.GyroSliderUnavailable) ||
- ((this.sliderDTermFilterMultiplier >= WARNING_FILTER_HIGH_GAIN ||
- this.sliderDTermFilterMultiplier <= WARNING_FILTER_LOW_GAIN) && !this.DTermSliderUnavailable));
+ this.updateFilterSlidersWarning(this.GyroSliderUnavailable, this.DTermSliderUnavailable);
};
TuningSliders.updateFormPids = function(updateSlidersOnly = false) {
@@ -387,14 +522,21 @@ TuningSliders.updateFormPids = function(updateSlidersOnly = false) {
$('.pid_tuning .YAW input[name="f"]').val(FC.ADVANCED_TUNING.feedforwardYaw);
}
- $('output[name="sliderMasterMultiplier-number"]').val(this.sliderMasterMultiplier);
- $('output[name="sliderRollPitchRatio-number"]').val(this.sliderRollPitchRatio);
- $('output[name="sliderIGain-number"]').val(this.sliderIGain);
- $('output[name="sliderPDRatio-number"]').val(this.sliderPDRatio);
- $('output[name="sliderPDGain-number"]').val(this.sliderPDGain);
- $('output[name="sliderDMinRatio-number"]').val(this.sliderDMinRatio);
- $('output[name="sliderFeedforwardGain-number"]').val(this.sliderFeedforwardGain);
-
+ if (semver.gte(FC.CONFIG.apiVersion, API_VERSION_1_44)) {
+ $('output[name="sliderDGain-number"]').val(this.sliderDGain);
+ $('output[name="sliderPIGain-number"]').val(this.sliderPIGain);
+ $('output[name="sliderFeedforwardGain-number"]').val(this.sliderFeedforwardGain);
+ $('output[name="sliderDMaxGain-number"]').val(this.sliderDMaxGain);
+ $('output[name="sliderIGain-number"]').val(this.sliderIGain);
+ $('output[name="sliderRollPitchRatio-number"]').val(this.sliderRollPitchRatio);
+ $('output[name="sliderPitchPIGain-number"]').val(this.sliderPitchPIGain);
+ $('output[name="sliderMasterMultiplier-number"]').val(this.sliderMasterMultiplier);
+ } else {
+ $('output[name="sliderMasterMultiplierLegacy-number"]').val(this.sliderMasterMultiplierLegacy);
+ $('output[name="sliderPDRatio-number"]').val(this.sliderPDRatio);
+ $('output[name="sliderPDGain-number"]').val(this.sliderPDGain);
+ $('output[name="sliderFeedforwardGainLegacy-number"]').val(this.sliderFeedforwardGainLegacy);
+ }
};
TuningSliders.legacyCalculatePids = function(updateSlidersOnly = false) {
@@ -421,9 +563,9 @@ TuningSliders.legacyCalculatePids = function(updateSlidersOnly = false) {
FC.PIDS[1][0] = Math.round(this.PID_DEFAULT[5] * this.sliderPDGain);
FC.PIDS[2][0] = Math.round(this.PID_DEFAULT[10] * this.sliderPDGain);
// feedforward
- FC.ADVANCED_TUNING.feedforwardRoll = Math.round(this.PID_DEFAULT[4] * this.sliderFeedforwardGain);
- FC.ADVANCED_TUNING.feedforwardPitch = Math.round(this.PID_DEFAULT[9] * this.sliderFeedforwardGain);
- FC.ADVANCED_TUNING.feedforwardYaw = Math.round(this.PID_DEFAULT[14] * this.sliderFeedforwardGain);
+ FC.ADVANCED_TUNING.feedforwardRoll = Math.round(this.PID_DEFAULT[4] * this.sliderFeedforwardGainLegacy);
+ FC.ADVANCED_TUNING.feedforwardPitch = Math.round(this.PID_DEFAULT[9] * this.sliderFeedforwardGainLegacy);
+ FC.ADVANCED_TUNING.feedforwardYaw = Math.round(this.PID_DEFAULT[14] * this.sliderFeedforwardGainLegacy);
// master slider part
// these are not calculated anywhere other than master slider multiplier therefore set at default before every calculation
FC.PIDS[0][1] = this.PID_DEFAULT[1];
@@ -436,18 +578,18 @@ TuningSliders.legacyCalculatePids = function(updateSlidersOnly = false) {
//master slider multiplication, max value 200 for main PID values
for (let i = 0; i < 3; i++) {
for (let j = 0; j < 3; j++) {
- FC.PIDS[j][i] = Math.min(Math.round(FC.PIDS[j][i] * this.sliderMasterMultiplier), MAX_PID_GAIN);
+ FC.PIDS[j][i] = Math.min(Math.round(FC.PIDS[j][i] * this.sliderMasterMultiplierLegacy), MAX_PID_GAIN);
}
}
- FC.ADVANCED_TUNING.feedforwardRoll = Math.min(Math.round(FC.ADVANCED_TUNING.feedforwardRoll * this.sliderMasterMultiplier), MAX_FEEDFORWARD_GAIN);
- FC.ADVANCED_TUNING.feedforwardPitch = Math.min(Math.round(FC.ADVANCED_TUNING.feedforwardPitch * this.sliderMasterMultiplier), MAX_FEEDFORWARD_GAIN);
- FC.ADVANCED_TUNING.feedforwardYaw = Math.min(Math.round(FC.ADVANCED_TUNING.feedforwardYaw * this.sliderMasterMultiplier), MAX_FEEDFORWARD_GAIN);
+ FC.ADVANCED_TUNING.feedforwardRoll = Math.min(Math.round(FC.ADVANCED_TUNING.feedforwardRoll * this.sliderMasterMultiplierLegacy), MAX_FEEDFORWARD_GAIN);
+ FC.ADVANCED_TUNING.feedforwardPitch = Math.min(Math.round(FC.ADVANCED_TUNING.feedforwardPitch * this.sliderMasterMultiplierLegacy), MAX_FEEDFORWARD_GAIN);
+ FC.ADVANCED_TUNING.feedforwardYaw = Math.min(Math.round(FC.ADVANCED_TUNING.feedforwardYaw * this.sliderMasterMultiplierLegacy), MAX_FEEDFORWARD_GAIN);
if (this.dMinFeatureEnabled) {
- FC.ADVANCED_TUNING.dMinRoll = Math.min(Math.round(FC.ADVANCED_TUNING.dMinRoll * this.sliderMasterMultiplier), MAX_DMIN_GAIN);
- FC.ADVANCED_TUNING.dMinPitch = Math.min(Math.round(FC.ADVANCED_TUNING.dMinPitch * this.sliderMasterMultiplier), MAX_DMIN_GAIN);
- FC.ADVANCED_TUNING.dMinYaw = Math.min(Math.round(FC.ADVANCED_TUNING.dMinYaw * this.sliderMasterMultiplier), MAX_DMIN_GAIN);
+ FC.ADVANCED_TUNING.dMinRoll = Math.min(Math.round(FC.ADVANCED_TUNING.dMinRoll * this.sliderMasterMultiplierLegacy), MAX_DMIN_GAIN);
+ FC.ADVANCED_TUNING.dMinPitch = Math.min(Math.round(FC.ADVANCED_TUNING.dMinPitch * this.sliderMasterMultiplierLegacy), MAX_DMIN_GAIN);
+ FC.ADVANCED_TUNING.dMinYaw = Math.min(Math.round(FC.ADVANCED_TUNING.dMinYaw * this.sliderMasterMultiplierLegacy), MAX_DMIN_GAIN);
}
this.updateFormPids(updateSlidersOnly);
@@ -458,28 +600,29 @@ TuningSliders.legacyCalculatePids = function(updateSlidersOnly = false) {
TuningSliders.calculateNewPids = function(updateSlidersOnly = false) {
// this is the main calculation for PID sliders, inputs are in form of slider position values
// values get set both into forms and their respective variables
- if (semver.lt(FC.CONFIG.apiVersion, API_VERSION_1_44)) {
- this.legacyCalculatePids(updateSlidersOnly);
- }
if (semver.gte(FC.CONFIG.apiVersion, API_VERSION_1_44)) {
FC.TUNING_SLIDERS.slider_pids_mode = parseInt($('#sliderPidsModeSelect').val());
//rounds slider values to nearies multiple of 5 and passes to the FW. Avoid dividing calc by (* x 100)/5 = 20
- FC.TUNING_SLIDERS.slider_master_multiplier = Math.round(this.sliderMasterMultiplier * 20) * 5;
- FC.TUNING_SLIDERS.slider_roll_pitch_ratio = Math.round(this.sliderRollPitchRatio * 20) * 5;
- FC.TUNING_SLIDERS.slider_i_gain = Math.round(this.sliderIGain * 20) * 5;
- FC.TUNING_SLIDERS.slider_pd_ratio = Math.round(this.sliderPDRatio * 20) * 5;
- FC.TUNING_SLIDERS.slider_pd_gain = Math.round(this.sliderPDGain * 20) * 5;
- FC.TUNING_SLIDERS.slider_dmin_ratio = Math.round(this.sliderDMinRatio * 20) * 5;
+ FC.TUNING_SLIDERS.slider_d_gain = Math.round(this.sliderDGain * 20) * 5;
+ FC.TUNING_SLIDERS.slider_pi_gain = Math.round(this.sliderPIGain * 20) * 5;
FC.TUNING_SLIDERS.slider_feedforward_gain = Math.round(this.sliderFeedforwardGain * 20) * 5;
+ FC.TUNING_SLIDERS.slider_dmax_gain = Math.round(this.sliderDMaxGain * 20) * 5;
+ FC.TUNING_SLIDERS.slider_i_gain = Math.round(this.sliderIGain * 20) * 5;
+ FC.TUNING_SLIDERS.slider_roll_pitch_ratio = Math.round(this.sliderRollPitchRatio * 20) * 5;
+ FC.TUNING_SLIDERS.slider_pitch_pi_gain = Math.round(this.sliderPitchPIGain * 20) * 5;
+ FC.TUNING_SLIDERS.slider_master_multiplier = Math.round(this.sliderMasterMultiplier * 20) * 5;
MSP.promise(MSPCodes.MSP_SET_TUNING_SLIDERS, mspHelper.crunch(MSPCodes.MSP_SET_TUNING_SLIDERS))
.then(() => MSP.promise(MSPCodes.MSP_PID))
.then(() => MSP.promise(MSPCodes.MSP_PID_ADVANCED))
.then(() => {
this.updateFormPids(updateSlidersOnly);
- TABS.pid_tuning.updatePIDColors();
+ this.updateSlidersWarning();
+ this.updateSwitchBoxes();
});
+ } else {
+ this.legacyCalculatePids(updateSlidersOnly);
}
};
@@ -533,10 +676,10 @@ TuningSliders.calculateNewDTermFilters = function() {
TuningSliders.writeFilterSliders = function () {
MSP.promise(MSPCodes.MSP_SET_TUNING_SLIDERS, mspHelper.crunch(MSPCodes.MSP_SET_TUNING_SLIDERS))
- .then(() => MSP.promise(MSPCodes.MSP_EEPROM_WRITE))
.then(() => MSP.promise(MSPCodes.MSP_FILTER_CONFIG))
.then(() => {
TuningSliders.updateLowpassValues();
+ TuningSliders.updateFilterSlidersWarning();
if (this.FilterReset) {
this.FilterReset = false;
this.updateFilterSlidersDisplay();
diff --git a/src/js/fc.js b/src/js/fc.js
index e769dcda..42171e93 100644
--- a/src/js/fc.js
+++ b/src/js/fc.js
@@ -656,18 +656,39 @@ const FC = {
this.VTX_DEVICE_STATUS = null;
this.TUNING_SLIDERS = {
- slider_pids_mode: 0,
- slider_master_multiplier: 0,
- slider_roll_pitch_ratio: 0,
- slider_i_gain: 0,
slider_pd_ratio: 0,
slider_pd_gain: 0,
- slider_dmin_ratio: 0,
slider_feedforward_gain: 0,
+ slider_master_multiplier: 0,
slider_dterm_filter: 0,
slider_dterm_filter_multiplier: 0,
slider_gyro_filter: 0,
slider_gyro_filter_multiplier: 0,
+ // introduced in 4.3
+ slider_pids_mode: 0,
+ slider_d_gain: 0,
+ slider_pi_gain: 0,
+ slider_dmax_gain: 0,
+ slider_i_gain: 0,
+ slider_roll_pitch_ratio: 0,
+ slider_pitch_pi_gain: 0,
+ };
+
+ this.DEFAULT_TUNING_SLIDERS = {
+ slider_pids_mode: 2,
+ slider_d_gain: 100,
+ slider_pi_gain: 100,
+ slider_feedforward_gain: 100,
+ slider_dmax_gain: 100,
+ slider_i_gain: 100,
+ slider_roll_pitch_ratio: 100,
+ slider_pitch_pi_gain: 100,
+ slider_master_multiplier: 100,
+
+ slider_dterm_filter: 1,
+ slider_dterm_filter_multiplier: 100,
+ slider_gyro_filter: 1,
+ slider_gyro_filter_multiplier: 100,
};
},
@@ -800,7 +821,7 @@ const FC = {
getFilterDefaults() {
const versionFilterDefaults = this.DEFAULT;
-
+ // Change filter defaults depending on API version here
if (semver.eq(this.CONFIG.apiVersion, API_VERSION_1_40)) {
versionFilterDefaults.dterm_lowpass2_hz = 200;
} else if (semver.gte(this.CONFIG.apiVersion, API_VERSION_1_41)) {
@@ -829,6 +850,11 @@ const FC = {
if (semver.gte(this.CONFIG.apiVersion, API_VERSION_1_44)) {
versionFilterDefaults.dyn_notch_q_rpm = 500;
versionFilterDefaults.dyn_notch_q = 300;
+ versionFilterDefaults.gyro_lowpass_hz = 250;
+ versionFilterDefaults.gyro_lowpass_dyn_min_hz = 250;
+ versionFilterDefaults.gyro_lowpass2_hz = 500;
+ versionFilterDefaults.dterm_lowpass_dyn_min_hz = 75;
+ versionFilterDefaults.dterm_lowpass_dyn_max_hz = 150;
}
}
return versionFilterDefaults;
@@ -843,7 +869,24 @@ const FC = {
46, 90, 38, 25, 95,
45, 90, 0, 0, 90,
];
+ } else if (semver.gte(this.CONFIG.apiVersion, API_VERSION_1_44)) {
+ versionPidDefaults = [
+ 45, 90, 40, 30, 120,
+ 47, 94, 46, 34, 125,
+ 45, 90, 0, 0, 120,
+ ];
}
return versionPidDefaults;
},
+
+ getSliderDefaults() {
+ const sliderDefaults = this.DEFAULT_TUNING_SLIDERS;
+ // change slider defaults here
+ if (semver.gte(this.CONFIG.apiVersion, API_VERSION_1_44)) {
+ sliderDefaults.slider_roll_pitch_ratio = 115;
+ sliderDefaults.slider_pitch_pi_gain = 105;
+ }
+
+ return sliderDefaults;
+ },
};
diff --git a/src/js/main.js b/src/js/main.js
index 7f6cb60b..483c8e27 100644
--- a/src/js/main.js
+++ b/src/js/main.js
@@ -251,6 +251,12 @@ function startProcess() {
const tab = tabClass.substring(4);
const tabName = $(self).text();
+ if (GUI.active_tab === 'pid_tuning') {
+ if (TABS.pid_tuning.sliderPositionHasChanged || TABS.pid_tuning.sliderModeHasChanged) {
+ TuningSliders.restoreInitialSettings();
+ }
+ }
+
if (tabRequiresConnection && !CONFIGURATOR.connectionValid) {
GUI.log(i18n.getMessage('tabSwitchConnectionRequired'));
return;
diff --git a/src/js/msp/MSPHelper.js b/src/js/msp/MSPHelper.js
index deb9126a..d9916015 100644
--- a/src/js/msp/MSPHelper.js
+++ b/src/js/msp/MSPHelper.js
@@ -645,8 +645,9 @@ MspHelper.prototype.process_data = function(dataHandler) {
console.log('Voltage config saved');
break;
case MSPCodes.MSP_DEBUG:
- for (let i = 0; i < 4; i++)
+ for (let i = 0; i < 4; i++) {
FC.SENSOR_DATA.debug[i] = data.read16();
+ }
break;
case MSPCodes.MSP_SET_MOTOR:
console.log('Motor Speeds Updated');
@@ -1491,10 +1492,11 @@ MspHelper.prototype.process_data = function(dataHandler) {
FC.TUNING_SLIDERS.slider_master_multiplier = data.readU8();
FC.TUNING_SLIDERS.slider_roll_pitch_ratio = data.readU8();
FC.TUNING_SLIDERS.slider_i_gain = data.readU8();
- FC.TUNING_SLIDERS.slider_pd_ratio = data.readU8();
- FC.TUNING_SLIDERS.slider_pd_gain = data.readU8();
- FC.TUNING_SLIDERS.slider_dmin_ratio = data.readU8();
+ FC.TUNING_SLIDERS.slider_d_gain = data.readU8();
+ FC.TUNING_SLIDERS.slider_pi_gain = data.readU8();
+ FC.TUNING_SLIDERS.slider_dmax_gain = data.readU8();
FC.TUNING_SLIDERS.slider_feedforward_gain = data.readU8();
+ FC.TUNING_SLIDERS.slider_pitch_pi_gain = data.readU8();
FC.TUNING_SLIDERS.slider_dterm_filter = data.readU8();
FC.TUNING_SLIDERS.slider_dterm_filter_multiplier = data.readU8();
FC.TUNING_SLIDERS.slider_gyro_filter = data.readU8();
@@ -2313,15 +2315,15 @@ MspHelper.prototype.crunch = function(code) {
.push8(FC.TUNING_SLIDERS.slider_master_multiplier)
.push8(FC.TUNING_SLIDERS.slider_roll_pitch_ratio)
.push8(FC.TUNING_SLIDERS.slider_i_gain)
- .push8(FC.TUNING_SLIDERS.slider_pd_ratio)
- .push8(FC.TUNING_SLIDERS.slider_pd_gain)
- .push8(FC.TUNING_SLIDERS.slider_dmin_ratio)
+ .push8(FC.TUNING_SLIDERS.slider_d_gain)
+ .push8(FC.TUNING_SLIDERS.slider_pi_gain)
+ .push8(FC.TUNING_SLIDERS.slider_dmax_gain)
.push8(FC.TUNING_SLIDERS.slider_feedforward_gain)
+ .push8(FC.TUNING_SLIDERS.slider_pitch_pi_gain)
.push8(FC.TUNING_SLIDERS.slider_dterm_filter)
.push8(FC.TUNING_SLIDERS.slider_dterm_filter_multiplier)
.push8(FC.TUNING_SLIDERS.slider_gyro_filter)
.push8(FC.TUNING_SLIDERS.slider_gyro_filter_multiplier);
-
break;
default:
diff --git a/src/js/tabs/motors.js b/src/js/tabs/motors.js
index 5f938f10..3e0dfeb4 100644
--- a/src/js/tabs/motors.js
+++ b/src/js/tabs/motors.js
@@ -237,10 +237,6 @@ TABS.motors.initialize = function (callback) {
}
}
- function isInt(n) {
- return n % 1 === 0;
- }
-
function setContentButtons(motorsTesting=false) {
$('.btn .tool').toggleClass("disabled", self.configHasChanged || motorsTesting);
$('.btn .save').toggleClass("disabled", !self.configHasChanged);
diff --git a/src/js/tabs/pid_tuning.js b/src/js/tabs/pid_tuning.js
index a203ed74..1b3dd88a 100644
--- a/src/js/tabs/pid_tuning.js
+++ b/src/js/tabs/pid_tuning.js
@@ -21,6 +21,10 @@ TABS.pid_tuning = {
SETPOINT_WEIGHT_RANGE_LEGACY: 2.54,
activeSubtab: 'pid',
analyticsChanges: {},
+
+ sliderPositionHasChanged: false,
+ sliderChanges: {},
+ sliderModeHasChanged: false,
};
TABS.pid_tuning.initialize = function (callback) {
@@ -80,9 +84,7 @@ TABS.pid_tuning.initialize = function (callback) {
self.setRateProfile();
}
- // Fill in the data from PIDs array
-
- // For each pid name
+ // Fill in the data from PIDs array for each pid name
FC.PID_NAMES.forEach(function(elementPid, indexPid) {
// Look into the PID table to a row with the name of the pid
@@ -482,30 +484,34 @@ TABS.pid_tuning.initialize = function (callback) {
}
if (semver.gte(FC.CONFIG.apiVersion, API_VERSION_1_44)) {
- // Feedforward
- const feedforwardGroupCheck = $('input[id="feedforwardGroup"]');
- const PID_FEEDFORWARD = (FC.ADVANCED_TUNING.feedforwardRoll ||
- FC.ADVANCED_TUNING.feedforwardPitch ||
- FC.ADVANCED_TUNING.feedforwardYaw);
+ $('.resetwarning').attr("title", i18n.getMessage("pidTuningResetWarning"));
+ } else {
+ // Previous html attributes for legacy sliders
+ $('.pid_tuning .ROLL input[name="p"]').attr("max", "200");
+ $('.pid_tuning .ROLL input[name="i"]').attr("max", "200");
+ $('.pid_tuning .ROLL input[name="d"]').attr("max", "200");
+ $('.pid_tuning .ROLL input[name="dMinPitch"]').attr("max", "100");
+ $('.pid_tuning .PITCH input[name="p"]').attr("max", "200");
+ $('.pid_tuning .PITCH input[name="i"]').attr("max", "200");
+ $('.pid_tuning .PITCH input[name="d"]').attr("max", "200");
+ $('.pid_tuning .PITCH input[name="dMinPitch"]').attr("max", "100");
+ $('.pid_tuning .YAW input[name="p"]').attr("max", "200");
+ $('.pid_tuning .YAW input[name="i"]').attr("max", "200");
+ $('.pid_tuning .YAW input[name="d"]').attr("max", "200");
+ $('.pid_tuning .YAW input[name="dMinPitch"]').attr("max", "1000");
+ $('#sliderDTermFilterMultiplier').attr({ "min": "0.5", "max": "1.5", "step": "0.025" });
+ }
- feedforwardGroupCheck.prop('checked', PID_FEEDFORWARD !== 0);
+ // Feedforward
+ if (semver.gte(FC.CONFIG.apiVersion, API_VERSION_1_44)) {
+ const feedforwardGroupCheck = $('input[id="feedforwardGroup"]');
+ const PID_FEEDFORWARD = FC.ADVANCED_TUNING.feedforwardRoll || FC.ADVANCED_TUNING.feedforwardPitch || FC.ADVANCED_TUNING.feedforwardYaw;
+ feedforwardGroupCheck.prop('checked', PID_FEEDFORWARD);
+ $('.feedforwardGroupCheckbox').addClass('switchery-disabled');
$('select[id="feedforwardAveraging"]').val(FC.ADVANCED_TUNING.feedforward_averaging);
$('input[name="feedforwardSmoothFactor"]').val(FC.ADVANCED_TUNING.feedforward_smooth_factor);
$('input[name="feedforwardBoost"]').val(FC.ADVANCED_TUNING.feedforward_boost);
- feedforwardGroupCheck.change(function() {
- const checked = $(this).is(':checked');
- $('.feedforwardGroup .suboption').toggle(checked);
- if (!checked) {
- $('.pid_tuning .ROLL input[name="f"]').val(0);
- $('.pid_tuning .PITCH input[name="f"]').val(0);
- $('.pid_tuning .YAW input[name="f"]').val(0);
- } else {
- $('.pid_tuning .ROLL input[name="f"]').val(FC.ADVANCED_TUNING.feedforwardRoll > 0 ? FC.ADVANCED_TUNING.feedforwardRoll : PID_DEFAULT[4]);
- $('.pid_tuning .PITCH input[name="f"]').val(FC.ADVANCED_TUNING.feedforwardPitch > 0 ? FC.ADVANCED_TUNING.feedforwardPitch : PID_DEFAULT[9]);
- $('.pid_tuning .YAW input[name="f"]').val(FC.ADVANCED_TUNING.feedforwardYaw > 0 ? FC.ADVANCED_TUNING.feedforwardYaw : PID_DEFAULT[14]);
- }
- }).change();
// Vbat Sag Compensation
const vbatSagCompensationCheck = $('input[id="vbatSagCompensation"]');
@@ -528,11 +534,21 @@ TABS.pid_tuning.initialize = function (callback) {
$('.thrustLinearization .suboption').toggle(checked);
}).change();
} else {
- $('.feedforwardOption').hide();
+ const checkbox = document.getElementById('feedforwardGroup');
+ if (checkbox.parentNode) {
+ checkbox.parentNode.removeChild(checkbox);
+ }
$('.vbatSagCompensation').hide();
$('.thrustLinearization').hide();
- $('.feedforwardGroupCheckbox').addClass('switchery-disabled');
- $('input[id="feedforwardGroup"]').prop('checked', true);
+
+ if (semver.gte(FC.CONFIG.apiVersion, API_VERSION_1_40)) {
+ $('.pid_tuning .ROLL input[name="f"]').val(FC.ADVANCED_TUNING.feedforwardRoll > 0 ? FC.ADVANCED_TUNING.feedforwardRoll : PID_DEFAULT[4]);
+ $('.pid_tuning .PITCH input[name="f"]').val(FC.ADVANCED_TUNING.feedforwardPitch > 0 ? FC.ADVANCED_TUNING.feedforwardPitch : PID_DEFAULT[9]);
+ $('.pid_tuning .YAW input[name="f"]').val(FC.ADVANCED_TUNING.feedforwardYaw > 0 ? FC.ADVANCED_TUNING.feedforwardYaw : PID_DEFAULT[14]);
+ $('span.feedforwardOption').hide();
+ } else {
+ $('.feedforwardGroup').hide();
+ }
}
$('input[id="useIntegratedYaw"]').change(function() {
@@ -540,16 +556,19 @@ TABS.pid_tuning.initialize = function (callback) {
$('#pidTuningIntegratedYawCaution').toggle(checked);
}).change();
+ // if user decreases Dmax, don't allow Dmin above Dmax
function adjustDMin(dElement, dMinElement) {
const dValue = parseInt(dElement.val());
const dMinValue = parseInt(dMinElement.val());
-
- const dMinLimit = Math.min(Math.max(dValue - 1, 0), 100);
+ let dMinLimit = Math.min(Math.max(dValue - 1, 0), 100);
+ if (semver.gte(FC.CONFIG.apiVersion, API_VERSION_1_44)) {
+ dMinLimit = Math.min(Math.max(dValue, 0), 250);
+ } else {
+ dMinElement.attr("max", dMinLimit);
+ }
if (dMinValue > dMinLimit) {
dMinElement.val(dMinLimit);
}
-
- dMinElement.attr("max", dMinLimit);
}
$('.pid_tuning .ROLL input[name="d"]').change(function() {
@@ -567,56 +586,95 @@ TABS.pid_tuning.initialize = function (callback) {
adjustDMin($(this), dMinElement);
}).change();
- //dMinSwitch toggle
+ // if user increases Dmin, don't allow Dmax below Dmin
+ function adjustD(dMinElement, dElement) {
+ if (semver.gte(FC.CONFIG.apiVersion, API_VERSION_1_44)) {
+ const dValue2 = parseInt(dElement.val());
+ const dMinValue2 = parseInt(dMinElement.val());
+ const dLimit = Math.min(Math.max(dMinValue2, 0), 250);
+ if (dValue2 < dLimit) {
+ dElement.val(dLimit);
+ }
+ }
+ }
+
+ $('.pid_tuning input[name="dMinRoll"]').change(function() {
+ const dElement= $('.pid_tuning .ROLL input[name="d"]');
+ adjustD($(this), dElement);
+ }).change();
+
+ $('.pid_tuning input[name="dMinPitch"]').change(function() {
+ const dElement= $('.pid_tuning .PITCH input[name="d"]');
+ adjustD($(this), dElement);
+ }).change();
+
+ $('.pid_tuning input[name="dMinYaw"]').change(function() {
+ const dElement= $('.pid_tuning .YAW input[name="d"]');
+ adjustD($(this), dElement);
+ }).change();
+
+ $('.pid_tuning .ROLL input[name="d"]').change(function() {
+ const dMinElement= $('.pid_tuning input[name="dMinRoll"]');
+ adjustDMin($(this), dMinElement);
+ }).change();
+
+ $('.pid_tuning .PITCH input[name="d"]').change(function() {
+ const dMinElement= $('.pid_tuning input[name="dMinPitch"]');
+ adjustDMin($(this), dMinElement);
+ }).change();
+
+ $('.pid_tuning .YAW input[name="d"]').change(function() {
+ const dMinElement= $('.pid_tuning input[name="dMinYaw"]');
+ adjustDMin($(this), dMinElement);
+ }).change();
+
+ // dMinSwitch toggle - renamed to Dynamic Damping and disabled in 4.3
if (semver.gte(FC.CONFIG.apiVersion, API_VERSION_1_41)) {
const dMinSwitch = $('#dMinSwitch');
- dMinSwitch.prop('checked', FC.ADVANCED_TUNING.dMinRoll > 0 || FC.ADVANCED_TUNING.dMinPitch > 0 || FC.ADVANCED_TUNING.dMinYaw > 0);
- dMinSwitch.change(function() {
- const checked = $(this).is(':checked');
- if (checked) {
- if (FC.TUNING_SLIDERS.slider_pids_mode !== 0 && semver.gte(FC.CONFIG.apiVersion, API_VERSION_1_44)) {
- TuningSliders.sliderDMinRatio = 1;
- $('output[name="sliderDMinRatio-number"]').val(1);
- $('#sliderDMinRatio').val(1);
- }
- if ($('.pid_tuning input[name="dMinRoll"]').val() == 0 && $('.pid_tuning input[name="dMinPitch"]').val() == 0 && $('.pid_tuning input[name="dMinYaw"]').val() == 0) {
- // when enabling dmin set its value based on 0.57x of actual dmax, dmin is limited to 100
- $('.pid_tuning input[name="dMinRoll"]').val(Math.min(Math.round($('.pid_tuning .ROLL input[name="d"]').val() * 0.57), 100));
- $('.pid_tuning input[name="dMinPitch"]').val(Math.min(Math.round($('.pid_tuning .PITCH input[name="d"]').val() * 0.57), 100));
- $('.pid_tuning input[name="dMinYaw"]').val(Math.min(Math.round($('.pid_tuning .YAW input[name="d"]').val() * 0.57), 100));
- if (semver.gte(FC.CONFIG.apiVersion, API_VERSION_1_43)) {
- $('.pid_tuning input[name="dMinRoll"]').val(Math.min(Math.round($('.pid_tuning .ROLL input[name="d"]').val() * 0.65), 100));
- $('.pid_tuning input[name="dMinPitch"]').val(Math.min(Math.round($('.pid_tuning .PITCH input[name="d"]').val() * 0.65), 100));
- $('.pid_tuning input[name="dMinYaw"]').val(Math.min(Math.round($('.pid_tuning .YAW input[name="d"]').val() * 0.65), 100));
+
+ if (semver.gte(FC.CONFIG.apiVersion, API_VERSION_1_44)) {
+ $('.dMinGroupCheckbox').addClass('switchery-disabled');
+ $('.dMinDisabledNote').hide();
+ self.updateGuiElements();
+ } else {
+ dMinSwitch.prop('checked', FC.ADVANCED_TUNING.dMinRoll > 0 || FC.ADVANCED_TUNING.dMinPitch > 0 || FC.ADVANCED_TUNING.dMinYaw > 0);
+
+ dMinSwitch.on('change', function() {
+ const checked = $(this).is(':checked');
+ if (checked) {
+ if ($('.pid_tuning input[name="dMinRoll"]').val() == 0 && $('.pid_tuning input[name="dMinPitch"]').val() == 0 && $('.pid_tuning input[name="dMinYaw"]').val() == 0) {
+ // when enabling dmin set its value based on 0.57x of actual dmax, dmin is limited to 100
+ $('.pid_tuning input[name="dMinRoll"]').val(Math.min(Math.round($('.pid_tuning .ROLL input[name="d"]').val() * 0.57), 100));
+ $('.pid_tuning input[name="dMinPitch"]').val(Math.min(Math.round($('.pid_tuning .PITCH input[name="d"]').val() * 0.57), 100));
+ $('.pid_tuning input[name="dMinYaw"]').val(Math.min(Math.round($('.pid_tuning .YAW input[name="d"]').val() * 0.57), 100));
+ if (semver.eq(FC.CONFIG.apiVersion, API_VERSION_1_43)) {
+ $('.pid_tuning input[name="dMinRoll"]').val(Math.min(Math.round($('.pid_tuning .ROLL input[name="d"]').val() * 0.65), 100));
+ $('.pid_tuning input[name="dMinPitch"]').val(Math.min(Math.round($('.pid_tuning .PITCH input[name="d"]').val() * 0.65), 100));
+ $('.pid_tuning input[name="dMinYaw"]').val(Math.min(Math.round($('.pid_tuning .YAW input[name="d"]').val() * 0.65), 100));
+ }
+ } else {
+ $('.pid_tuning input[name="dMinRoll"]').val(FC.ADVANCED_TUNING.dMinRoll);
+ $('.pid_tuning input[name="dMinPitch"]').val(FC.ADVANCED_TUNING.dMinPitch);
+ $('.pid_tuning input[name="dMinYaw"]').val(FC.ADVANCED_TUNING.dMinYaw);
}
+ $('.dMinDisabledNote').hide();
+ $('.dminGroup .suboption').show();
+ $('#pid_main tr :nth-child(5)').show();
+ $('#pid_main .pid_titlebar2 th').attr('colspan', 6);
+ $('.derivativeText').text(i18n.getMessage("pidTuningDMax"));
} else {
- $('.pid_tuning input[name="dMinRoll"]').val(FC.ADVANCED_TUNING.dMinRoll);
- $('.pid_tuning input[name="dMinPitch"]').val(FC.ADVANCED_TUNING.dMinPitch);
- $('.pid_tuning input[name="dMinYaw"]').val(FC.ADVANCED_TUNING.dMinYaw);
+ $('.dMinDisabledNote').show();
+ $('.dminGroup .suboption').hide();
+ $('#pid_main tr :nth-child(5)').hide();
+ $('#pid_main .pid_titlebar2 th').attr('colspan', 5);
+ $('.derivativeText').text(i18n.getMessage("pidTuningDerivative"));
+ $('.pid_tuning input[name="dMinRoll"]').val(0);
+ $('.pid_tuning input[name="dMinPitch"]').val(0);
+ $('.pid_tuning input[name="dMinYaw"]').val(0);
}
- $('.dMinDisabledNote').hide();
- $('.dminGroup .suboption').show();
- $('#pid_main tr :nth-child(5)').show();
- $('#pid_main .pid_titlebar2 th').attr('colspan', 6);
- $('.derivativeText').text(i18n.getMessage("pidTuningDMax"));
- } else {
- if (FC.TUNING_SLIDERS.slider_pids_mode !== 0 && semver.gte(FC.CONFIG.apiVersion, API_VERSION_1_44)) {
- TuningSliders.sliderDMinRatio = 2;
- }
- $('.pid_tuning input[name="dMinRoll"]').val(0);
- $('.pid_tuning input[name="dMinPitch"]').val(0);
- $('.pid_tuning input[name="dMinYaw"]').val(0);
- $('.dMinDisabledNote').show();
- $('.dminGroup .suboption').hide();
- $('#pid_main tr :nth-child(5)').hide();
- $('#pid_main .pid_titlebar2 th').attr('colspan', 5);
- $('.derivativeText').text(i18n.getMessage("pidTuningDerivative"));
- }
- if (semver.gte(FC.CONFIG.apiVersion, API_VERSION_1_44)) {
- TuningSliders.updatePidSlidersDisplay();
- }
- });
- dMinSwitch.change();
+ });
+ }
+ dMinSwitch.trigger('change');
}
$('input[id="gyroNotch1Enabled"]').change(function() {
@@ -1016,22 +1074,20 @@ TABS.pid_tuning.initialize = function (callback) {
FC.ADVANCED_TUNING.vbat_sag_compensation = $('input[id="vbatSagCompensation"]').is(':checked') ? parseInt($('input[name="vbatSagValue"]').val()) : 0;
FC.ADVANCED_TUNING.thrustLinearization = $('input[id="thrustLinearization"]').is(':checked') ? parseInt($('input[name="thrustLinearValue"]').val()) : 0;
FC.FILTER_CONFIG.dyn_notch_count = parseInt($('.pid_filter input[name="dynamicNotchCount"]').val());
- }
- if (semver.gte(FC.CONFIG.apiVersion, API_VERSION_1_44)) {
- FC.TUNING_SLIDERS.slider_pids_mode = parseInt($('#sliderPidsModeSelect').val());
+ FC.TUNING_SLIDERS.slider_pids_mode = TuningSliders.sliderPidsMode;
//rounds slider values to nearies multiple of 5 and passes to the FW. Avoid dividing calc by (* x 100)/5 = 20
FC.TUNING_SLIDERS.slider_master_multiplier = Math.round(TuningSliders.sliderMasterMultiplier * 20) * 5;
- FC.TUNING_SLIDERS.slider_roll_pitch_ratio = Math.round(TuningSliders.sliderRollPitchRatio * 20) * 5;
- FC.TUNING_SLIDERS.slider_i_gain = Math.round(TuningSliders.sliderIGain * 20) * 5;
- FC.TUNING_SLIDERS.slider_pd_ratio = Math.round(TuningSliders.sliderPDRatio * 20) * 5;
- FC.TUNING_SLIDERS.slider_pd_gain = Math.round(TuningSliders.sliderPDGain * 20) * 5;
- FC.TUNING_SLIDERS.slider_dmin_ratio = Math.round(TuningSliders.sliderDMinRatio * 20) * 5;
+ FC.TUNING_SLIDERS.slider_d_gain = Math.round(TuningSliders.sliderDGain * 20) * 5;
+ FC.TUNING_SLIDERS.slider_pi_gain = Math.round(TuningSliders.sliderPIGain * 20) * 5;
FC.TUNING_SLIDERS.slider_feedforward_gain = Math.round(TuningSliders.sliderFeedforwardGain * 20) * 5;
+ FC.TUNING_SLIDERS.slider_i_gain = Math.round(TuningSliders.sliderIGain * 20) * 5;
+ FC.TUNING_SLIDERS.slider_dmax_gain = Math.round(TuningSliders.sliderDMaxGain * 20) * 5;
+ FC.TUNING_SLIDERS.slider_roll_pitch_ratio = Math.round(TuningSliders.sliderRollPitchRatio * 20) * 5;
+ FC.TUNING_SLIDERS.slider_pitch_pi_gain = Math.round(TuningSliders.sliderPitchPIGain * 20) * 5;
FC.TUNING_SLIDERS.slider_dterm_filter = TuningSliders.sliderDTermFilter ? 1 : 0;
FC.TUNING_SLIDERS.slider_dterm_filter_multiplier = Math.round(TuningSliders.sliderDTermFilterMultiplier * 20) * 5;
-
FC.TUNING_SLIDERS.slider_gyro_filter = TuningSliders.sliderGyroFilter ? 1 : 0;
FC.TUNING_SLIDERS.slider_gyro_filter_multiplier = Math.round(TuningSliders.sliderGyroFilterMultiplier * 20) * 5;
}
@@ -1313,14 +1369,32 @@ TABS.pid_tuning.initialize = function (callback) {
updatePidDisplay();
});
- $('#resetProfile').on('click', function(){
+ $('#resetProfile').on('click', function() {
self.updating = true;
- MSP.promise(MSPCodes.MSP_SET_RESET_CURR_PID).then(function () {
- self.refresh(function () {
+
+ function refresh () {
+ self.refresh(() => {
self.updating = false;
GUI.log(i18n.getMessage('pidTuningProfileReset'));
});
+ }
+
+ MSP.promise(MSPCodes.MSP_SET_RESET_CURR_PID).then(() => {
+ if (semver.gte(FC.CONFIG.apiVersion, API_VERSION_1_44)) {
+ TuningSliders.resetDefault();
+ MSP.promise(MSPCodes.MSP_SET_TUNING_SLIDERS, mspHelper.crunch(MSPCodes.MSP_SET_TUNING_SLIDERS)).then(() => {
+ MSP.promise(MSPCodes.MSP_EEPROM_WRITE).then(() => {
+ self.sliderPositionHasChanged = false;
+ self.sliderModeHasChanged = false;
+ self.sliderChanges = {};
+ GUI.log(i18n.getMessage('pidTuningEepromSaved'));
+ refresh();
+ });
+ });
+ } else {
+ refresh();
+ }
});
});
@@ -1398,7 +1472,6 @@ TABS.pid_tuning.initialize = function (callback) {
}
});
-
// DTerm filter options
function loadFilterTypeValues() {
const filterTypeValues = [];
@@ -1422,10 +1495,7 @@ TABS.pid_tuning.initialize = function (callback) {
}
// Added in API 1.42.0
function loadDynamicNotchRangeValues() {
- const dynamicNotchRangeValues = [
- "HIGH", "MEDIUM", "LOW", "AUTO",
- ];
- return dynamicNotchRangeValues;
+ return [ "HIGH", "MEDIUM", "LOW", "AUTO" ];
}
function populateDynamicNotchRangeSelect(selectDynamicNotchRangeValues) {
const dynamicNotchRangeSelect = $('select[name="dynamicNotchRange"]');
@@ -1772,12 +1842,14 @@ TABS.pid_tuning.initialize = function (callback) {
const selectRateProfile = $('.selectRateProfile');
$.each(selectProfileValues, function(key, value) {
- if (key != FC.CONFIG.profile)
+ if (key !== FC.CONFIG.profile) {
selectProfile.append(new Option(value, key));
+ }
});
$.each(selectRateProfileValues, function(key, value) {
- if (key != FC.CONFIG.rateProfile)
+ if (key !== FC.CONFIG.rateProfile) {
selectRateProfile.append(new Option(value, key));
+ }
});
$('.copyprofilebtn').click(function() {
@@ -1832,20 +1904,74 @@ TABS.pid_tuning.initialize = function (callback) {
$('.copyrateprofilebtn').hide();
}
+ /*
+ * TuningSliders
+ */
+
if (semver.gte(FC.CONFIG.apiVersion, API_VERSION_1_42)) {
// filter and tuning sliders
TuningSliders.initialize();
// UNSCALED non expert slider constrain values
- const NON_EXPERT_SLIDER_MAX = 1.25;
- const NON_EXPERT_SLIDER_MIN = 0.7;
+ const NON_EXPERT_SLIDER_MAX = semver.gte(FC.CONFIG.apiVersion, API_VERSION_1_44) ? 1.2 : 1.25;
+ const NON_EXPERT_SLIDER_MIN = semver.gte(FC.CONFIG.apiVersion, API_VERSION_1_44) ? 0.85 : 0.7;
+ const NON_EXPERT_SLIDER_MIN_FF = 0.7;
+ const NON_EXPERT_SLIDER_MAX_FF = 1.35;
const SLIDER_STEP_LOWER = semver.gte(FC.CONFIG.apiVersion, API_VERSION_1_44) ? 0.025 : 0.05;
const SLIDER_STEP_UPPER = semver.gte(FC.CONFIG.apiVersion, API_VERSION_1_44) ? 0.05 : 0.1;
- $('#sliderPidsModeSelect').val(FC.TUNING_SLIDERS.slider_pids_mode);
+ if (semver.gte(FC.CONFIG.apiVersion, API_VERSION_1_44)) {
+ TuningSliders.saveInitialSettings();
+ const initialConfiguration = TuningSliders.initialSettings;
- if (semver.lt(FC.CONFIG.apiVersion, API_VERSION_1_44)) {
+ // we only target the range target type.
+ function sliderHandler(e) {
+ if (e.target !== e.currentTarget) {
+ const item = e.target.id === '' ? e.target.name : e.target.id;
+ const value = isInt(e.target.value) ? parseInt(e.target.value) : parseFloat(e.target.value);
+ self.sliderChanges[item] = value;
+
+ if (item in initialConfiguration) {
+ if (value !== initialConfiguration[item]) {
+ self.sliderPositionHasChanged = true;
+ } else {
+ delete self.sliderChanges[item];
+ if (Object.keys(self.sliderChanges).length === 0) {
+ self.sliderPositionHasChanged = false;
+ }
+ }
+ }
+ }
+ e.stopPropagation();
+ }
+
+ function disableSlideronManualChange(e, angle) {
+ const sliderPidsModeSelectElement = $('#sliderPidsModeSelect');
+ const mode = parseInt(sliderPidsModeSelectElement.val());
+ if (mode > 0) {
+ if (mode === 1 && angle === 'YAW') {
+ e.preventDefault();
+ } else {
+ sliderPidsModeSelectElement.val(0).trigger('change');
+ self.sliderModeHasChanged = true;
+ }
+ } else {
+ self.updateGuiElements();
+ }
+ }
+
+ function HandleEventParams(param) {
+ return (e) => disableSlideronManualChange(e, param);
+ }
+
+ document.querySelectorAll('.sliderLabels').forEach(elem => elem.addEventListener('change', sliderHandler));
+ document.querySelectorAll('.sliderMode').forEach(elem => elem.addEventListener('change', sliderHandler));
+ document.querySelectorAll('.ROLL').forEach(elem => elem.addEventListener('change', HandleEventParams('ROLL')));
+ document.querySelectorAll('.PITCH').forEach(elem => elem.addEventListener('change', HandleEventParams('PITCH')));
+ document.querySelectorAll('.YAW').forEach(elem => elem.addEventListener('change', HandleEventParams('YAW')));
+ $('#sliderPidsModeSelect').val(FC.TUNING_SLIDERS.slider_pids_mode);
+ } else {
$('#dMinSwitch').change(function() {
TuningSliders.setDMinFeatureEnabled($(this).is(':checked'));
// switch dmin and dmax values on dmin on/off if sliders available
@@ -1876,76 +2002,125 @@ TABS.pid_tuning.initialize = function (callback) {
}
let allPidTuningSliders;
- if (semver.lt(FC.CONFIG.apiVersion, API_VERSION_1_44)) {
- allPidTuningSliders = $('#sliderMasterMultiplier, #sliderPDRatio, #sliderPDGain, #sliderFeedforwardGain');
- $('.tab-pid_tuning .advancedSlider').hide();
- $('.tab-pid_tuning .sliderMode').hide();
+ if (semver.gte(FC.CONFIG.apiVersion, API_VERSION_1_44)) {
+ allPidTuningSliders = $('#sliderMasterMultiplier, #sliderDGain, #sliderPIGain, #sliderFeedforwardGain, #sliderIGain, #sliderDMaxGain, #sliderRollPitchRatio, #sliderPitchPIGain');
+ $('.tab-pid-tuning .legacySlider').hide();
} else {
- allPidTuningSliders = $('#sliderMasterMultiplier, #sliderRollPitchRatio, #sliderIGain, #sliderPDRatio, #sliderPDGain, #sliderDMinRatio, #sliderFeedforwardGain');
- $('.tab-pid-tuning .baseSlider').show();
- $('.tab-pid-tuning .MasterSlider').show();
+ allPidTuningSliders = $('#sliderMasterMultiplierLegacy, #sliderPDRatio, #sliderPDGain, #sliderFeedforwardGainLegacy');
+ $('.tab-pid_tuning .advancedSlider').hide();
+ $('.tab-pid-tuning .baseSlider').hide();
+ $('.tab-pid_tuning .sliderMode').hide();
}
- allPidTuningSliders.on('input', function() {
+ allPidTuningSliders.on('input mouseup', function() {
const slider = $(this);
- // adjust step for more smoothness above 1x
- if (slider.val() >= 1) {
- slider.attr('step', SLIDER_STEP_LOWER);
- } else {
- slider.attr('step', SLIDER_STEP_UPPER);
- }
- if (!TuningSliders.expertMode && semver.lt(FC.CONFIG.apiVersion, API_VERSION_1_44)) {
- if (slider.val() > NON_EXPERT_SLIDER_MAX) {
- slider.val(NON_EXPERT_SLIDER_MAX);
- } else if (slider.val() < NON_EXPERT_SLIDER_MIN) {
- slider.val(NON_EXPERT_SLIDER_MIN);
+
+ if (semver.lt(FC.CONFIG.apiVersion, API_VERSION_1_44)) {
+ if (slider.val() >= 1) {
+ slider.attr('step', SLIDER_STEP_LOWER);
+ } else {
+ slider.attr('step', SLIDER_STEP_UPPER);
}
}
- const scaledValue = TuningSliders.scaleSliderValue(slider.val());
- if (slider.is('#sliderMasterMultiplier')) {
- TuningSliders.sliderMasterMultiplier = scaledValue;
- } else if (slider.is('#sliderRollPitchRatio')) {
- TuningSliders.sliderRollPitchRatio = scaledValue;
- } else if (slider.is('#sliderIGain')) {
- TuningSliders.sliderIGain = scaledValue;
- } else if (slider.is('#sliderPDRatio')) {
- TuningSliders.sliderPDRatio = scaledValue;
- } else if (slider.is('#sliderPDGain')) {
- TuningSliders.sliderPDGain = scaledValue;
- } else if (slider.is('#sliderDMinRatio')) {
- TuningSliders.sliderDMinRatio = scaledValue;
- } else if (slider.is('#sliderFeedforwardGain')) {
- TuningSliders.sliderFeedforwardGain = scaledValue;
+
+ if (!TuningSliders.expertMode) {
+ if (slider.val() > NON_EXPERT_SLIDER_MAX) {
+ slider.val(slider.is('#sliderFeedforwardGain') ? NON_EXPERT_SLIDER_MAX_FF : NON_EXPERT_SLIDER_MAX);
+ } else if (slider.val() < NON_EXPERT_SLIDER_MIN) {
+ slider.val(slider.is('#sliderFeedforwardGain') ? NON_EXPERT_SLIDER_MIN_FF : NON_EXPERT_SLIDER_MIN);
+ }
+ }
+
+ const sliderValue = isInt(slider.val()) ? parseInt(slider.val()) : parseFloat(slider.val());
+ const scaledValue = TuningSliders.scaleSliderValue(sliderValue);
+
+ if (semver.gte(FC.CONFIG.apiVersion, API_VERSION_1_44)) {
+ if (slider.is('#sliderDGain')) {
+ TuningSliders.sliderDGain = scaledValue;
+ } else if (slider.is('#sliderPIGain')) {
+ TuningSliders.sliderPIGain = scaledValue;
+ } else if (slider.is('#sliderFeedforwardGain')) {
+ TuningSliders.sliderFeedforwardGain = sliderValue;
+ } else if (slider.is('#sliderDMaxGain')) {
+ TuningSliders.sliderDMaxGain = sliderValue;
+ } else if (slider.is('#sliderIGain')) {
+ TuningSliders.sliderIGain = scaledValue;
+ } else if (slider.is('#sliderRollPitchRatio')) {
+ TuningSliders.sliderRollPitchRatio = scaledValue;
+ } else if (slider.is('#sliderPitchPIGain')) {
+ TuningSliders.sliderPitchPIGain = scaledValue;
+ } else if (slider.is('#sliderMasterMultiplier')) {
+ TuningSliders.sliderMasterMultiplier = scaledValue;
+ }
+ } else {
+ if (slider.is('#sliderMasterMultiplierLegacy')) {
+ TuningSliders.sliderMasterMultiplierLegacy = sliderValue;
+ } else if (slider.is('#sliderPDRatio')) {
+ TuningSliders.sliderPDRatio = sliderValue;
+ } else if (slider.is('#sliderPDGain')) {
+ TuningSliders.sliderPDGain = sliderValue;
+ } else if (slider.is('#sliderFeedforwardGainLegacy')) {
+ TuningSliders.sliderFeedforwardGainLegacy = sliderValue;
+ }
}
TuningSliders.calculateNewPids();
self.analyticsChanges['PidTuningSliders'] = "On";
});
- allPidTuningSliders.mouseup(function() {
- // readjust dmin maximums
- $('.pid_tuning .ROLL input[name="d"]').change();
- $('.pid_tuning .PITCH input[name="d"]').change();
- $('.pid_tuning .YAW input[name="d"]').change();
+ if (semver.lt(FC.CONFIG.apiVersion, API_VERSION_1_44)) {
+ allPidTuningSliders.mouseup(function() {
+ // readjust dmin maximums
+ $('.pid_tuning .ROLL input[name="d"]').change();
+ $('.pid_tuning .PITCH input[name="d"]').change();
+ $('.pid_tuning .YAW input[name="d"]').change();
+ });
+ } else {
TuningSliders.updatePidSlidersDisplay();
- });
+ TuningSliders.updateSlidersWarning();
+ }
// reset to middle with double click
allPidTuningSliders.dblclick(function() {
const slider = $(this);
- slider.val(1);
- if (slider.is('#sliderMasterMultiplier')) {
- TuningSliders.sliderMasterMultiplier = 1;
- } else if (slider.is('#sliderRollPitchRatio')) {
- TuningSliders.sliderRollPitchRatio = 1;
- } else if (slider.is('#sliderIGain')) {
- TuningSliders.sliderIGain = 1;
- } else if (slider.is('#sliderPDRatio')) {
- TuningSliders.sliderPDRatio = 1;
- } else if (slider.is('#sliderPDGain')) {
- TuningSliders.sliderPDGain = 1;
- } else if (slider.is('#sliderDMinRatio')) {
- TuningSliders.sliderDMinRatio = 1;
- } else if (slider.is('#sliderFeedforwardGain')) {
- TuningSliders.sliderFeedforwardGain = 1;
+ let value;
+
+ if (semver.gte(FC.CONFIG.apiVersion, API_VERSION_1_44)) {
+ if (slider.is('#sliderDGain')) {
+ value = FC.DEFAULT_TUNING_SLIDERS.slider_d_gain / 100;
+ TuningSliders.sliderDGain = value;
+ } else if (slider.is('#sliderPIGain')) {
+ value = FC.DEFAULT_TUNING_SLIDERS.slider_pi_gain / 100;
+ TuningSliders.sliderPIGain = value;
+ } else if (slider.is('#sliderFeedforwardGain')) {
+ value = FC.DEFAULT_TUNING_SLIDERS.slider_feedforward_gain / 100;
+ TuningSliders.sliderFeedforwardGain = value;
+ } else if (slider.is('#sliderDMaxGain')) {
+ value = FC.DEFAULT_TUNING_SLIDERS.slider_dmax_gain / 100;
+ TuningSliders.sliderDMaxGain = value;
+ } else if (slider.is('#sliderIGain')) {
+ value = FC.DEFAULT_TUNING_SLIDERS.slider_i_gain / 100;
+ TuningSliders.sliderIGain = value;
+ } else if (slider.is('#sliderRollPitchRatio')) {
+ value = FC.DEFAULT_TUNING_SLIDERS.slider_roll_pitch_ratio / 100;
+ TuningSliders.sliderRollPitchRatio = value;
+ } else if (slider.is('#sliderPitchPIGain')) {
+ value = FC.DEFAULT_TUNING_SLIDERS.slider_pitch_pi_gain / 100;
+ TuningSliders.sliderPitchPIGain = value;
+ } else if (slider.is('#sliderMasterMultiplier')) {
+ value = FC.DEFAULT_TUNING_SLIDERS.slider_master_multiplier / 100;
+ TuningSliders.sliderMasterMultiplier = value;
+ }
+ slider.val(TuningSliders.downscaleSliderValue(value));
+ } else {
+ if (slider.is('#sliderMasterMultiplierLegacy')) {
+ TuningSliders.sliderMasterMultiplierLegacy = 1;
+ } else if (slider.is('#sliderPDRatio')) {
+ TuningSliders.sliderPDRatio = 1;
+ } else if (slider.is('#sliderPDGain')) {
+ TuningSliders.sliderPDGain = 1;
+ } else if (slider.is('#sliderFeedforwardGainLegacy')) {
+ TuningSliders.sliderFeedforwardGainLegacy = 1;
+ }
}
+
TuningSliders.calculateNewPids();
TuningSliders.updatePidSlidersDisplay();
});
@@ -1953,8 +2128,8 @@ TABS.pid_tuning.initialize = function (callback) {
$('a.buttonPidTuningSliders').click(function() {
//set Slider PID mode to RPY when re-enabling Sliders
if (semver.gte(FC.CONFIG.apiVersion, API_VERSION_1_44)) {
- FC.TUNING_SLIDERS.slider_pids_mode = 2;
- $('#sliderPidsModeSelect').val(FC.TUNING_SLIDERS.slider_pids_mode);
+ $('#sliderPidsModeSelect').val(2).trigger('change');
+ self.sliderModeHasChanged = true;
}
// if values were previously changed manually and then sliders are reactivated, reset pids to previous valid values if available, else default
TuningSliders.resetPidSliders();
@@ -1966,30 +2141,40 @@ TABS.pid_tuning.initialize = function (callback) {
self.analyticsChanges['PidTuningSliders'] = "On";
});
- // filter slider inputs
+ // enable filter sliders inputs
const allFilterTuningSliders = $('#sliderGyroFilterMultiplier, #sliderDTermFilterMultiplier');
- allFilterTuningSliders.on('input', function() {
+ allFilterTuningSliders.on('input mouseup', function() {
const slider = $(this);
- // adjust step for more smoothness above 1x
- if (slider.val() >= 1) {
- slider.attr('step', SLIDER_STEP_LOWER);
+
+ if (semver.gte(FC.CONFIG.apiVersion, API_VERSION_1_44)) {
+ if (slider.is('#sliderGyroFilterMultiplier')) {
+ slider.attr('step', SLIDER_STEP_UPPER * 2);
+ } else {
+ slider.attr('step', SLIDER_STEP_UPPER);
+ }
} else {
- slider.attr('step', SLIDER_STEP_UPPER);
+ // adjust step for more smoothness above 1x
+ if (slider.val() >= 1) {
+ slider.attr('step', SLIDER_STEP_LOWER);
+ } else {
+ slider.attr('step', SLIDER_STEP_UPPER);
+ }
}
- if (!TuningSliders.expertMode && semver.lt(FC.CONFIG.apiVersion, API_VERSION_1_44)) {
+ if (!TuningSliders.expertMode) {
if (slider.val() > NON_EXPERT_SLIDER_MAX) {
slider.val(NON_EXPERT_SLIDER_MAX);
} else if (slider.val() < NON_EXPERT_SLIDER_MIN) {
slider.val(NON_EXPERT_SLIDER_MIN);
}
}
- const scaledValue = TuningSliders.scaleSliderValue(slider.val());
+ const sliderValue = isInt(slider.val()) ? parseInt(slider.val()) : parseFloat(slider.val());
+ const scaledValue = TuningSliders.scaleSliderValue(sliderValue);
if (slider.is('#sliderGyroFilterMultiplier')) {
TuningSliders.sliderGyroFilterMultiplier = scaledValue;
TuningSliders.calculateNewGyroFilters();
self.analyticsChanges['GyroFilterTuningSlider'] = "On";
} else if (slider.is('#sliderDTermFilterMultiplier')) {
- TuningSliders.sliderDTermFilterMultiplier = scaledValue;
+ TuningSliders.sliderDTermFilterMultiplier = sliderValue;
TuningSliders.calculateNewDTermFilters();
self.analyticsChanges['DTermFilterTuningSlider'] = "On";
}
@@ -2008,6 +2193,7 @@ TABS.pid_tuning.initialize = function (callback) {
});
// enable Filter sliders button
$('a.buttonFilterTuningSliders').click(function() {
+ self.sliderModeHasChanged = true;
if (TuningSliders.GyroSliderUnavailable) {
//set Slider mode to ON when re-enabling Sliders
if (semver.gte(FC.CONFIG.apiVersion, API_VERSION_1_44)) {
@@ -2079,8 +2265,8 @@ TABS.pid_tuning.initialize = function (callback) {
// update == save.
$('a.update').click(function () {
form_to_pid_and_rc();
-
self.updating = true;
+
Promise.resolve(true)
.then(function () {
let promise;
@@ -2113,6 +2299,9 @@ TABS.pid_tuning.initialize = function (callback) {
return MSP.promise(MSPCodes.MSP_EEPROM_WRITE);
}).then(function () {
self.updating = false;
+ self.sliderPositionHasChanged = false;
+ self.sliderModeHasChanged = false;
+ self.sliderChanges = {};
self.setDirty(false);
GUI.log(i18n.getMessage('pidTuningEepromSaved'));
@@ -2174,7 +2363,7 @@ TABS.pid_tuning.renderModel = function () {
this.currentRates.rc_expo,
this.currentRates.superexpo,
this.currentRates.deadband,
- this.currentRates.roll_rate_limit
+ this.currentRates.roll_rate_limit,
);
const pitch = delta * this.rateCurve.rcCommandRawToDegreesPerSecond(
FC.RC.channels[1],
@@ -2183,7 +2372,7 @@ TABS.pid_tuning.renderModel = function () {
this.currentRates.rc_pitch_expo,
this.currentRates.superexpo,
this.currentRates.deadband,
- this.currentRates.pitch_rate_limit
+ this.currentRates.pitch_rate_limit,
);
const yaw = delta * this.rateCurve.rcCommandRawToDegreesPerSecond(
FC.RC.channels[2],
@@ -2192,7 +2381,7 @@ TABS.pid_tuning.renderModel = function () {
this.currentRates.rc_yaw_expo,
this.currentRates.superexpo,
this.currentRates.yawDeadband,
- this.currentRates.yaw_rate_limit
+ this.currentRates.yaw_rate_limit,
);
this.model.rotateBy(-degToRad(pitch), -degToRad(yaw), -degToRad(roll));
@@ -2222,6 +2411,10 @@ TABS.pid_tuning.cleanup = function (callback) {
TABS.pid_tuning.refresh = function (callback) {
const self = this;
+ if ((self.sliderPositionHasChanged || self.sliderModeHasChanged) && !self.updating) {
+ TuningSliders.restoreInitialSettings();
+ }
+
GUI.tab_switch_cleanup(function () {
self.initialize();
@@ -2280,7 +2473,9 @@ TABS.pid_tuning.checkUpdateProfile = function (updateRateProfile) {
}
if (changedProfile || changedRateProfile) {
+ self.updating = true;
self.refresh(function () {
+ self.updating = false;
if (changedProfile) {
GUI.log(i18n.getMessage('pidTuningReceivedProfile', [FC.CONFIG.profile + 1]));
FC.CONFIG.profile = self.currentProfile;
@@ -2502,9 +2697,9 @@ TABS.pid_tuning.updateRatesLabels = function() {
balloonsDirty = []; // reset the dirty balloon draw area (for overlap detection)
// create an array of balloons to draw
const balloons = [
- {value: parseInt(maxAngularVelRoll), balloon: function() {drawBalloonLabel(stickContext, maxAngularVelRoll, curveWidth, rateScale * (maxAngularVel - parseInt(maxAngularVelRoll)), 'right', BALLOON_COLORS.roll, balloonsDirty);}},
+ {value: parseInt(maxAngularVelRoll), balloon: function() {drawBalloonLabel(stickContext, maxAngularVelRoll, curveWidth, rateScale * (maxAngularVel - parseInt(maxAngularVelRoll)), 'right', BALLOON_COLORS.roll, balloonsDirty);}},
{value: parseInt(maxAngularVelPitch), balloon: function() {drawBalloonLabel(stickContext, maxAngularVelPitch, curveWidth, rateScale * (maxAngularVel - parseInt(maxAngularVelPitch)), 'right', BALLOON_COLORS.pitch, balloonsDirty);}},
- {value: parseInt(maxAngularVelYaw), balloon: function() {drawBalloonLabel(stickContext, maxAngularVelYaw, curveWidth, rateScale * (maxAngularVel - parseInt(maxAngularVelYaw)), 'right', BALLOON_COLORS.yaw, balloonsDirty);}}
+ {value: parseInt(maxAngularVelYaw), balloon: function() {drawBalloonLabel(stickContext, maxAngularVelYaw, curveWidth, rateScale * (maxAngularVel - parseInt(maxAngularVelYaw)), 'right', BALLOON_COLORS.yaw, balloonsDirty);}},
];
// show warning message if any axis angular velocity exceeds 1800d/s
const MAX_RATE_WARNING = 1800;
@@ -2520,7 +2715,7 @@ TABS.pid_tuning.updateRatesLabels = function() {
balloons.push(
{value: parseInt(currentValues[0]), balloon: function() {drawBalloonLabel(stickContext, currentValues[0], 10, 150, 'none', BALLOON_COLORS.roll, balloonsDirty);}},
{value: parseInt(currentValues[1]), balloon: function() {drawBalloonLabel(stickContext, currentValues[1], 10, 250, 'none', BALLOON_COLORS.pitch, balloonsDirty);}},
- {value: parseInt(currentValues[2]), balloon: function() {drawBalloonLabel(stickContext, currentValues[2], 10, 350, 'none', BALLOON_COLORS.yaw, balloonsDirty);}}
+ {value: parseInt(currentValues[2]), balloon: function() {drawBalloonLabel(stickContext, currentValues[2], 10, 350, 'none', BALLOON_COLORS.yaw, balloonsDirty);}},
);
}
// then display them on the chart
@@ -2585,6 +2780,23 @@ TABS.pid_tuning.updatePIDColors = function(clear = false) {
setTuningElementColor($('.pid_tuning .YAW input[name="f"]'), FC.ADVANCED_TUNING_ACTIVE.feedforwardYaw, FC.ADVANCED_TUNING.feedforwardYaw);
};
+TABS.pid_tuning.updateGuiElements = function() {
+ const rollF = parseInt($('.pid_tuning .ROLL input[name="f"]').val());
+ const pitchF = parseInt($('.pid_tuning .PITCH input[name="f"]').val());
+ const yawF = parseInt($('.pid_tuning .YAW input[name="f"]').val());
+ const FF_SWITCH = rollF || pitchF || yawF;
+ $('input[id="feedforwardGroup"]').prop('checked', FF_SWITCH).trigger('change');
+
+ const dRoll = parseInt($('.pid_tuning .ROLL input[name="d"]').val());
+ const dPitch = parseInt($('.pid_tuning .PITCH input[name="d"]').val());
+ const dYaw = parseInt($('.pid_tuning .YAW input[name="d"]').val());
+ const dMinRoll = parseInt($('.pid_tuning input[name="dMinRoll"]').val());
+ const dMinPitch = parseInt($('.pid_tuning input[name="dMinPitch"]').val());
+ const dMinYaw = parseInt($('.pid_tuning input[name="dMinYaw"]').val());
+ const DMAX_GAIN_SWITCH = dRoll !== dMinRoll || dPitch !== dMinPitch || dYaw !== dMinYaw;
+ $('#dMinSwitch').prop('checked', DMAX_GAIN_SWITCH).trigger('change');
+};
+
TABS.pid_tuning.changeRatesType = function(rateTypeID) {
const self = this;
const dialogRatesType = $('.dialogRatesType')[0];
diff --git a/src/js/utils/common.js b/src/js/utils/common.js
index 2e2e108a..bf3b5017 100644
--- a/src/js/utils/common.js
+++ b/src/js/utils/common.js
@@ -26,6 +26,10 @@ export function bytesToSize(bytes) {
return outputBytes;
}
+export function isInt(n) {
+ return n % 1 === 0;
+}
+
/*
* checkChromeRuntimeError() has to be called after each chrome API call
*/
@@ -107,6 +111,7 @@ export function sortElement(element, keepDown = "DISABLED") {
// TODO: these are temp binding while transition to module happens
window.degToRad = degToRad;
window.bytesToSize = bytesToSize;
+window.isInt = isInt;
window.checkChromeRuntimeError = checkChromeRuntimeError;
window.generateVirtualApiVersions = generateVirtualApiVersions;
window.getMixerImageSrc = getMixerImageSrc;
diff --git a/src/tabs/pid_tuning.html b/src/tabs/pid_tuning.html
index 1c988321..27e4c0ee 100644
--- a/src/tabs/pid_tuning.html
+++ b/src/tabs/pid_tuning.html
@@ -39,9 +39,11 @@
+ + | ++ + | ++ + | ++ + | +||
+ + | ++ + | ++ + | ++ + | +||
+ + | ++ + | ++ + | ++ + | +||
+ + | ++ + | ++ + | ++ + | +||
+ + | ++ + | ++ + | ++ + | +||
+ + | ++ + | ++ + | ++ + | +||
+ + | ++ + | ++ + | ++ + | +||
+ + | ++ + | ++ + | ++ + | +||
+ + | ++ + | ++ + | ++ + | +||
+ + | ++ + | ++ + | ++ + | +||
+ + | ++ + | ++ + | ++ + | +||
@@ -203,89 +364,7 @@ | |||||
- - | -- - | -- - | -- - | -||
- - | -- - | -- - | -- - | -||
- - | -- - | -- - | -- - | -||
- - | -- - | -- - | -- - | -||
- - | -- - | -- - | -- - | -||
- - | -- - | -- - | -- - | -