Skip to content

Commit

Permalink
Integration with PID Climate
Browse files Browse the repository at this point in the history
  • Loading branch information
rsciriano committed Mar 28, 2021
1 parent 8bb3d8d commit f1bd6ee
Show file tree
Hide file tree
Showing 4 changed files with 150 additions and 15 deletions.
49 changes: 47 additions & 2 deletions opentherm.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ esphome:
- opentherm_climate.h
- opentherm_switch.h
- opentherm_binary.h
- opentherm_output.h

wifi:
ssid: !secret wifi_name
Expand All @@ -39,6 +40,21 @@ custom_component:
components:
- id: opentherm
output:
- platform: custom
type: float
lambda: |-
OpenthermComponent *openthermComp = (OpenthermComponent*) opentherm;
auto opentherm_pid_output = new OpenthermFloatOutput();
openthermComp->set_pid_output(opentherm_pid_output);
App.register_component(opentherm_pid_output);
return {opentherm_pid_output};
outputs:
id: pid_output
#min_power: 30.00%
#max_power: 60.00%

sensor:
- platform: custom
lambda: |-
Expand All @@ -48,7 +64,8 @@ sensor:
openthermComp->external_temperature_sensor,
openthermComp->return_temperature_sensor,
openthermComp->pressure_sensor,
openthermComp->modulation_sensor
openthermComp->modulation_sensor,
openthermComp->heatting_target_temperature_sensor
};
sensors:
- name: "Boiler Temperature"
Expand All @@ -66,6 +83,21 @@ sensor:
- name: "Boiler Modulation"
unit_of_measurement: "%"
accuracy_decimals: 0
- name: "Heating Target Temperature"
unit_of_measurement: ºC
accuracy_decimals: 2
- platform: homeassistant
id: temperature_sensor
entity_id: sensor.temperature_sensor
- platform: pid
name: "PID Climate Result"
type: RESULT
- platform: pid
name: "PID Climate HEAT"
type: HEAT
- platform: pid
name: "PID Climate ERROR"
type: ERROR

binary_sensor:
- platform: custom
Expand All @@ -85,6 +117,10 @@ switch:
switches:
name: "Termostato ambiente"
- platform: template
name: "PID Climate Autotune"
turn_on_action:
- climate.pid.autotune: pid_climate

climate:
- platform: custom
Expand All @@ -98,4 +134,13 @@ climate:
climates:
- name: "Hot water"
- name: "Heating water"

- platform: pid
id: pid_climate
name: "PID Climate Controller"
sensor: temperature_sensor
default_target_temperature: 21°C
heat_output: pid_output
control_parameters:
kp: 0.38197
ki: 0.01012
kd: 3.60387
45 changes: 43 additions & 2 deletions opentherm_climate.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,37 @@
class OpenthermClimate : public Climate {
private:
const char *TAG = "opentherm_climate";
bool supports_auto_mode_ = false;
bool supports_two_point_target_temperature_ = false;
public:

void set_supports_auto_mode(bool value)
{
supports_auto_mode_ = value;
}
bool get_supports_auto_mode()
{
return supports_auto_mode_;
}

void set_supports_two_point_target_temperature(bool value)
{
supports_two_point_target_temperature_ = value;
}
bool get_supports_two_point_target_temperature()
{
return supports_two_point_target_temperature_;
}


climate::ClimateTraits traits() override {

auto traits = climate::ClimateTraits();
traits.set_supports_current_temperature(true);
traits.set_supports_auto_mode(false);
traits.set_supports_auto_mode(supports_auto_mode_);
traits.set_supports_cool_mode(false);
traits.set_supports_heat_mode(true);
traits.set_supports_two_point_target_temperature(false);
traits.set_supports_two_point_target_temperature(supports_two_point_target_temperature_);
traits.set_supports_away(false);
traits.set_supports_action(true);

Expand Down Expand Up @@ -48,6 +69,26 @@ class OpenthermClimate : public Climate {
this->target_temperature = temp;
this->publish_state();
}
if (call.get_target_temperature_low().has_value()) {
// User requested target temperature change
float temp = *call.get_target_temperature_low();
// Send target temp to climate
// ...
ESP_LOGD(TAG, "get_target_temperature_low");

this->target_temperature_low = temp;
this->publish_state();
}
if (call.get_target_temperature_high().has_value()) {
// User requested target temperature change
float temp = *call.get_target_temperature_high();
// Send target temp to climate
// ...
ESP_LOGD(TAG, "get_target_temperature_high");

this->target_temperature_high = temp;
this->publish_state();
}

}
};
Expand Down
50 changes: 39 additions & 11 deletions opentherm_component.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
#include "opentherm_switch.h"
#include "opentherm_climate.h"
#include "opentherm_binary.h"
#include "opentherm_output.h"


// Pins to OpenTherm Adapter
Expand All @@ -19,22 +20,27 @@ ICACHE_RAM_ATTR void handleInterrupt() {
class OpenthermComponent: public PollingComponent {
private:
const char *TAG = "opentherm_component";
OpenthermFloatOutput *pid_output_;
public:
Switch *thermostatSwitch = new OpenthermSwitch();
Sensor *external_temperature_sensor = new Sensor();
Sensor *return_temperature_sensor = new Sensor();
Sensor *boiler_temperature = new Sensor();
Sensor *pressure_sensor = new Sensor();
Sensor *modulation_sensor = new Sensor();
Sensor *heatting_target_temperature_sensor = new Sensor();
Climate *hotWaterClimate = new OpenthermClimate();
Climate *heatingWaterClimate = new OpenthermClimate();
OpenthermClimate *heatingWaterClimate = new OpenthermClimate();
BinarySensor *flame = new OpenthermBinarySensor();

// Set 3 sec. to give time to read all sensors (and not appear in HA as not available)
OpenthermComponent(): PollingComponent(3000) {
OpenthermComponent(): PollingComponent(15000) {

}

void set_pid_output(OpenthermFloatOutput *pid_output) { pid_output_ = pid_output; }


void setup() override {
// This will be called once to set up the component
// think of it as the setup() call in Arduino
Expand All @@ -45,6 +51,10 @@ class OpenthermComponent: public PollingComponent {
thermostatSwitch->add_on_state_callback([=](bool state) -> void {
ESP_LOGD ("opentherm_component", "termostatSwitch_on_state_callback %d", state);
});

// Adjust HeatingWaterClimate depending on PID
heatingWaterClimate->set_supports_auto_mode(this->pid_output_ != nullptr);
heatingWaterClimate->set_supports_two_point_target_temperature(this->pid_output_ != nullptr);
}
float getExternalTemperature() {
unsigned long response = ot.sendRequest(ot.buildRequest(OpenThermRequestType::READ, OpenThermMessageID::Toutside, 0));
Expand Down Expand Up @@ -92,36 +102,54 @@ class OpenthermComponent: public PollingComponent {
bool isFlameOn = ot.isFlameOn(response);
bool isCentralHeatingActive = ot.isCentralHeatingActive(response);
bool isHotWaterActive = ot.isHotWaterActive(response);
float return_temperature = getReturnTemperature();
float hotWater_temperature = getHotWaterTemperature();


// Set temperature depending on room thermostat
if (thermostatSwitch->state) {
ot.setBoilerTemperature(heatingWaterClimate->target_temperature);
ESP_LOGD("opentherm_component", "setBoilerTemperature at %f °C (from heating water climate)", heatingWaterClimate->target_temperature);
float heatting_target_temperature;
if (this->pid_output_ != nullptr) {
float pid_output = pid_output_->get_state();
if (pid_output == 0.0f) {
heatting_target_temperature = 10.0f;
}
else {
heatting_target_temperature = pid_output * (heatingWaterClimate->target_temperature_high - heatingWaterClimate->target_temperature_low)
+ heatingWaterClimate->target_temperature_low;
}
ESP_LOGD("opentherm_component", "setBoilerTemperature at %f °C (from PID Output)", heatting_target_temperature);
}
else if (thermostatSwitch->state) {
heatting_target_temperature = heatingWaterClimate->target_temperature;
ESP_LOGD("opentherm_component", "setBoilerTemperature at %f °C (from heating water climate)", heatting_target_temperature);
}
else {
// If the room thermostat is off, set it to 10, so that the pump continues to operate
ot.setBoilerTemperature(10.0);
ESP_LOGD("opentherm_component", "setBoilerTemperature at %f °C (default low value)", 10.0);
heatting_target_temperature = 10.0;
ESP_LOGD("opentherm_component", "setBoilerTemperature at %f °C (default low value)", heatting_target_temperature);
}
ot.setBoilerTemperature(heatting_target_temperature);


// Set hot water temperature
setHotWaterTemperature(hotWaterClimate->target_temperature);

// Read sensor values
// Read sensor values
/*
float boilerTemperature = ot.getBoilerTemperature();
float ext_temperature = getExternalTemperature();
float return_temperature = getReturnTemperature();
float hotWater_temperature = getHotWaterTemperature();
float pressure = getPressure();
float modulation = getModulation();
// Publish sensor values
flame->publish_state(isFlameOn);
//flame->publish_state(isFlameOn);
external_temperature_sensor->publish_state(ext_temperature);
return_temperature_sensor->publish_state(return_temperature);
boiler_temperature->publish_state(boilerTemperature);
pressure_sensor->publish_state(pressure);
modulation_sensor->publish_state(modulation);
*/
heatting_target_temperature_sensor->publish_state(heatting_target_temperature);

// Publish status of thermostat that controls hot water
hotWaterClimate->current_temperature = hotWater_temperature;
Expand Down
21 changes: 21 additions & 0 deletions opentherm_output.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
#pragma once

#include "esphome.h"
using namespace esphome;


class OpenthermFloatOutput : public Component, public FloatOutput {
public:
float get_state() const { return state_; }
void setup() override {
// This will be called by App.setup()
//pinMode(5, OUTPUT);
}

protected:
float state_{0.0f};
void write_state(float state) override { this->state_ = state; }

};


0 comments on commit f1bd6ee

Please sign in to comment.