diff --git a/config.default.h b/config.default.h index 5da1aa1..40eeaab 100644 --- a/config.default.h +++ b/config.default.h @@ -481,6 +481,14 @@ BANG_BANG_OFF PWM value for 'off' */ // #define BANG_BANG_OFF 45 +/** \def PID_CONDITIONAL_INTEGRATION + PID_CONDITIONAL_INTEGRATION + Controls 'integral windup' by preventing the integral term from accumulating error if the heater output is saturated high/low by + the other terms in the PID calculation. This is in addition to M133/I_LIMIT mechanism, and can help prevent overshoot in cases of + large setpoint changes which may overfill the integral term. + Costs 50 bytes. +*/ +//#define PID_CONDITIONAL_INTEGRATION /** move buffer size, in number of moves diff --git a/heater.c b/heater.c index 9fe1cc1..61fdd33 100644 --- a/heater.c +++ b/heater.c @@ -321,22 +321,26 @@ void heater_tick(heater_t h, temp_type_t type, uint16_t current_temp, uint16_t t // combine factors int32_t pid_output_intermed = ( // Units: counts - ( - (((int32_t) heater_p) * heaters_pid[h].p_factor) + - (((int32_t) heaters_runtime[h].heater_i) * heaters_pid[h].i_factor) + - (((int32_t) heater_d) * heaters_pid[h].d_factor) - ) / PID_SCALE - ); + ( + (((int32_t) heater_p) * heaters_pid[h].p_factor) + + (((int32_t) heaters_runtime[h].heater_i) * heaters_pid[h].i_factor) + + (((int32_t) heater_d) * heaters_pid[h].d_factor) + ) / PID_SCALE + ); // rebase and limit factors if (pid_output_intermed > 255) { + #ifdef PID_CONDITIONAL_INTEGRATION if (t_error > 0) heaters_runtime[h].heater_i -= t_error; // un-integrate + #endif pid_output = 255; } else if (pid_output_intermed < 0) { + #ifdef PID_CONDITIONAL_INTEGRATION if (t_error < 0) heaters_runtime[h].heater_i -= t_error; // un-integrate + #endif pid_output = 0; } else