PID Climate (#885)

* 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
This commit is contained in:
Otto Winter
2020-01-04 12:43:11 +01:00
committed by GitHub
parent 05f9dede70
commit a6d31f05ee
11 changed files with 1064 additions and 0 deletions
+36
View File
@@ -0,0 +1,36 @@
import esphome.codegen as cg
import esphome.config_validation as cv
from esphome.components import sensor
from esphome.const import CONF_ID, UNIT_PERCENT, ICON_GAUGE, CONF_TYPE
from ..climate import pid_ns, PIDClimate
PIDClimateSensor = pid_ns.class_('PIDClimateSensor', sensor.Sensor, cg.Component)
PIDClimateSensorType = pid_ns.enum('PIDClimateSensorType')
PID_CLIMATE_SENSOR_TYPES = {
'RESULT': PIDClimateSensorType.PID_SENSOR_TYPE_RESULT,
'ERROR': PIDClimateSensorType.PID_SENSOR_TYPE_ERROR,
'PROPORTIONAL': PIDClimateSensorType.PID_SENSOR_TYPE_PROPORTIONAL,
'INTEGRAL': PIDClimateSensorType.PID_SENSOR_TYPE_INTEGRAL,
'DERIVATIVE': PIDClimateSensorType.PID_SENSOR_TYPE_DERIVATIVE,
'HEAT': PIDClimateSensorType.PID_SENSOR_TYPE_HEAT,
'COOL': PIDClimateSensorType.PID_SENSOR_TYPE_COOL,
}
CONF_CLIMATE_ID = 'climate_id'
CONFIG_SCHEMA = sensor.sensor_schema(UNIT_PERCENT, ICON_GAUGE, 1).extend({
cv.GenerateID(): cv.declare_id(PIDClimateSensor),
cv.GenerateID(CONF_CLIMATE_ID): cv.use_id(PIDClimate),
cv.Required(CONF_TYPE): cv.enum(PID_CLIMATE_SENSOR_TYPES, upper=True),
}).extend(cv.COMPONENT_SCHEMA)
def to_code(config):
parent = yield cg.get_variable(config[CONF_CLIMATE_ID])
var = cg.new_Pvariable(config[CONF_ID])
yield sensor.register_sensor(var, config)
yield cg.register_component(var, config)
cg.add(var.set_parent(parent))
cg.add(var.set_type(config[CONF_TYPE]))
@@ -0,0 +1,47 @@
#include "pid_climate_sensor.h"
#include "esphome/core/log.h"
#include "esphome/core/helpers.h"
namespace esphome {
namespace pid {
static const char *TAG = "pid.sensor";
void PIDClimateSensor::setup() {
this->parent_->add_on_pid_computed_callback([this]() { this->update_from_parent_(); });
this->update_from_parent_();
}
void PIDClimateSensor::update_from_parent_() {
float value;
switch (this->type_) {
case PID_SENSOR_TYPE_RESULT:
value = this->parent_->get_output_value();
break;
case PID_SENSOR_TYPE_ERROR:
value = this->parent_->get_error_value();
break;
case PID_SENSOR_TYPE_PROPORTIONAL:
value = this->parent_->get_proportional_term();
break;
case PID_SENSOR_TYPE_INTEGRAL:
value = this->parent_->get_integral_term();
break;
case PID_SENSOR_TYPE_DERIVATIVE:
value = this->parent_->get_derivative_term();
break;
case PID_SENSOR_TYPE_HEAT:
value = clamp(this->parent_->get_output_value(), 0.0f, 1.0f);
break;
case PID_SENSOR_TYPE_COOL:
value = clamp(-this->parent_->get_output_value(), 0.0f, 1.0f);
break;
default:
value = NAN;
break;
}
this->publish_state(value * 100.0f);
}
void PIDClimateSensor::dump_config() { LOG_SENSOR("", "PID Climate Sensor", this); }
} // namespace pid
} // namespace esphome
@@ -0,0 +1,34 @@
#pragma once
#include "esphome/core/component.h"
#include "esphome/components/pid/pid_climate.h"
namespace esphome {
namespace pid {
enum PIDClimateSensorType {
PID_SENSOR_TYPE_RESULT,
PID_SENSOR_TYPE_ERROR,
PID_SENSOR_TYPE_PROPORTIONAL,
PID_SENSOR_TYPE_INTEGRAL,
PID_SENSOR_TYPE_DERIVATIVE,
PID_SENSOR_TYPE_HEAT,
PID_SENSOR_TYPE_COOL,
};
class PIDClimateSensor : public sensor::Sensor, public Component {
public:
void setup() override;
void set_parent(PIDClimate *parent) { parent_ = parent; }
void set_type(PIDClimateSensorType type) { type_ = type; }
void dump_config() override;
protected:
void update_from_parent_();
PIDClimate *parent_;
PIDClimateSensorType type_;
};
} // namespace pid
} // namespace esphome