Betaflight Dterm Setpoint Weight Feed Feedforward Calculator

Betaflight DTerm Setpoint Weight Feedforward Calculator :root { –primary-color: #004a99; –success-color: #28a745; –background-color: #f8f9fa; –text-color: #333; –border-color: #ddd; –card-background: #fff; –error-color: #dc3545; } body { font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; background-color: var(–background-color); color: var(–text-color); line-height: 1.6; margin: 0; padding: 0; } .container { max-width: 1000px; margin: 20px auto; padding: 20px; background-color: var(–card-background); border-radius: 8px; box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1); } header { text-align: center; margin-bottom: 30px; padding-bottom: 20px; border-bottom: 1px solid var(–border-color); } h1 { color: var(–primary-color); margin-bottom: 10px; } .subtitle { font-size: 1.1em; color: #555; } .loan-calc-container { background-color: var(–card-background); padding: 25px; border-radius: 8px; box-shadow: 0 1px 5px rgba(0, 0, 0, 0.05); margin-bottom: 30px; } .input-group { margin-bottom: 20px; padding: 15px; border: 1px solid var(–border-color); border-radius: 5px; background-color: #fdfdfd; } .input-group label { display: block; margin-bottom: 8px; font-weight: bold; color: var(–primary-color); } .input-group input[type="number"], .input-group select { width: calc(100% – 22px); padding: 10px; border: 1px solid var(–border-color); border-radius: 4px; font-size: 1em; margin-top: 5px; } .input-group .helper-text { font-size: 0.85em; color: #6c757d; margin-top: 5px; display: block; } .error-message { color: var(–error-color); font-size: 0.8em; margin-top: 5px; display: none; /* Hidden by default */ } .button-group { display: flex; justify-content: space-between; margin-top: 25px; gap: 10px; } button { padding: 12px 20px; border: none; border-radius: 5px; cursor: pointer; font-size: 1em; font-weight: bold; transition: background-color 0.3s ease; } .btn-primary { background-color: var(–primary-color); color: white; } .btn-primary:hover { background-color: #003366; } .btn-secondary { background-color: #6c757d; color: white; } .btn-secondary:hover { background-color: #5a6268; } .btn-reset { background-color: #ffc107; color: #212529; } .btn-reset:hover { background-color: #e0a800; } .results-container { margin-top: 30px; padding: 25px; background-color: var(–primary-color); color: white; border-radius: 8px; text-align: center; box-shadow: 0 4px 15px rgba(0, 74, 153, 0.3); } .results-container h2 { margin-top: 0; color: white; font-size: 1.8em; } .main-result { font-size: 2.5em; font-weight: bold; margin: 15px 0; display: block; padding: 10px; background-color: rgba(255, 255, 255, 0.2); border-radius: 5px; } .intermediate-results { display: flex; justify-content: space-around; flex-wrap: wrap; margin-top: 20px; gap: 15px; } .intermediate-results div { text-align: center; padding: 10px 15px; background-color: rgba(255, 255, 255, 0.15); border-radius: 5px; flex: 1; min-width: 150px; } .intermediate-results span { display: block; font-size: 1.8em; font-weight: bold; } .formula-explanation { margin-top: 20px; font-size: 0.9em; color: rgba(255, 255, 255, 0.8); border-top: 1px solid rgba(255, 255, 255, 0.2); padding-top: 15px; } .chart-container { margin-top: 30px; padding: 25px; background-color: var(–card-background); border-radius: 8px; box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1); text-align: center; } .chart-container h2 { color: var(–primary-color); margin-bottom: 20px; } canvas { max-width: 100%; height: auto; } .table-container { margin-top: 30px; overflow-x: auto; } table { width: 100%; border-collapse: collapse; margin-top: 15px; box-shadow: 0 2px 5px rgba(0, 0, 0, 0.05); } th, td { padding: 12px 15px; text-align: left; border: 1px solid var(–border-color); } thead { background-color: var(–primary-color); color: white; } th { font-weight: bold; } tbody tr:nth-child(even) { background-color: #f2f2f2; } tbody tr:hover { background-color: #e9ecef; } caption { font-size: 1.1em; font-weight: bold; color: var(–text-color); margin-bottom: 10px; text-align: left; } .article-section { margin-top: 40px; padding: 30px; background-color: var(–card-background); border-radius: 8px; box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1); } .article-section h2, .article-section h3 { color: var(–primary-color); margin-bottom: 15px; } .article-section h3 { margin-top: 25px; } .article-section p { margin-bottom: 15px; } .article-section ul, .article-section ol { margin-left: 20px; margin-bottom: 15px; } .article-section li { margin-bottom: 8px; } .faq-item { margin-bottom: 15px; padding: 10px; border-left: 3px solid var(–primary-color); background-color: #fefefe; } .faq-item strong { color: var(–primary-color); } .internal-links-section ul { list-style: none; padding: 0; } .internal-links-section li { margin-bottom: 10px; } .internal-links-section a { color: var(–primary-color); text-decoration: none; font-weight: bold; } .internal-links-section a:hover { text-decoration: underline; } .internal-links-section span { font-size: 0.9em; color: #555; display: block; margin-top: 3px; } .highlight { background-color: var(–success-color); color: white; padding: 2px 5px; border-radius: 3px; } .code-snippet { background-color: #e9ecef; padding: 10px; border-radius: 4px; font-family: 'Courier New', Courier, monospace; font-size: 0.9em; overflow-x: auto; margin-bottom: 15px; } @media (max-width: 768px) { .container { margin: 10px; padding: 15px; } .button-group { flex-direction: column; } .intermediate-results { flex-direction: column; align-items: center; } .intermediate-results div { width: 80%; margin-bottom: 15px; } }

Betaflight DTerm Setpoint Weight Feedforward Calculator

Optimize your drone's PID tuning for superior flight stability and responsiveness.

PID Tuning Parameters

Maximum expected gyro rate during aggressive maneuvers.
Your Betaflight PID loop time in microseconds (e.g., 1000 for 1kHz, 2000 for 500Hz).
The cutoff frequency of the DTerm low-pass filter in Hertz.
Weighting for the setpoint in the DTerm calculation (typically 0.0 to 1.0). Higher values make the quad react faster to stick inputs.
Weighting for the Feedforward term. Higher values can improve responsiveness but increase the risk of oscillations.
Controls how quickly Feedforward is applied based on stick input magnitude. 0.0 disables it.

Recommended PID Tuning Values

DTerm Setpoint Weight

Feed

Feedforward

The DTerm Setpoint Weight is directly set. Feed is calculated as (Setpoint Weight * Gyro Rate) / Looptime. Feedforward is calculated based on its weight and the setpoint input.

PID Tuning Response Simulation

Simulated response curves for different PID tuning parameters.
Parameter Value Unit Description
Gyro Rate deg/s Max expected gyro rate.
Looptime us PID loop time.
DTerm Filter Hz DTerm filter cutoff.
Setpoint Weight N/A Setpoint influence on DTerm.
Feedforward Weight N/A Feedforward influence.
Feedforward Transition N/A Feedforward application threshold.
Calculated Feed N/A Internal feed calculation.
Calculated Feedforward N/A Internal feedforward calculation.

What is Betaflight DTerm Setpoint Weight Feedforward?

The Betaflight DTerm Setpoint Weight Feedforward calculator is a specialized tool designed for FPV (First Person View) drone pilots and builders. It helps in fine-tuning the PID (Proportional-Integral-Derivative) control loops of a drone's flight controller software, specifically Betaflight. The core purpose is to optimize how the drone responds to pilot inputs and external disturbances, leading to a more stable, predictable, and agile flight experience. Understanding and adjusting these parameters, particularly DTerm Setpoint Weight, Feed, and Feedforward, is crucial for achieving a locked-in feel and preventing oscillations or sluggishness.

Who Should Use It?

This calculator is primarily for:

  • FPV Drone Pilots: Especially those who build their own drones or frequently adjust PID settings for racing, freestyle, or cinematic flying.
  • Drone Builders: Individuals assembling custom FPV drones who need to set initial PID values or troubleshoot tuning issues.
  • Enthusiasts: Anyone interested in the technical aspects of drone flight control and seeking to improve their drone's performance.

Common Misconceptions

  • "Higher is always better": This is a dangerous misconception. Increasing DTerm Setpoint Weight or Feedforward too much can lead to high-frequency oscillations, motor desync, or even flyaways.
  • "PID tuning is a one-time fix": PID tuning is often an iterative process. Changes in drone weight, motor/propeller combinations, or flying style may necessitate re-tuning.
  • "Feedforward is the same as P": While both influence responsiveness, Feedforward is specifically designed to anticipate changes based on pilot input, whereas the P term reacts to the current error.

DTerm Setpoint Weight, Feed, and Feedforward Formula and Mathematical Explanation

The Betaflight PID controller calculates control outputs based on the error between the desired state (setpoint) and the current state (gyro reading). The DTerm (Derivative) component helps to dampen oscillations and improve stability by reacting to the *rate of change* of the error. However, raw DTerm can be noisy and overly sensitive. Setpoint Weight, Feed, and Feedforward are mechanisms to modify and enhance the DTerm's behavior.

Core Concepts:

  • DTerm: Primarily reacts to the rate of change of the error signal. Helps to prevent overshoot and oscillations.
  • Setpoint Weight: This parameter directly influences how much the *desired* change (from pilot input) affects the DTerm calculation. A higher Setpoint Weight makes the DTerm more sensitive to stick movements, leading to quicker reactions.
  • Feed: This term is essentially a scaled version of the DTerm calculation, often influenced by the Setpoint Weight and the drone's expected performance (like gyro rate and looptime). It helps normalize the DTerm's sensitivity across different configurations.
  • Feedforward: This term aims to predict and counteract future errors based on the pilot's input *before* the error actually occurs. It significantly boosts responsiveness, especially for quick stick movements.

The Formulas (Simplified Betaflight Logic):

In Betaflight, the DTerm calculation itself is complex, involving filtering and scaling. However, the parameters we adjust relate to how these components are weighted and applied.

// Simplified conceptual representation: var error = setpoint – current_angle;
var derivative = calculate_derivative(error); // Includes filtering
var dterm_output = derivative * pid_gains.d;
// DTerm Setpoint Weight (Directly applied in Betaflight's internal logic) // The 'setpoint_weight' parameter directly modulates the error signal before derivative calculation, // or influences the final DTerm output depending on Betaflight version and specific implementation. // For simplicity, we consider its effect on the overall DTerm sensitivity. // Feed Calculation (Conceptual) // Feed aims to provide a baseline DTerm-like response based on expected performance. var feed = (setpoint_weight * gyro_rate) / looptime; // Feedforward Calculation (Conceptual) // Feedforward is often proportional to the input stick magnitude and the feedforward weight. // A transition value can be used to enable it only above a certain stick input threshold. var stick_input_magnitude = calculate_stick_input_magnitude(); var feedforward_output = 0; if (stick_input_magnitude > feedforward_transition) { feedforward_output = feedforward_weight * stick_input_magnitude * some_scaling_factor; } // Final Output (Conceptual) // final_output = p_term + i_term + dterm_output + feed + feedforward_output;

Variable Explanations:

Variable Meaning Unit Typical Range
Gyro Rate Maximum expected angular velocity the drone might experience. deg/s 500 – 2000+
Looptime The time interval (in microseconds) at which the PID loop executes. Lower is faster. us 250 (4kHz) – 2000 (500Hz)
DTerm Filter Hz Cutoff frequency for the low-pass filter applied to the DTerm signal. Hz 50 – 250
Setpoint Weight Weighting factor for the setpoint in the DTerm calculation. N/A (Multiplier) 0.0 – 1.0 (Can sometimes exceed 1.0, but not recommended)
Feedforward Weight Weighting factor for the Feedforward term. N/A (Multiplier) 0.0 – 1.0 (Higher values increase risk of oscillations)
Feedforward Transition Threshold for stick input magnitude to activate Feedforward. N/A (Normalized Input) 0.0 – 1.0
Feed Calculated intermediate value based on Setpoint Weight, Gyro Rate, and Looptime. N/A Varies
Feedforward Calculated intermediate value based on Feedforward Weight and input. N/A Varies

Practical Examples (Real-World Use Cases)

Let's explore how different settings impact the calculated values and what they mean for flight performance.

Example 1: Agile Freestyle Quad

A pilot wants a highly responsive quad for freestyle maneuvers. They are running a fast looptime and expect high gyro rates.

  • Inputs:
  • Gyro Rate: 1500 deg/s
  • Looptime: 500 us (2kHz loop frequency)
  • DTerm Filter Hz: 120 Hz
  • Setpoint Weight: 0.8
  • Feedforward Weight: 0.3
  • Feedforward Transition: 0.4

Calculator Output (Illustrative):

  • DTerm Setpoint Weight: 0.8
  • Feed: (0.8 * 1500) / 500 = 2.4
  • Feedforward: (0.3 * Stick Input Magnitude) – Activated above 0.4 stick input

Interpretation: The high Setpoint Weight (0.8) combined with a fast looptime means the DTerm will react very strongly to pilot inputs. The moderate Feedforward weight (0.3) will further enhance responsiveness for quick stick movements, making flips and rolls feel sharp. The DTerm filter at 120Hz helps prevent noise from overwhelming the DTerm.

Example 2: Stable Cinematic Quad

A pilot prioritizes smooth, stable flight for cinematic shots, willing to sacrifice some immediate responsiveness for reduced oscillations.

  • Inputs:
  • Gyro Rate: 800 deg/s
  • Looptime: 1000 us (1kHz loop frequency)
  • DTerm Filter Hz: 80 Hz
  • Setpoint Weight: 0.3
  • Feedforward Weight: 0.0
  • Feedforward Transition: 0.0

Calculator Output (Illustrative):

  • DTerm Setpoint Weight: 0.3
  • Feed: (0.3 * 800) / 1000 = 0.24
  • Feedforward: 0.0 (Disabled)

Interpretation: The low Setpoint Weight (0.3) makes the DTerm less sensitive to pilot inputs, promoting smoother flight. Disabling Feedforward (0.0 weight) further reduces the chance of introducing unwanted jitters. The lower DTerm filter (80Hz) might be used if the setup is inherently less noisy or to ensure smoothness over raw reaction speed. The slower looptime also contributes to a less aggressive feel.

How to Use This Betaflight DTerm Setpoint Weight Feedforward Calculator

This calculator simplifies the complex process of PID tuning by providing recommended values and insights based on your drone's configuration and desired flight characteristics.

  1. Gather Your Drone's Specifications:
    • Gyro Rate: Estimate the maximum angular velocity (degrees per second) your drone might reach during aggressive maneuvers. You can often find typical values for different drone classes or estimate based on past experience.
    • Looptime: Check your Betaflight Configurator under the "PID Controller" tab. This is crucial for accurate calculations. Lower looptime (e.g., 500us) means faster processing.
    • DTerm Filter: Note the current DTerm filter setting in Betaflight. This filter helps reduce noise that can cause oscillations.
  2. Define Your Flight Style:
    • Setpoint Weight: Decide how responsive you want your drone to be to stick inputs. Higher values (e.g., 0.7-1.0) for aggressive freestyle/racing, lower values (e.g., 0.1-0.5) for smoother, cinematic flight.
    • Feedforward Weight: If you want even more responsiveness, especially for quick inputs, set a moderate value (e.g., 0.1-0.4). Start low and increase cautiously. Set to 0.0 to disable.
    • Feedforward Transition: If using Feedforward, set this value (e.g., 0.3-0.6) to control the stick input threshold at which Feedforward becomes active. This prevents it from interfering with gentle inputs.
  3. Enter Values into the Calculator: Input the gathered specifications and desired flight style parameters into the corresponding fields.
  4. Calculate PID Values: Click the "Calculate PID Values" button. The calculator will display:
    • Main Result: Often a summary or a key takeaway, though in this context, the intermediate values are more critical.
    • DTerm Setpoint Weight: The value you entered, confirming its role.
    • Feed: An intermediate calculation showing the scaled DTerm baseline.
    • Feedforward: The calculated Feedforward value based on your inputs.
  5. Interpret the Results:
    • The calculated values provide a starting point for your Betaflight PID tuning.
    • The chart visually represents how different parameters might affect the drone's response.
    • The table summarizes all input and calculated values for clarity.
  6. Apply and Test: Enter the recommended or adjusted values into your Betaflight Configurator. Always test incrementally in a safe environment. Make small adjustments and observe the flight characteristics. Listen for oscillations (high-pitched buzzing) and feel for sluggishness or jitters.
  7. Refine: PID tuning is iterative. Use the calculator as a guide, but trust your flight experience to make final adjustments. If you encounter oscillations, try lowering Setpoint Weight, Feedforward Weight, or increasing the DTerm filter. If the drone feels sluggish, consider increasing Setpoint Weight or Feedforward Weight cautiously.

Key Factors That Affect DTerm Setpoint Weight Feedforward Results

While the calculator provides a solid baseline, several real-world factors influence how these PID parameters perform and require adjustments:

  1. Drone Weight and Balance: A heavier drone requires more force to change its state, potentially needing higher P and D gains, or adjusted Setpoint Weight/Feedforward to maintain responsiveness without oscillation. Imbalanced weight distribution can introduce unwanted coupling between axes.
  2. Motor and Propeller Efficiency: Different motor KV ratings and propeller sizes/pitches have varying thrust and responsiveness characteristics. High-power systems might require lower Feedforward or DTerm gains to prevent overpowering the airframe and causing oscillations. Less powerful systems might need higher gains to feel responsive.
  3. Frame Rigidity: A flexible frame can introduce vibrations and resonance that interfere with gyro readings and PID calculations. This can make the DTerm noisy, necessitating a lower DTerm filter cutoff or reduced Setpoint Weight/Feedforward.
  4. ESC (Electronic Speed Controller) Performance: The quality and firmware of your ESCs affect how quickly and smoothly they can respond to commands from the flight controller. Poor ESC performance can lead to desyncs or sluggishness, impacting the effectiveness of PID tuning.
  5. Battery Voltage and State of Charge: As the battery discharges, its voltage drops, affecting motor power output. This can subtly change the drone's flight characteristics, sometimes requiring minor PID tweaks during a long flight session or between battery packs.
  6. Air Density and Wind Conditions: Flying in thinner air (higher altitude) or denser air (sea level) affects aerodynamic forces. Strong winds can constantly push the drone off its intended path, requiring the PID controller to work harder. While PID tuning aims for consistency, extreme conditions might highlight limitations.
  7. Flight Controller Processing Load: Running too many features (e.g., advanced telemetry, blackbox logging at high rates, complex OSD elements) can increase the CPU load on the flight controller, potentially impacting looptime consistency and PID loop execution, even if the set looptime is low.

Frequently Asked Questions (FAQ)

Q1: What is the ideal Setpoint Weight?
A: There's no single "ideal" value. It depends heavily on your drone's setup, looptime, and desired flight feel. Start around 0.5-0.7 for freestyle and adjust based on responsiveness and oscillations. For cinematic, start lower (0.1-0.3).
Q2: Can I set Feedforward Weight higher than 1.0?
A: Betaflight might allow it, but it's generally not recommended. Values significantly above 0.5 can easily lead to oscillations and instability. Always increase cautiously.
Q3: My drone oscillates after increasing Setpoint Weight. What should I do?
A: Lower the Setpoint Weight. You might also need to increase the DTerm filter frequency (e.g., from 100Hz to 120Hz or 150Hz) to filter out noise causing the oscillation, or slightly decrease the P gain.
Q4: What's the difference between Feed and Feedforward?
A: 'Feed' is often seen as a way to normalize the DTerm's sensitivity based on expected performance (gyro rate, looptime). 'Feedforward' is specifically designed to anticipate and react to pilot stick inputs *before* an error occurs, boosting responsiveness.
Q5: Does the DTerm Filter Hz affect the calculator results?
A: The calculator uses the DTerm Filter Hz as an input parameter because it's crucial for tuning stability. While the calculator doesn't directly compute the filter's cutoff, it acknowledges its importance. A lower filter value might allow higher Setpoint Weight/Feedforward without oscillation, while a higher value might require lower gains.
Q6: How does Looptime impact these calculations?
A: Looptime is critical. A lower looptime (faster loop) means the PID controller runs more frequently, allowing for quicker reactions. Calculations involving 'Feed' are inversely proportional to looptime; a shorter looptime results in a higher 'Feed' value for the same inputs, indicating potentially higher sensitivity.
Q7: Should I use the calculator values directly in Betaflight?
A: Use them as a strong starting point. Always perform test flights in a safe area and make small, incremental adjustments based on how the drone actually flies. Listen for oscillations and feel for responsiveness.
Q8: What does Feedforward Transition do?
A: It acts as a threshold. Feedforward is only applied when the pilot's stick input exceeds this normalized value (0.0 to 1.0). This prevents Feedforward from making small, precise movements feel jerky, while still providing boost for aggressive maneuvers.

Related Tools and Internal Resources

© 2023 Your FPV Tuning Hub. All rights reserved. This calculator and information are for educational purposes. Always fly responsibly and safely.

var chartInstance = null; // Global variable to hold chart instance function validateInput(value, id, min, max, name) { var errorElement = document.getElementById(id + 'Error'); errorElement.style.display = 'none'; // Hide previous error if (value === ") { errorElement.textContent = name + ' cannot be empty.'; errorElement.style.display = 'block'; return false; } var numValue = parseFloat(value); if (isNaN(numValue)) { errorElement.textContent = name + ' must be a valid number.'; errorElement.style.display = 'block'; return false; } if (min !== null && numValue max) { errorElement.textContent = name + ' cannot be greater than ' + max + '.'; errorElement.style.display = 'block'; return false; } return true; } function calculatePID() { var gyroRate = document.getElementById('gyroRate').value; var looptime = document.getElementById('looptime').value; var dtermFilterHz = document.getElementById('dtermFilterHz').value; var setpointWeight = document.getElementById('setpointWeight').value; var feedforwardWeight = document.getElementById('feedforwardWeight').value; var feedforwardTransition = document.getElementById('feedforwardTransition').value; // Validation var isValid = true; isValid &= validateInput(gyroRate, 'gyroRate', 1, null, 'Gyro Rate'); isValid &= validateInput(looptime, 'looptime', 1, null, 'Looptime'); isValid &= validateInput(dtermFilterHz, 'dtermFilterHz', 1, null, 'DTerm Filter'); isValid &= validateInput(setpointWeight, 'setpointWeight', 0, null, 'Setpoint Weight'); isValid &= validateInput(feedforwardWeight, 'feedforwardWeight', 0, null, 'Feedforward Weight'); isValid &= validateInput(feedforwardTransition, 'feedforwardTransition', 0, 1, 'Feedforward Transition'); if (!isValid) { document.getElementById('resultsSection').style.display = 'none'; return; } var numGyroRate = parseFloat(gyroRate); var numLooptime = parseFloat(looptime); var numDtermFilterHz = parseFloat(dtermFilterHz); var numSetpointWeight = parseFloat(setpointWeight); var numFeedforwardWeight = parseFloat(feedforwardWeight); var numFeedforwardTransition = parseFloat(feedforwardTransition); // Calculations var feed = (numSetpointWeight * numGyroRate) / numLooptime; // Feedforward calculation is conceptual and depends on stick input magnitude, which isn't directly input. // We'll represent it as a potential value based on max input. var conceptualFeedforward = numFeedforwardWeight * 1.0; // Assuming max stick input of 1.0 // Update results display document.getElementById('dtermSetpointWeightResult').textContent = numSetpointWeight.toFixed(2); document.getElementById('feedResult').textContent = feed.toFixed(2); document.getElementById('feedforwardResult').textContent = conceptualFeedforward.toFixed(2); document.getElementById('mainResult').textContent = "Tune based on flight feel"; // Main result is subjective // Update table document.getElementById('tableGyroRate').textContent = numGyroRate.toFixed(0); document.getElementById('tableLooptime').textContent = numLooptime.toFixed(0); document.getElementById('tableDtermFilterHz').textContent = numDtermFilterHz.toFixed(0); document.getElementById('tableSetpointWeight').textContent = numSetpointWeight.toFixed(2); document.getElementById('tableFeedforwardWeight').textContent = numFeedforwardWeight.toFixed(2); document.getElementById('tableFeedforwardTransition').textContent = numFeedforwardTransition.toFixed(2); document.getElementById('tableFeed').textContent = feed.toFixed(2); document.getElementById('tableFeedforward').textContent = conceptualFeedforward.toFixed(2); document.getElementById('resultsSection').style.display = 'block'; updateChart(numSetpointWeight, feed, conceptualFeedforward, numFeedforwardTransition); } function resetForm() { document.getElementById('gyroRate').value = 1000; document.getElementById('looptime').value = 1000; document.getElementById('dtermFilterHz').value = 100; document.getElementById('setpointWeight').value = 1.0; document.getElementById('feedforwardWeight').value = 0.0; document.getElementById('feedforwardTransition').value = 0.0; calculatePID(); // Recalculate with defaults } function copyResults() { var mainResult = document.getElementById('mainResult').textContent; var dtermSetpointWeight = document.getElementById('dtermSetpointWeightResult').textContent; var feed = document.getElementById('feedResult').textContent; var feedforward = document.getElementById('feedforwardResult').textContent; var tableGyroRate = document.getElementById('tableGyroRate').textContent; var tableLooptime = document.getElementById('tableLooptime').textContent; var tableDtermFilterHz = document.getElementById('tableDtermFilterHz').textContent; var tableSetpointWeight = document.getElementById('tableSetpointWeight').textContent; var tableFeedforwardWeight = document.getElementById('tableFeedforwardWeight').textContent; var tableFeedforwardTransition = document.getElementById('tableFeedforwardTransition').textContent; var tableFeed = document.getElementById('tableFeed').textContent; var tableFeedforward = document.getElementById('tableFeedforward').textContent; var resultsText = "— PID Tuning Results —\n\n"; resultsText += "Main Recommendation: " + mainResult + "\n"; resultsText += "DTerm Setpoint Weight: " + dtermSetpointWeight + "\n"; resultsText += "Feed: " + feed + "\n"; resultsText += "Feedforward: " + feedforward + "\n\n"; resultsText += "— Input Parameters —\n"; resultsText += "Gyro Rate: " + tableGyroRate + " deg/s\n"; resultsText += "Looptime: " + tableLooptime + " us\n"; resultsText += "DTerm Filter: " + tableDtermFilterHz + " Hz\n"; resultsText += "Setpoint Weight: " + tableSetpointWeight + "\n"; resultsText += "Feedforward Weight: " + tableFeedforwardWeight + "\n"; resultsText += "Feedforward Transition: " + tableFeedforwardTransition + "\n\n"; resultsText += "— Calculated Values —\n"; resultsText += "Feed: " + tableFeed + "\n"; resultsText += "Feedforward (Conceptual Max): " + tableFeedforward + "\n"; // Use a temporary textarea to copy text var textArea = document.createElement("textarea"); textArea.value = resultsText; textArea.style.position = "fixed"; textArea.style.left = "-9999px"; document.body.appendChild(textArea); textArea.focus(); textArea.select(); try { var successful = document.execCommand('copy'); var msg = successful ? 'Results copied!' : 'Copy failed'; console.log('Copy command was ' + msg); // Optionally show a temporary message to the user var copyButton = document.querySelector('button.btn-secondary'); var originalText = copyButton.textContent; copyButton.textContent = 'Copied!'; setTimeout(function() { copyButton.textContent = originalText; }, 2000); } catch (err) { console.log('Oops, unable to copy', err); } document.body.removeChild(textArea); } function updateChart(setpointWeight, feed, feedforward, transition) { var ctx = document.getElementById('pidResponseChart').getContext('2d'); // Clear previous chart if it exists if (chartInstance) { chartInstance.destroy(); } // Simulate data points for visualization // X-axis: Stick Input Magnitude (0 to 1) // Y-axis: Response Magnitude (Conceptual) var stickInputs = []; var dtermResponse = []; // Represents DTerm influenced by Setpoint Weight var ffResponse = []; // Represents Feedforward response for (var i = 0; i transition) { // Simplified: Scales with FF weight and stick input above transition currentFF = feedforward * (stickInput – transition) / (1 – transition); } ffResponse.push(currentFF); } chartInstance = new Chart(ctx, { type: 'line', data: { labels: stickInputs.map(val => val.toFixed(2)), // Labels for X-axis datasets: [{ label: 'DTerm Response (Setpoint Weight Influence)', data: dtermResponse, borderColor: 'rgba(0, 74, 153, 1)', // Primary color backgroundColor: 'rgba(0, 74, 153, 0.1)', fill: true, tension: 0.1 }, { label: 'Feedforward Response', data: ffResponse, borderColor: 'rgba(40, 167, 69, 1)', // Success color backgroundColor: 'rgba(40, 167, 69, 0.1)', fill: true, tension: 0.1 }] }, options: { responsive: true, maintainAspectRatio: false, scales: { x: { title: { display: true, text: 'Stick Input Magnitude (Normalized)' } }, y: { title: { display: true, text: 'Conceptual Response Magnitude' }, beginAtZero: true } }, plugins: { tooltip: { callbacks: { label: function(context) { var label = context.dataset.label || "; if (label) { label += ': '; } if (context.parsed.y !== null) { label += context.parsed.y.toFixed(3); } return label; } } } } } }); } // Initial calculation on page load document.addEventListener('DOMContentLoaded', function() { calculatePID(); });

Leave a Comment