mirror of
https://github.com/esphome/esphome.git
synced 2025-03-25 03:58:23 +00:00
* PID Climate * Add sensor for debugging PID output value * Add dump_config, use percent * Add more observable values * Update * Set target temperature * Add autotuner * Add algorithm explanation * Add autotuner action, update controller * Add simulator * Format * Change defaults * Updates
80 lines
2.0 KiB
C++
80 lines
2.0 KiB
C++
#pragma once
|
|
|
|
#include "esphome/core/esphal.h"
|
|
|
|
namespace esphome {
|
|
namespace pid {
|
|
|
|
struct PIDController {
|
|
float update(float setpoint, float process_value) {
|
|
// e(t) ... error at timestamp t
|
|
// r(t) ... setpoint
|
|
// y(t) ... process value (sensor reading)
|
|
// u(t) ... output value
|
|
|
|
float dt = calculate_relative_time_();
|
|
|
|
// e(t) := r(t) - y(t)
|
|
error = setpoint - process_value;
|
|
|
|
// p(t) := K_p * e(t)
|
|
proportional_term = kp * error;
|
|
|
|
// i(t) := K_i * \int_{0}^{t} e(t) dt
|
|
accumulated_integral_ += error * dt * ki;
|
|
// constrain accumulated integral value
|
|
if (!isnan(min_integral) && accumulated_integral_ < min_integral)
|
|
accumulated_integral_ = min_integral;
|
|
if (!isnan(max_integral) && accumulated_integral_ > max_integral)
|
|
accumulated_integral_ = max_integral;
|
|
integral_term = accumulated_integral_;
|
|
|
|
// d(t) := K_d * de(t)/dt
|
|
float derivative = 0.0f;
|
|
if (dt != 0.0f)
|
|
derivative = (error - previous_error_) / dt;
|
|
previous_error_ = error;
|
|
derivative_term = kd * derivative;
|
|
|
|
// u(t) := p(t) + i(t) + d(t)
|
|
return proportional_term + integral_term + derivative_term;
|
|
}
|
|
|
|
/// Proportional gain K_p.
|
|
float kp = 0;
|
|
/// Integral gain K_i.
|
|
float ki = 0;
|
|
/// Differential gain K_d.
|
|
float kd = 0;
|
|
|
|
float min_integral = NAN;
|
|
float max_integral = NAN;
|
|
|
|
// Store computed values in struct so that values can be monitored through sensors
|
|
float error;
|
|
float proportional_term;
|
|
float integral_term;
|
|
float derivative_term;
|
|
|
|
protected:
|
|
float calculate_relative_time_() {
|
|
uint32_t now = millis();
|
|
uint32_t dt = now - this->last_time_;
|
|
if (last_time_ == 0) {
|
|
last_time_ = now;
|
|
return 0.0f;
|
|
}
|
|
last_time_ = now;
|
|
return dt / 1000.0f;
|
|
}
|
|
|
|
/// Error from previous update used for derivative term
|
|
float previous_error_ = 0;
|
|
/// Accumulated integral value
|
|
float accumulated_integral_ = 0;
|
|
uint32_t last_time_ = 0;
|
|
};
|
|
|
|
} // namespace pid
|
|
} // namespace esphome
|