Автоматическая система сброса теплой воды для фильтров обратного осмоса
Друзья, в одной из моих квартир недавно возникла проблема с температурой холодной воды, и с тех пор она не была решена. Возможно, в системе центрального водоснабжения моего дома горячая вода где-то подмешивается в трубу с холодной водой, и из-за этого из крана холодной воды поступает вода с температурой 36–39 градусов.
Такая повышенная температура из трубы холодной воды негативно сказывается на работе моей системы очистки воды методом обратного осмоса (ОС), а также на работу моего устройства ионизации воды, так как оно подключено после трех префильтров ОС. По паспорту, в систему ОС можно подавать воду до 38 градусов, а в устройство ионизации воды — до 30 градусов Цельсия. На практике рекомендуется использовать воду с температурой 4–30 °C для оптимальной работы системы ОС. Также температура воды в 25-35 °C может способствовать активному росту бактерий в накопительном баке системы обратного осмоса, но это решается установкой UV-фильтра.
После слива такой воды из крана в течение 5 минут вода становится около 27 градусов Цельсия. Было решено сделать автоматическую систему сброса теплой воды на базе ESP32 и Home Assistant.
Что вам понадобится
- Бокс для блока управления – 1 шт.
- Бокс для блока манифольда – 1 шт.
- Микроконтроллер ESP32 – 1 шт.
- Блок питания 220VAC / 5VDC, 10Вт – 1 шт.
- Блок питания 220VAC / 24VDC, 72Вт – 1 шт.
- Электрический шаровый кран (1/2” 24VDC Normally Opened) – 1 шт.
- Электрический шаровый кран (1/2” 24VDC Normally Closed) – 1 шт.
- Фитинги для шарового крана (1/4” Hose — 1/2” BSP) – 4 шт.
- Трубки 1/4”
- Расходомер, 5VDC – 1 шт.
- Цифровой температурный сенсор DS18B20 – 1 шт.
- Стальной патрубок 50 мм 1/4” BSP – 1 шт.
- Термоусадка для стального патрубка d18 мм — 50 мм
- Термоизоляция для стального патрубка внутр. диам. 16 мм — 50 мм
- Фиттинг для стального патрубка (1/4” Hose — 1/4” BSP Female) – 2 шт.
- Угловой фиттинг (1/4” quick jack) – 6 шт.
- Т-фиттинг (1/4” quick jack) – 2 шт.
- Соединительный фиттинг (1/4” quick jack) – 3 шт.
- Коннектор GX12 2P под корпус (вилка + розетка) – 8 шт.
- Коннектор GX12 2P для провода (вилка + розетка) – 1 шт.
- Коннектор GX12 3P под корпус (вилка + розетка) – 4 шт.
- Резистор 4.7 кОм, 1/4 Вт – 1 шт.
- Реле SRD-05VDC-SL-C – 3 шт.
- Диод 1N4001 – 3 шт.
- Транзистор 2N3904 – 3 шт.
- Резистор 1 кОм, 1/4 Вт – 3 шт.
- Красный LED 5VDC – 2 шт.
- Синий LED 5VDC – 1 шт.
- Резистор 240 Ом, 1/4 Вт – 3 шт.
- Красный LED 24VDC – 1 шт.
- Синий LED 24VDC – 2 шт.
- Резистор 2.4 кОм, 1/4 Вт – 3 шт.
Шаг 1 : Изготавливаем температурный датчик

Температурный сенсор DS18B20
Возьмите температурный сенсор и припаяйте к нему трехжильный сигнальный провод. Не забудьте про маркировку контактов, чтобы знать, где Data, Ground и VDC. Закрепите сенсор на металлическом патрубке с помощью термоусадки. Сам патрубок соедините с двумя фитингами 1/4BSP – 1/4 Hose. Затем поместите патрубок в термоизоляцию.

Температурный сенсор прикрепленный к патрубку 1/4 BSP с помощью термоусадки
А вот и готовые термодатчики (дополнительный термодатчик я сделал для другого проекта):

Термодатчики
Шаг 2 : Собираем блок манифольда

Блок манифольда
Боксы для электрических шаровых кранов у всех будут свои, поэтому количество соединительных фитингов будет разным. В моем случае я купил контейнер для хранения с крышкой, просверлил в нем три отверстия под трубки 1/4”, а также четыре отверстия для вилки разъема GX12 на корпус. В этот бокс я поместил температурный датчик, два электрических шаровых крана, расходомер и соединил все фитингами для систем обратного осмоса. Провода электрических шаровых кранов, термодатчика и расходомера припаял к соответствующим выходам вилок разъемов GX12.
Шаг 3 : Пайка блока управления

Блок управления
Здесь также все предельно просто. В боксе просверлите соответствующие отверстия под GX12, светодиоды и кабель питания 220VAC. Соберите компоненты согласно схеме. Полноразмерную схему скачайте отсюда.

Задняя сторона блока управления
Шаг 4 : Заливаем программу в ESP32
Подсоедините ESP32 к ноутбуку, откройте Arduino IDE и загрузите следующий скетч:
#include <WiFi.h> extern "C" { #include "freertos/FreeRTOS.h" #include "freertos/timers.h" } #include <AsyncMqttClient.h> #include <OneWire.h> #include <DallasTemperature.h> #define WIFI_SSID "Your_WiFi_SSID" #define WIFI_PASSWORD "Your_WiFi_Password" IPAddress staticIP(192, 168, 0, XXX); IPAddress gateway(192, 168, 0, 1); IPAddress subnet(255, 255, 255, 0); IPAddress dns(192, 168, 0, 1); // Home Assistant Mosquitto MQTT Broker #define MQTT_HOST IPAddress(192, 168, 0, XXX) #define MQTT_PORT 1883 #define MQTT_USER "Your_MQTT_Username" #define MQTT_PASSWORD "Your_MQTT_Password" // MQTT Topics #define MQTT_TOPIC_WATER_TEMPERATURE "homeassistant/ro_system/water_temperature" #define MQTT_TOPIC_RO_SOLENOID "homeassistant/ro_system/ro_solenoid" #define MQTT_TOPIC_DRAINAGE_SOLENOID "homeassistant/ro_system/drainage_solenoid" #define MQTT_TOPIC_RO_PUMP "homeassistant/ro_system/ro_pump" #define MQTT_TOPIC_DUMPED_WATER_INTERVAL_VOLUME "homeassistant/ro_system/dumped_water_interval_volume" #define MQTT_TOPIC_SYSTEM_STATE "homeassistant/ro_system/system_state" #define MQTT_TOPIC_DUMP_TIME "homeassistant/ro_system/dump_time" #define MQTT_TOPIC_DUMP_TEMP_THRESHOLD "homeassistant/ro_system/dump_temp_threshold" // GPIO pins for solenoids #define RO_SOLENOID_PIN 26 #define DRAINAGE_SOLENOID_PIN 25 // GPIO where the DS18B20 is connected to #define ONE_WIRE_BUS 27 // GPIO where Hall Sensor is connected to #define FLOW_METER_PIN 33 volatile int pulseCount = 0; // Count of Hall Sensor pulses // GPIO LEDS #define RO_BLUE_LED 15 #define DRAINAGE_RED_LED 2 #define DUMP_TIMEOUT_RED_LED 4 // GPIO for RO PUMP #define RO_PUMP_PIN 18 // Setup a oneWire instance to communicate with any OneWire devices OneWire oneWire(ONE_WIRE_BUS); // Pass our oneWire reference to Dallas Temperature sensor DallasTemperature sensors(&oneWire); // Temperature value float water_temperature; bool ro_solenoid_status = true; // true for opened, false for closed. RO solenoid is normally opened. bool drainage_solenoid_status = false; // true for opened, false for closed. Drainage solenoid is normally closed. bool ro_pump_status = true; // true for ON, false for OFF bool ro_pump_delayed_start = false; // false for no delayed start initiated bool system_error_state = false; // false for no errors AsyncMqttClient mqttClient; TimerHandle_t mqttReconnectTimer; TimerHandle_t wifiReconnectTimer; unsigned long previous_millis = 0; // Stores last time temperature was published unsigned long previous_millis_r = 0; // Stores last time RO solenoid was opened unsigned long previous_millis_d = 0; // Stores last time Drainage solenoid was opened const long interval = 10000; // 10 seconds interval at which to publish sensor readings long dump_time = 600000; // Initial dump time set for 10 minutes float dump_temp_threshold = 29; // Initial dump temp threshold String solenoid_open_name = "Открыто"; String solenoid_closed_name = "Закрыто"; String status_ro_water_supply_name = "Подача воды в обратный осмос"; String status_water_dump_timeout_name = "Превышение времени сброса"; String status_water_dump_in_progress_name = "Сброс тёплой воды"; int status_ro_pump_on = 1, status_ro_pump_off = 0, is_mqtt3 = 0; String deviceName = "ESP32RO"; void connectToWifi() { Serial.println("Connecting to Wi-Fi..."); WiFi.mode(WIFI_STA); WiFi.hostname(deviceName); WiFi.config(staticIP, gateway, subnet); WiFi.begin(WIFI_SSID, WIFI_PASSWORD); } void connectToMqtt() { Serial.println("Connecting to MQTT..."); mqttClient.connect(); } void WiFiEvent(WiFiEvent_t event) { Serial.printf("[WiFi-event] event: %dn", event); switch(event) { case SYSTEM_EVENT_STA_GOT_IP: Serial.println("WiFi connected"); Serial.println("IP address: "); Serial.println(WiFi.localIP()); connectToMqtt(); break; case SYSTEM_EVENT_STA_DISCONNECTED: Serial.println("WiFi lost connection"); xTimerStop(mqttReconnectTimer, 0); // ensure we don't reconnect to MQTT while reconnecting to Wi-Fi xTimerStart(wifiReconnectTimer, 0); break; } } void onMqttConnect(bool sessionPresent) { Serial.println("Connected to MQTT."); Serial.print("Session present: "); Serial.println(sessionPresent); uint16_t packetIdSub = mqttClient.subscribe(MQTT_TOPIC_DUMP_TIME, 2); Serial.print("Subscribing at QoS 2, packetId: "); Serial.println(packetIdSub); uint16_t packetIdSub1 = mqttClient.subscribe(MQTT_TOPIC_DUMP_TEMP_THRESHOLD, 2); Serial.print("Subscribing at QoS 2, packetId: "); Serial.println(packetIdSub1); uint16_t packetIdSub2 = mqttClient.subscribe(MQTT_TOPIC_RO_PUMP, 2); Serial.print("Subscribing at QoS 2, packetId: "); Serial.println(packetIdSub2); } void onMqttDisconnect(AsyncMqttClientDisconnectReason reason) { Serial.println("Disconnected from MQTT."); if (WiFi.isConnected()) { xTimerStart(mqttReconnectTimer, 0); } } void onMqttSubscribe(uint16_t packetId, uint8_t qos) { Serial.println("Subscribe acknowledged."); Serial.print(" packetId: "); Serial.println(packetId); Serial.print(" qos: "); Serial.println(qos); } void onMqttUnsubscribe(uint16_t packetId) { Serial.println("Unsubscribe acknowledged."); Serial.print(" packetId: "); Serial.println(packetId); } void onMqttMessage(char* topic, char* payload, AsyncMqttClientMessageProperties properties, size_t len, size_t index, size_t total) { if (String(topic) == "homeassistant/ro_system/dump_time") { String message1 = ""; for (size_t i = 0; i < len; i++) { message1 += (char)payload[i]; } dump_time = message1.toInt()*60000; } if (String(topic) == "homeassistant/ro_system/dump_temp_threshold") { String message2 = ""; for (size_t i = 0; i < len; i++) { message2 += (char)payload[i]; } dump_temp_threshold = message2.toFloat(); } if (String(topic) == MQTT_TOPIC_RO_PUMP) { String message3 = ""; for (size_t i = 0; i < len; i++) { message3 += (char)payload[i]; } if (message3.toInt() == 0) ro_pump_status = false; else ro_pump_status = true; is_mqtt3 = 1; } } void onMqttPublish(uint16_t packetId) { Serial.println("Publish acknowledged."); Serial.print(" packetId: "); Serial.println(packetId); } void setup() { pinMode(FLOW_METER_PIN, INPUT_PULLUP); // Enable pull-up resistor attachInterrupt(digitalPinToInterrupt(FLOW_METER_PIN), pulseCounter, FALLING); // Assign pulseCounter to interrupt pinMode(RO_SOLENOID_PIN, OUTPUT); pinMode(DRAINAGE_SOLENOID_PIN, OUTPUT); pinMode(RO_BLUE_LED, OUTPUT); pinMode(DRAINAGE_RED_LED, OUTPUT); pinMode(DUMP_TIMEOUT_RED_LED, OUTPUT); pinMode(RO_PUMP_PIN, OUTPUT); digitalWrite(RO_SOLENOID_PIN, LOW); digitalWrite(DRAINAGE_SOLENOID_PIN, LOW); digitalWrite(RO_BLUE_LED, HIGH); digitalWrite(DRAINAGE_RED_LED, HIGH); digitalWrite(DUMP_TIMEOUT_RED_LED, LOW); digitalWrite(RO_PUMP_PIN, LOW); // Start the DS18B20 sensor sensors.begin(); Serial.begin(115200); Serial.println(); Serial.println(); mqttReconnectTimer = xTimerCreate("mqttTimer", pdMS_TO_TICKS(2000), pdFALSE, (void*)0, reinterpret_cast<TimerCallbackFunction_t>(connectToMqtt)); wifiReconnectTimer = xTimerCreate("wifiTimer", pdMS_TO_TICKS(2000), pdFALSE, (void*)0, reinterpret_cast<TimerCallbackFunction_t>(connectToWifi)); WiFi.onEvent(WiFiEvent); mqttClient.onConnect(onMqttConnect); mqttClient.onDisconnect(onMqttDisconnect); mqttClient.onSubscribe(onMqttSubscribe); mqttClient.onUnsubscribe(onMqttUnsubscribe); mqttClient.onMessage(onMqttMessage); mqttClient.onPublish(onMqttPublish); mqttClient.setServer(MQTT_HOST, MQTT_PORT); mqttClient.setCredentials(MQTT_USER, MQTT_PASSWORD); connectToWifi(); } void loop() { if (ro_pump_status == false && is_mqtt3 == 1) { digitalWrite(RO_PUMP_PIN, HIGH); is_mqtt3 = 0; } if (ro_pump_status == true && is_mqtt3 == 1) { digitalWrite(RO_PUMP_PIN, LOW); is_mqtt3 = 0; } // Get current millis() unsigned long current_millis = millis(); // Check if it's time to take a new data readings if (current_millis - previous_millis >= interval) { // Record the time of the reading previous_millis = current_millis; float intervalVolume = pulseCount * 0.1622168797; // Convert pulse count to millilitres pulseCount = 0; // Reset pulse count // Take a temperature reading sensors.requestTemperatures(); water_temperature = sensors.getTempCByIndex(0); Serial.print("Water temp: "); Serial.println(water_temperature); Serial.print("Interval volume: "); Serial.println(intervalVolume); // Publish volume of dumped water for the last 10 seconds to MQTT mqttClient.publish(MQTT_TOPIC_DUMPED_WATER_INTERVAL_VOLUME, 2, false, String(intervalVolume).c_str()); // Publish the temperature reading to MQTT mqttClient.publish(MQTT_TOPIC_WATER_TEMPERATURE, 2, false, String(water_temperature).c_str()); // Publish RO pump state to MQTT if (ro_pump_status == true) { mqttClient.publish(MQTT_TOPIC_RO_PUMP, 2, false, String(status_ro_pump_on).c_str()); } else { mqttClient.publish(MQTT_TOPIC_RO_PUMP, 2, false, String(status_ro_pump_off).c_str()); } // Publish system state to MQTT if (ro_solenoid_status == false && drainage_solenoid_status == true && system_error_state == false) { // Publish system state to MQTT. Water dump in progress mqttClient.publish(MQTT_TOPIC_SYSTEM_STATE, 2, false, status_water_dump_in_progress_name.c_str()); } else if (ro_solenoid_status == true && drainage_solenoid_status == false && system_error_state == false) { // Publish system state to MQTT. RO water supply mqttClient.publish(MQTT_TOPIC_SYSTEM_STATE, 2, false, status_ro_water_supply_name.c_str()); } else { // Publish system error state to MQTT mqttClient.publish(MQTT_TOPIC_SYSTEM_STATE, 2, false, status_water_dump_timeout_name.c_str()); } // Check if the temperature is above 29 degrees if (water_temperature > dump_temp_threshold && system_error_state == false) { // Close RO solenoid if (digitalRead(RO_SOLENOID_PIN) != HIGH) { // Switch off Blue RO LED digitalWrite(RO_BLUE_LED, LOW); // Close RO solenoid digitalWrite(RO_SOLENOID_PIN, HIGH); // Update the RO solenoid status ro_solenoid_status = false; // Publish RO solenoid status to MQTT mqttClient.publish(MQTT_TOPIC_RO_SOLENOID, 2, false, solenoid_closed_name.c_str()); } // Open Drainage solenoid if (digitalRead(DRAINAGE_SOLENOID_PIN) != HIGH) { previous_millis_d = current_millis; // Switch off Red Drainage LED digitalWrite(DRAINAGE_RED_LED, LOW); // Open Drainage solenoid digitalWrite(DRAINAGE_SOLENOID_PIN, HIGH); // Update the Drainage solenoid status drainage_solenoid_status = true; // Publish Drainage solenoid status to MQTT mqttClient.publish(MQTT_TOPIC_DRAINAGE_SOLENOID, 2, false, solenoid_open_name.c_str()); } // Switch OFF RO pump if (digitalRead(RO_PUMP_PIN) != HIGH) { // Switch OFF RO pump digitalWrite(RO_PUMP_PIN, HIGH); // Update the RO Pump status ro_pump_status = false; // Publish RO pump state to MQTT mqttClient.publish(MQTT_TOPIC_RO_PUMP, 2, false, String(status_ro_pump_off).c_str()); } } else if (water_temperature < (dump_temp_threshold - 2) && system_error_state == false) { // Open RO solenoid if (digitalRead(RO_SOLENOID_PIN) != LOW) { previous_millis_r = current_millis; // Open RO solenoid digitalWrite(RO_SOLENOID_PIN, LOW); // Switch on Blue RO LED digitalWrite(RO_BLUE_LED, HIGH); // Update the RO solenoid status ro_solenoid_status = true; // Update the RO Pump delayed start status ro_pump_delayed_start = true; // Publish RO solenoid status to MQTT mqttClient.publish(MQTT_TOPIC_RO_SOLENOID, 2, false, solenoid_open_name.c_str()); } // Close Drainage solenoid if (digitalRead(DRAINAGE_SOLENOID_PIN) != LOW) { // Close Drainage solenoid digitalWrite(DRAINAGE_SOLENOID_PIN, LOW); // Switch on Red Drainage LED digitalWrite(DRAINAGE_RED_LED, HIGH); // Update the Drainage solenoid status drainage_solenoid_status = false; // Publish Drainage solenoid status to MQTT mqttClient.publish(MQTT_TOPIC_DRAINAGE_SOLENOID, 2, false, solenoid_closed_name.c_str()); } } // End of ELSE IF // Delayed start of RO pump after 15 seconds if (ro_pump_delayed_start == true && system_error_state == false && current_millis - previous_millis_r >= 15000 ) { // Switch ON RO pump digitalWrite(RO_PUMP_PIN, LOW); // Update the RO Pump delayed start status ro_pump_delayed_start = false; // Update the RO Pump status ro_pump_status = true; // Publish RO pump state to MQTT mqttClient.publish(MQTT_TOPIC_RO_PUMP, 2, false, String(status_ro_pump_on).c_str()); } // Check if dump continues for more than XX minutes set in HA if (drainage_solenoid_status == true && system_error_state == false && current_millis - previous_millis_d >= dump_time) { // Close Drainage solenoid if it has been open for more than XX minutes set in HA digitalWrite(DRAINAGE_SOLENOID_PIN, LOW); // Switch on Red Drainage LED digitalWrite(DRAINAGE_RED_LED, HIGH); // Switch on Red Timeout LED digitalWrite(DUMP_TIMEOUT_RED_LED, HIGH); // Update the solenoid status variable drainage_solenoid_status = false; system_error_state = true; //Publish Drainage solenoid status to MQTT mqttClient.publish(MQTT_TOPIC_DRAINAGE_SOLENOID, 2, false, solenoid_closed_name.c_str()); } } } void pulseCounter() { pulseCount++; // Increment pulse count }
Все указанные библиотеки в скетче должны быть установлены заранее. Обратите внимание, что в формуле intervalVolume = pulseCount * 0.1622168797, коэффициент 0.1622168797 означает количество миллилитров за каждый оборот турбинки расходомера.
Шаг 5 : Настраиваем Home Assistant
Связь между ESP32 и Home Assistant (HA) осуществляется через MQTT-брокер. В HA создайте следующую карточку:
type: entities entities: - entity: sensor.water_temperature secondary_info: last-changed name: Температура воды icon: mdi:water - entity: sensor.ro_system_state secondary_info: last-changed name: Статус системы icon: mdi:water-alert - entity: sensor.ro_solenoid_status secondary_info: last-changed name: Соленоид осмоса icon: mdi:pipe-valve - entity: sensor.drainage_solenoid_status secondary_info: last-changed name: Соленоид сброса icon: mdi:pipe-valve - entity: switch.ro_pump secondary_info: last-changed name: Насос icon: mdi:pump - entity: input_number.dump_temp_threshold secondary_info: last-changed name: Порог температуры - entity: input_number.dump_time name: Макс. время сброса secondary_info: last-changed - entity: sensor.water_dump_counts_for_today secondary_info: last-changed name: Количество сбросов за сегодня - entity: sensor.average_dump_time_today secondary_info: last-changed name: Среднее время сброса icon: mdi:timer show_header_toggle: false title: Обратный осмос state_color: true
В configuration.yaml добавьте следующие строки:
sensor: - platform: template sensors: average_dump_time_today: unit_of_measurement: 'мин.' friendly_name: "Average dump time today" value_template: "{{ ((states('sensor.water_dumps_total_time_for_today')|float / states('sensor.water_dump_counts_for_today')|float) * 60)|round(1) }}" - platform: history_stats name: Water dump counts for today entity_id: sensor.ro_system_state state: "Сброс тёплой воды" type: count start: "{{ now().replace(hour=0, minute=0, second=0) }}" end: "{{ now() }}" - platform: history_stats name: Water dumps total time for today entity_id: sensor.ro_system_state state: "Сброс тёплой воды" type: time start: "{{ now().replace(hour=0, minute=0, second=0) }}" end: "{{ now() }}" input_number: dump_time: name: Dump time mode: slider unit_of_measurement: "мин." icon: mdi:timer min: 10 max: 20 step: 1 dump_temp_threshold: name: Dump temp threshold mode: slider unit_of_measurement: "°C" icon: mdi:thermometer min: 22 max: 31 step: 0.1
В automations.yaml добавьте следующее:
- id: 'XXXXXXXXXXXX1' alias: Отправить значение максимального времени сброса воды через MQTT description: '' trigger: - platform: state entity_id: input_number.dump_time condition: [] action: - data: topic: homeassistant/ro_system/dump_time payload: '{{ states(''input_number.dump_time'') }}' retain: true action: mqtt.publish mode: single - id: 'XXXXXXXXXXXX2' alias: Отправить значение порога температуры воды через MQTT description: '' trigger: - platform: state entity_id: input_number.dump_temp_threshold condition: [] action: - data: topic: homeassistant/ro_system/dump_temp_threshold payload: '{{ states(''input_number.dump_temp_threshold'') }}' retain: true action: mqtt.publish mode: single - id: 'XXXXXXXXXXXX3' alias: Установить значение максимального времени сброса воды из MQTT на слайдере description: '' trigger: - platform: mqtt topic: homeassistant/ro_system/dump_time condition: [] action: service: input_number.set_value data_template: entity_id: input_number.dump_time value: '{{ trigger.payload }}' mode: single - id: 'XXXXXXXXXXXX4' alias: Установить значение порога температуры воды из MQTT на слайдере description: '' trigger: - platform: mqtt topic: homeassistant/ro_system/dump_temp_threshold condition: [] action: - service: input_number.set_value data_template: entity_id: input_number.dump_temp_threshold value: '{{ trigger.payload }}' mode: single
Шаг 6 : Подключаем систему обратного осмоса
Подключите трубку подачи воды от холодной воды к входу блока манифольда. Выход от электрического шарового крана (НО) подключите к входу обратного осмоса, а выход от электрического шарового крана (НЗ) подключите к трубке дренажа через Т-фиттинг. Затем соедините блок манифольда с блоком управления и протестируйте систему. В моем случае в системе обратного осмоса присутствует насос подкачки, и он также подключен к блоку управления. Если термодатчик зафиксирует превышение температуры поступающей воды, то подача воды на обратный осмос закроется, и параллельно начнется сброс воды в дренаж. Также блок управления отключит насос подкачки обратного осмоса. После падения температуры воды произойдет обратный процесс, и насос подкачки включится через 15 секунд после начала закрытия электрических шаровых кранов. Если по какой-то причине температура не снизится ниже 2 градусов от заданной пороговой температуры на слайдере и в течение заданного времени сброса в Home Assistant, то сброс автоматически закроется, и на корпусе блока управления загорится красный светодиод ошибки.
P/S
Profit :)
Понравилась инструкция? Тогда поделитесь ей со своими друзьями или попробуйте написать свою собственную!