Skip to content

Commit

Permalink
Merge pull request #3 from fwestenberg/main
Browse files Browse the repository at this point in the history
Support new ESPHome version, restore temp. settings.
  • Loading branch information
rsciriano authored Jul 6, 2021
2 parents f1bd6ee + ee41838 commit 41cc0f0
Show file tree
Hide file tree
Showing 7 changed files with 97 additions and 83 deletions.
10 changes: 8 additions & 2 deletions Readme.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
# ESPHome OpenTherm

This is an example of a integration with a OpenTherm boiler using [ESPHome](https://esphome.io/) and [OpenTherm Adapter](http://ihormelnyk.com/opentherm_adapter)
This is an example of a integration with a OpenTherm boiler using [ESPHome](https://esphome.io/) and the [Ihor Melnyk](http://ihormelnyk.com/opentherm_adapter) or [DIYLESS](https://diyless.com/product/esp8266-thermostat-shield) OpenTherm Adapter

More details coming soon... 8-)
## Installation
- Copy the content of this repository to your ESPHome folder
- Make sure the pin numbers are right, check the file opentherm_component.h in the esphome-opentherm folder.
- Edit the opentherm.yaml file:
- Make sure the board and device settings are correct for your device
- Set the sensor entity_id with the external temperature sensor's name from Home Assistant. (The ESPHome sensor name is temperature_sensor).
- Flash the ESP and configure in Home Assistant. It should be auto-discovered by the ESPHome Integration.
File renamed without changes.
53 changes: 32 additions & 21 deletions opentherm_climate.h → esphome-opentherm/opentherm_climate.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,37 +2,49 @@
#include "esphome.h"


class OpenthermClimate : public Climate {
class OpenthermClimate : public Climate, public Component {
private:
const char *TAG = "opentherm_climate";
bool supports_auto_mode_ = false;
bool supports_heat_cool_mode_ = false;
bool supports_two_point_target_temperature_ = false;
float minimum_temperature_ = 0;
float maximum_temperature_ = 0;
float default_target_ = 0;
public:

void set_supports_auto_mode(bool value)
{
supports_auto_mode_ = value;
}
bool get_supports_auto_mode()
{
return supports_auto_mode_;
void set_supports_heat_cool_mode(bool value) { supports_heat_cool_mode_ = value; }
bool get_supports_heat_cool_mode() { return supports_heat_cool_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_; }
void set_temperature_settings(float min = 0, float max = 0, float target = 0) {
minimum_temperature_ = min;
maximum_temperature_ = max,
default_target_ = target;
}

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_;
void setup() override {
// restore setpoints
auto restore = this->restore_state_();
if (restore.has_value()) {
restore->apply(this);
} else {
// restore from defaults
this->mode = climate::CLIMATE_MODE_OFF;
// initialize target temperature to some value so that it's not NAN
this->target_temperature = default_target_;

if (supports_two_point_target_temperature_){
this->target_temperature_low = minimum_temperature_;
this->target_temperature_high = maximum_temperature_;
}
}
}


climate::ClimateTraits traits() override {

auto traits = climate::ClimateTraits();
traits.set_supports_current_temperature(true);
traits.set_supports_auto_mode(supports_auto_mode_);
// traits.set_supports_heat_cool_mode(supports_heat_cool_mode_);
traits.set_supports_heat_cool_mode(false);
traits.set_supports_cool_mode(false);
traits.set_supports_heat_mode(true);
traits.set_supports_two_point_target_temperature(supports_two_point_target_temperature_);
Expand Down Expand Up @@ -91,5 +103,4 @@ class OpenthermClimate : public Climate {
}

}
};

};
57 changes: 28 additions & 29 deletions opentherm_component.h → esphome-opentherm/opentherm_component.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,9 @@
#include "opentherm_binary.h"
#include "opentherm_output.h"


// Pins to OpenTherm Adapter
const int inPin = D5;
const int outPin = D6;

int inPin = D2;
int outPin = D1;
OpenTherm ot(inPin, outPin, false);

ICACHE_RAM_ATTR void handleInterrupt() {
Expand All @@ -20,22 +18,21 @@ ICACHE_RAM_ATTR void handleInterrupt() {
class OpenthermComponent: public PollingComponent {
private:
const char *TAG = "opentherm_component";
OpenthermFloatOutput *pid_output_;
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();
Sensor *heating_target_temperature_sensor = new Sensor();
OpenthermClimate *hotWaterClimate = 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(15000) {

OpenthermComponent(): PollingComponent(3000) {
}

void set_pid_output(OpenthermFloatOutput *pid_output) { pid_output_ = pid_output; }
Expand All @@ -53,8 +50,13 @@ class OpenthermComponent: public PollingComponent {
});

// Adjust HeatingWaterClimate depending on PID
heatingWaterClimate->set_supports_auto_mode(this->pid_output_ != nullptr);
// heatingWaterClimate->set_supports_heat_cool_mode(this->pid_output_ != nullptr);
heatingWaterClimate->set_supports_two_point_target_temperature(this->pid_output_ != nullptr);

hotWaterClimate->set_temperature_settings(5, 6, 0);
heatingWaterClimate->set_temperature_settings(0, 0, 30);
hotWaterClimate->setup();
heatingWaterClimate->setup();
}
float getExternalTemperature() {
unsigned long response = ot.sendRequest(ot.buildRequest(OpenThermRequestType::READ, OpenThermMessageID::Toutside, 0));
Expand Down Expand Up @@ -90,7 +92,8 @@ class OpenthermComponent: public PollingComponent {

void update() override {

ESP_LOGD("opentherm_component", "update");
ESP_LOGD("opentherm_component", "update heatingWaterClimate: %i", heatingWaterClimate->mode);
ESP_LOGD("opentherm_component", "update hotWaterClimate: %i", hotWaterClimate->mode);

bool enableCentralHeating = heatingWaterClimate->mode == ClimateMode::CLIMATE_MODE_HEAT;
bool enableHotWater = hotWaterClimate->mode == ClimateMode::CLIMATE_MODE_HEAT;
Expand All @@ -107,60 +110,56 @@ class OpenthermComponent: public PollingComponent {


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

ot.setBoilerTemperature(heating_target_temperature);

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

// Read sensor values
/*
float boilerTemperature = ot.getBoilerTemperature();
float ext_temperature = getExternalTemperature();
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);

heating_target_temperature_sensor->publish_state(heating_target_temperature);

// Publish status of thermostat that controls hot water
hotWaterClimate->current_temperature = hotWater_temperature;
hotWaterClimate->action = isHotWaterActive ? ClimateAction::CLIMATE_ACTION_HEATING : ClimateAction::CLIMATE_ACTION_OFF;
hotWaterClimate->publish_state();

// Publish status of thermostat that controls heating
heatingWaterClimate->current_temperature = return_temperature;
heatingWaterClimate->current_temperature = boilerTemperature;
heatingWaterClimate->action = isCentralHeatingActive && isFlameOn ? ClimateAction::CLIMATE_ACTION_HEATING : ClimateAction::CLIMATE_ACTION_OFF;
heatingWaterClimate->publish_state();

}

};
};
File renamed without changes.
File renamed without changes.
60 changes: 29 additions & 31 deletions opentherm.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -5,31 +5,25 @@ substitutions:
esphome:
name: $devicename
platform: ESP8266
board: d1_mini_lite
board: d1_mini
arduino_version: '2.7.2'
platformio_options:
lib_deps:
- ihormelnyk/OpenTherm Library @ 1.1.0
- ihormelnyk/OpenTherm Library @ 1.1.3
- ESP Async WebServer

includes:
- opentherm_component.h
- opentherm_climate.h
- opentherm_switch.h
- opentherm_binary.h
- opentherm_output.h
- esphome-opentherm/

wifi:
ssid: !secret wifi_name
ssid: !secret wifi_ssid
password: !secret wifi_password

# Enable logging
logger:
baud_rate: 74880
#level: DEBUG
ap:
ssid: "${devicename} Fallback"
password: !secret esphome_fallback_password

captive_portal:
logger:
api:

ota:

custom_component:
Expand All @@ -39,13 +33,11 @@ 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);
Expand All @@ -65,30 +57,33 @@ sensor:
openthermComp->return_temperature_sensor,
openthermComp->pressure_sensor,
openthermComp->modulation_sensor,
openthermComp->heatting_target_temperature_sensor
openthermComp->heating_target_temperature_sensor
};
sensors:
- name: "Boiler Temperature"
- name: Boiler Temperature
unit_of_measurement: °C
accuracy_decimals: 2
accuracy_decimals: 1
- name: "External Temperature"
unit_of_measurement: °C
accuracy_decimals: 0
- name: "Return Temperature"
unit_of_measurement: °C
accuracy_decimals: 2
accuracy_decimals: 1
- name: "Heating Water Pressure"
unit_of_measurement: hPa
accuracy_decimals: 2
accuracy_decimals: 1
- name: "Boiler Modulation"
unit_of_measurement: "%"
accuracy_decimals: 0
- name: "Heating Target Temperature"
unit_of_measurement: ºC
accuracy_decimals: 2
accuracy_decimals: 1

- platform: homeassistant
id: temperature_sensor
entity_id: sensor.temperature_sensor
name: "Actual temperature"
unit_of_measurement: °C
- platform: pid
name: "PID Climate Result"
type: RESULT
Expand All @@ -104,7 +99,6 @@ binary_sensor:
lambda: |-
OpenthermComponent *openthermComp = (OpenthermComponent*) opentherm;
return {openthermComp->flame};
binary_sensors:
- name: "Flame"
#device_class: heat
Expand All @@ -114,9 +108,8 @@ switch:
lambda: |-
OpenthermComponent *openthermComp = (OpenthermComponent*) opentherm;
return {openthermComp->thermostatSwitch};
switches:
name: "Termostato ambiente"
name: "Disable PID"
- platform: template
name: "PID Climate Autotune"
turn_on_action:
Expand All @@ -130,17 +123,22 @@ climate:
openthermComp->hotWaterClimate,
openthermComp->heatingWaterClimate
};
climates:
- name: "Hot water"
- name: "Heating water"
- id: hot_water
name: "Hot water"
- id: heating_water
name: "Heating water"
- platform: pid
id: pid_climate
name: "PID Climate Controller"
visual:
min_temperature: 16 °C
max_temperature: 28 °C
temperature_step: 0.5 °C
sensor: temperature_sensor
default_target_temperature: 21°C
default_target_temperature: 20°C
heat_output: pid_output
control_parameters:
kp: 0.38197
ki: 0.01012
kd: 3.60387
kd: 3.60387

0 comments on commit 41cc0f0

Please sign in to comment.