From 69026f759958b6203fd021e255d42ba7664e2730 Mon Sep 17 00:00:00 2001 From: Mathias Pihl Date: Wed, 13 Dec 2023 00:50:55 +0100 Subject: [PATCH] Remove setpoint-change from error when calculating derivative in pid controller (#4737) Co-authored-by: Mathias Pihl --- esphome/components/pid/pid_controller.cpp | 11 ++++++++--- esphome/components/pid/pid_controller.h | 3 ++- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/esphome/components/pid/pid_controller.cpp b/esphome/components/pid/pid_controller.cpp index 30f6038325..1a16f14542 100644 --- a/esphome/components/pid/pid_controller.cpp +++ b/esphome/components/pid/pid_controller.cpp @@ -16,7 +16,7 @@ float PIDController::update(float setpoint, float process_value) { calculate_proportional_term_(); calculate_integral_term_(); - calculate_derivative_term_(); + calculate_derivative_term_(setpoint); // u(t) := p(t) + i(t) + d(t) float output = proportional_term_ + integral_term_ + derivative_term_; @@ -69,13 +69,18 @@ void PIDController::calculate_integral_term_() { integral_term_ = accumulated_integral_; } -void PIDController::calculate_derivative_term_() { +void PIDController::calculate_derivative_term_(float setpoint) { // derivative_term_ // d(t) := K_d * de(t)/dt float derivative = 0.0f; - if (dt_ != 0.0f) + if (dt_ != 0.0f) { + // remove changes to setpoint from error + if (!std::isnan(previous_setpoint_) && previous_setpoint_ != setpoint) + previous_error_ -= previous_setpoint_ - setpoint; derivative = (error_ - previous_error_) / dt_; + } previous_error_ = error_; + previous_setpoint_ = setpoint; // smooth the derivative samples derivative = weighted_average_(derivative_list_, derivative, derivative_samples_); diff --git a/esphome/components/pid/pid_controller.h b/esphome/components/pid/pid_controller.h index 05ce5f9224..e2a7030b57 100644 --- a/esphome/components/pid/pid_controller.h +++ b/esphome/components/pid/pid_controller.h @@ -49,12 +49,13 @@ struct PIDController { void calculate_proportional_term_(); void calculate_integral_term_(); - void calculate_derivative_term_(); + void calculate_derivative_term_(float setpoint); float weighted_average_(std::deque &list, float new_value, int samples); float calculate_relative_time_(); /// Error from previous update used for derivative term float previous_error_ = 0; + float previous_setpoint_ = NAN; /// Accumulated integral value float accumulated_integral_ = 0; uint32_t last_time_ = 0;