Crash course on PID tuning
Posted: Tue Mar 31, 2020 3:31 am
Feedback loops show up in tuning from time to time. Turbocharged cars often use it to control boost. Cruise-control uses feedback to control speed. Drive-by-wire cars use feedback to control the throttle blade angle when idling, and cable-throttle cars use it to control the IAC motor. I recently had some major headaches with my car stalling when it was supposed to return to idle (e.g. when I push the clutch pedal and lift off the gas pedal) and that turned out to be due to the PID feedback loop that controls idle airflow.
The total feedback is just three terms (values) added together: Proportional, Integral, and Derivative terms (hence "PID" feedback). Those get added to the default position of the throttle blade or IAC, which is determined by the "desired airflow" or "base airflow" table (two names for the same thing). The default throttle position should be close to the right position to get the desired idle speed - the closer the better. But it doesn't need to be exactly right because the feedback will take care of the rest.
"Gain" is just a number that scales the amount of a feedback term. The PCM contains a bunch of tables that contain gain values.
"Error" is the difference between the target value (sometimes called "setpoint") and the actual value. So for idle the error is just actual_RPM - desired_RPM.
All of this gets evaluated around 50 to 100 times per second:
Proportional term = proportional_gain * error
This term is "proportional" to the error. Large errors cause large values. This can't get the idle to the target speed by itself though, because if the error was zero this term would be zero and the throttle/IAC would go back to the default position. So this term will pull the actuator in the right direction, but not quite far enough.
Integrated_error = integrated_error + error
Integral term = integral_gain * integrated_error
Note that the first formula above is adding the error value to the integrated_error value. So if the engine is 100 RPM too high for a short period of time, the integrated error will be small, but if it stays 100 RPM too high for a while, the integrated error value will grow larger. So this term will gradually open the throttle further and further, until RPM reaches the target value. This term could be sufficient by itself, but you get better/faster results with all three terms.
One common problem with the integral term is that it can get quite large over time (called "integral windup") and then it takes a while to shrink back down. That was a big part of my stalling problem. I'd let off the gas and push in the clutch, the integral term would aggressively close the throttle (because it was tuned for a 50 pound clutch/flywheel) and then the engine would stall because the throttle was closed. Turning this way down helped a lot.
Derivative_error = error - error_from_previous_iteration
Derivative term = derivative_gain * derivative_error
The value of this term depends on whether the error is growing or shrinking. This helps offset the integral windup problem. For example, when the integral term is growing large and RPM is rapidly approaching the target, this term opens the throttle to avoid overshooting idle and staling the engine. I was turning this up 10% at a time today.
Throttle blade angle (or IAC position) = default + proportional + integral + derivative + idle_trim
I'm not 100% sure about the idle trim but I think it is just based on the integral term, but updated very slowly. That way the integral term doesn't need to rediscover the right value every time you return to idle.
You can kinda think of the P, I, and D gains as just a single number. Feedback loops work OK that way. But the PCM looks up the gain based on tables for a little more flexibility. There are separate columns for "RPM too high" and "RPM too low" gains, which is nice because it let me use high gain for underspeed and low gain for overspeed.
The proportional gain stays at zero for small errors, which means that the throttle blade doesn't move, and instead the PCM relies on ignition timing to make small corrections to idle speed.
The total feedback is just three terms (values) added together: Proportional, Integral, and Derivative terms (hence "PID" feedback). Those get added to the default position of the throttle blade or IAC, which is determined by the "desired airflow" or "base airflow" table (two names for the same thing). The default throttle position should be close to the right position to get the desired idle speed - the closer the better. But it doesn't need to be exactly right because the feedback will take care of the rest.
"Gain" is just a number that scales the amount of a feedback term. The PCM contains a bunch of tables that contain gain values.
"Error" is the difference between the target value (sometimes called "setpoint") and the actual value. So for idle the error is just actual_RPM - desired_RPM.
All of this gets evaluated around 50 to 100 times per second:
Proportional term = proportional_gain * error
This term is "proportional" to the error. Large errors cause large values. This can't get the idle to the target speed by itself though, because if the error was zero this term would be zero and the throttle/IAC would go back to the default position. So this term will pull the actuator in the right direction, but not quite far enough.
Integrated_error = integrated_error + error
Integral term = integral_gain * integrated_error
Note that the first formula above is adding the error value to the integrated_error value. So if the engine is 100 RPM too high for a short period of time, the integrated error will be small, but if it stays 100 RPM too high for a while, the integrated error value will grow larger. So this term will gradually open the throttle further and further, until RPM reaches the target value. This term could be sufficient by itself, but you get better/faster results with all three terms.
One common problem with the integral term is that it can get quite large over time (called "integral windup") and then it takes a while to shrink back down. That was a big part of my stalling problem. I'd let off the gas and push in the clutch, the integral term would aggressively close the throttle (because it was tuned for a 50 pound clutch/flywheel) and then the engine would stall because the throttle was closed. Turning this way down helped a lot.
Derivative_error = error - error_from_previous_iteration
Derivative term = derivative_gain * derivative_error
The value of this term depends on whether the error is growing or shrinking. This helps offset the integral windup problem. For example, when the integral term is growing large and RPM is rapidly approaching the target, this term opens the throttle to avoid overshooting idle and staling the engine. I was turning this up 10% at a time today.
Throttle blade angle (or IAC position) = default + proportional + integral + derivative + idle_trim
I'm not 100% sure about the idle trim but I think it is just based on the integral term, but updated very slowly. That way the integral term doesn't need to rediscover the right value every time you return to idle.
You can kinda think of the P, I, and D gains as just a single number. Feedback loops work OK that way. But the PCM looks up the gain based on tables for a little more flexibility. There are separate columns for "RPM too high" and "RPM too low" gains, which is nice because it let me use high gain for underspeed and low gain for overspeed.
The proportional gain stays at zero for small errors, which means that the throttle blade doesn't move, and instead the PCM relies on ignition timing to make small corrections to idle speed.