Tinkster Logo
All
advancedSmart Home & IoT11-Mar-2025

Automatic warm water discharge system for reverse osmosis filters

Author
Anton Shagaev
Tomsk, RU
7 days
--
10
Cover
Friends, in one of my apartments, a problem with the cold water temperature recently arose, and it has not been resolved since then. Possibly, in the central water supply system of my building, hot water is being mixed somewhere into the cold water pipe, and because of this, water with a temperature of 36–39 degrees is coming from the cold water tap.
Such an elevated temperature from the cold water pipe negatively affects the operation of my reverse osmosis (RO) water purification system, as well as the operation of my water ionization device, since it is connected after the three RO pre-filters. According to , water up to 38 degrees can be supplied to the RO system, and up to 30 degrees Celsius to the water ionization device. In practice, it is recommended to use water with a temperature of 4–30 °C for optimal RO system operation. Also, water temperature of 25-35 °C can promote active bacterial growth in the storage tank of the reverse osmosis system, but this is solved by installing a UV filter.
After draining such water from the tap for 5 minutes, the water becomes about 27 degrees Celsius. It was decided to make an automatic warm water discharge system based on ESP32 and Home Assistant.

Steps

1

We manufacture a temperature sensor

Thermal sensors
DS18B20 temperature sensor
Temperature sensor attached to 1/4 BSP pipe using heat shrink tubing
Take the temperature sensor and solder a three-core signal wire to it. Do not forget about contact labeling to know where Data, Ground, and VDC are. Secure the sensor to the metal pipe using heat shrink tubing. Connect the pipe itself to two 1/4BSP – 1/4 Hose fittings. Then place the pipe in thermal insulation.
And here are the ready temperature sensors (I made an additional temperature sensor for another project):
2

Assembling the manifold block

Assembling the manifold block
Manifold block
Each electric ball valve will have its own enclosure, so the number of connecting fittings will vary. In my case, I purchased a storage container with a lid, drilled three holes in it for 1/4" tubing, as well as four holes for the GX12 connector plug on the housing. I placed a temperature sensor, two electric ball valves, a flow meter inside this enclosure, and connected everything with reverse osmosis system fittings. I soldered the wires from the electric ball valves, temperature sensor, and flow meter to the corresponding outputs of the GX12 connector plugs.
3

Control unit soldering

Control unit soldering
Control unit
Back side of the control unit
Here everything is also extremely simple. Drill the corresponding holes in the box for the GX12, LEDs, and 220VAC power cable. Assemble the components according to the diagram.
4

Upload the program to ESP32

Connect the ESP32 to the laptop, open Arduino IDE and upload the following sketch:
tinkster@almalinux:~#
1
#include <Arduino.h>
2
#include <WiFi.h>
3
#include <WiFiClient.h>
4
#include <OneWire.h>
5
#include <DallasTemperature.h>
6
#include <mqtt_client.h>
7
#include "esp_heap_caps.h"
8
9
#if __has_include(<esp_arduino_version.h>)
10
#include <esp_arduino_version.h>
11
#endif
12
13
// ================== CONFIGURATION ==================
14
// WiFi parameters
15
#define WIFI_SSID "HomeNetwork"
16
#define WIFI_PASSWORD "SecurePass2024"
17
IPAddress staticIP(192, 168, 1, 100);
18
IPAddress gateway(192, 168, 1, 1);
19
IPAddress subnet(255, 255, 255, 0);
20
21
// MQTT broker parameters
22
#define MQTT_HOST "192.168.1.50"
23
#define MQTT_PORT 1883
24
#define MQTT_USER "device_user"
25
#define MQTT_PASSWORD "mqtt_secure_pass"
26
27
// MQTT topics
28
#define MQTT_TOPIC_WATER_TEMPERATURE "homeassistant/ro_system/water_temperature"
29
#define MQTT_TOPIC_RO_SOLENOID "homeassistant/ro_system/ro_solenoid"
30
#define MQTT_TOPIC_DRAINAGE_SOLENOID "homeassistant/ro_system/drainage_solenoid"
31
#define MQTT_TOPIC_RO_PUMP "homeassistant/ro_system/ro_pump"
32
#define MQTT_TOPIC_DUMPED_WATER_INTERVAL_VOLUME "homeassistant/ro_system/dumped_water_interval_volume"
33
#define MQTT_TOPIC_SYSTEM_STATE "homeassistant/ro_system/system_state"
34
#define MQTT_TOPIC_DUMP_TIME "homeassistant/ro_system/dump_time"
35
#define MQTT_TOPIC_DUMP_TEMP_THRESHOLD "homeassistant/ro_system/dump_temp_threshold"
36
37
// ================== GPIO ==================
38
#define RO_SOLENOID_PIN 26 // Supply valve
39
#define DRAINAGE_SOLENOID_PIN 25 // Drain valve
40
#define ONE_WIRE_BUS 27 // DS18B20 temperature sensor
41
#define FLOW_METER_PIN 33 // Flow meter
42
#define RO_BLUE_LED 15 // Blue LED
43
#define DRAINAGE_RED_LED 2 // Red LED
44
#define DUMP_TIMEOUT_RED_LED 4 // Error LED
45
#define RO_PUMP_PIN 18 // Booster pump
46
47
// ================== STATE ENUMS ==================
48
// Pump command state (debounce)
49
enum PumpCommandState {
50
PUMP_CMD_IDLE=0,
51
PUMP_CMD_PENDING=1,
52
PUMP_CMD_CONFIRMED=2
53
};
54
55
// System state
56
enum SystemState {
57
STATE_NORMAL=0, // Normal operation
58
STATE_DUMP_IN_PROGRESS=1, // Warm water dump in progress
59
STATE_PUMP_DELAYED_START=2,// Delay before pump restart
60
STATE_DUMP_TIMEOUT=3 // Error: dump timeout exceeded
61
};
62
63
// ================== SENSORS AND MQTT ==================
64
OneWire oneWire(ONE_WIRE_BUS);
65
DallasTemperature sensors(&oneWire);
66
67
static esp_mqtt_client_handle_t mqtt_client = NULL;
68
static char mqtt_publish_buf[128];
69
static char mqtt_topic_buf[128];
70
static char mqtt_data_buf[64];
71
72
// ================== SYSTEM STATE ==================
73
SystemState system_state = STATE_NORMAL;
74
PumpCommandState pump_cmd_state = PUMP_CMD_IDLE;
75
76
bool ro_solenoid_open = true;
77
bool drainage_solenoid_open = false;
78
bool ro_pump_enabled = true;
79
bool mqtt_control_allowed = true;
80
81
// ================== PARAMETERS ==================
82
float water_temperature = 0.0;
83
long dump_time_ms = 600000; // Dump time (ms)
84
float dump_temp_threshold = 29.0; // Temperature threshold for dump (°C)
85
float dump_temp_hysteresis = 2.0; // Hysteresis (°C)
86
const long pump_restart_delay = 15000; // Pump restart delay (ms)
87
88
bool pump_cmd_pending_value = false;
89
unsigned long pump_cmd_timestamp = 0;
90
91
// ================== TIMERS ==================
92
unsigned long last_sensor_update = 0;
93
unsigned long last_status_update = 0;
94
unsigned long dump_start_time = 0;
95
unsigned long pump_restart_time = 0;
96
unsigned long last_heap_check = 0;
97
98
const long sensor_interval = 5000;
99
const long STATUS_UPDATE_INTERVAL = 5000;
100
const long led_update_interval = 100;
101
102
// ================== FLOW METER ==================
103
portMUX_TYPE mux = portMUX_INITIALIZER_UNLOCKED;
104
volatile uint32_t pulseCount = 0;
105
volatile bool wifiReconnectNeeded = false;
106
volatile bool mqttReconnectNeeded = false;
107
const float FLOW_COEFFICIENT = 0.1622168797; // Pulses -> liters
108
109
// ================== STATUS STRINGS ==================
110
const char* solenoid_open_name = "Open";
111
const char* solenoid_closed_name = "Closed";
112
const char* status_normal = "Water supply to reverse osmosis";
113
const char* status_dump = "Warm water dump";
114
const char* status_dump_timeout = "Dump timeout exceeded";
115
const char* deviceName = "ESP32RO";
116
117
// ================== LOGGING AND MQTT ==================
118
119
// Logging with timestamp and category
120
void logInfoF(const char* category, const char* format, ...) {
121
unsigned long timestamp = millis();
122
char buf[128];
123
va_list args;
124
va_start(args, format);
125
vsnprintf(buf, sizeof(buf), format, args);
126
va_end(args);
127
Serial.printf("[%lu] [%s] %sn", timestamp, category, buf);
128
}
129
130
// Publish to MQTT (QoS=1, no retain)
131
void publishMqtt(const char* topic, const char* payload) {
132
if (mqtt_client) {
133
esp_mqtt_client_publish(mqtt_client, topic, payload, 0, 1, 0);
134
}
135
}
136
137
// ================== HELPER PUBLISH FUNCTIONS ==================
138
139
void publishRoSolenoidStatus() {
140
publishMqtt(MQTT_TOPIC_RO_SOLENOID, ro_solenoid_open ? solenoid_open_name : solenoid_closed_name);
141
}
142
143
void publishDrainageSolenoidStatus() {
144
publishMqtt(MQTT_TOPIC_DRAINAGE_SOLENOID, drainage_solenoid_open ? solenoid_open_name : solenoid_closed_name);
145
}
146
147
void publishPumpStatus() {
148
publishMqtt(MQTT_TOPIC_RO_PUMP, ro_pump_enabled ? "1" : "0");
149
}
150
151
void publishSystemState() {
152
const char* state_str;
153
switch (system_state) {
154
case STATE_DUMP_IN_PROGRESS:
155
state_str = status_dump;
156
break;
157
case STATE_DUMP_TIMEOUT:
158
state_str = status_dump_timeout;
159
break;
160
case STATE_PUMP_DELAYED_START:
161
case STATE_NORMAL:
162
default:
163
state_str = status_normal;
164
break;
165
}
166
publishMqtt(MQTT_TOPIC_SYSTEM_STATE, state_str);
167
}
168
169
// ================== COMPONENT CONTROL ==================
170
171
// Control supply valve (LOW opens, HIGH closes)
172
void setRoSolenoid(bool open) {
173
if (ro_solenoid_open != open) {
174
ro_solenoid_open = open;
175
digitalWrite(RO_SOLENOID_PIN, open ? LOW : HIGH);
176
logInfoF("RO_SOL", "Changed to: %s", open ? "OPEN" : "CLOSED");
177
publishRoSolenoidStatus();
178
}
179
}
180
181
// Control drain valve (HIGH opens, LOW closes)
182
void setDrainageSolenoid(bool open) {
183
if (drainage_solenoid_open != open) {
184
drainage_solenoid_open = open;
185
digitalWrite(DRAINAGE_SOLENOID_PIN, open ? HIGH : LOW);
186
logInfoF("DRAIN_SOL", "Changed to: %s", open ? "OPEN" : "CLOSED");
187
publishDrainageSolenoidStatus();
188
}
189
}
190
191
// Control pump (LOW turns on, HIGH turns off)
192
// Blocks turning on during dump and cooling
193
void setPumpEnabled(bool enabled) {
194
if (enabled && (system_state == STATE_DUMP_IN_PROGRESS || system_state == STATE_PUMP_DELAYED_START)) {
195
logInfoF("PUMP", "Block: System State %d", system_state);
196
return;
197
}
198
199
if (ro_pump_enabled != enabled) {
200
ro_pump_enabled = enabled;
201
digitalWrite(RO_PUMP_PIN, enabled ? LOW : HIGH);
202
logInfoF("PUMP", "Changed to: %s", enabled ? "ON" : "OFF");
203
publishPumpStatus();
204
}
205
}
206
207
// ================== SYSTEM LOGIC ==================
208
209
// Main system control logic:
210
// 1. Overheat detection -> start dump
211
// 2. Cooling detection -> delay before restart
212
// 3. Dump timeout -> error
213
// 4. Delay completion -> return to normal
214
void handleSystemLogic() {
215
unsigned long now = millis();
216
217
// STAGE 1: OVERHEAT - START DUMP
218
if (system_state == STATE_NORMAL && water_temperature > dump_temp_threshold) {
219
logInfoF("SYSTEM", "Temp too high (%.1f), starting DUMP", water_temperature);
220
system_state = STATE_DUMP_IN_PROGRESS;
221
dump_start_time = now;
222
223
setRoSolenoid(false); // Close supply
224
setDrainageSolenoid(true); // Open drain
225
setPumpEnabled(false); // Turn off pump
226
mqtt_control_allowed = false;
227
228
publishSystemState();
229
}
230
231
// STAGE 2: COOLING - DELAY BEFORE RESTART
232
if (system_state == STATE_DUMP_IN_PROGRESS && water_temperature < (dump_temp_threshold - dump_temp_hysteresis)) {
233
logInfoF("SYSTEM", "Temp normal (%.1f), waiting...", water_temperature);
234
system_state = STATE_PUMP_DELAYED_START;
235
pump_restart_time = now;
236
237
setRoSolenoid(true); // Open supply
238
setDrainageSolenoid(false); // Close drain
239
mqtt_control_allowed = false;
240
241
publishSystemState();
242
}
243
244
// STAGE 3: DUMP TIMEOUT - ERROR
245
if (system_state == STATE_DUMP_IN_PROGRESS && (now - dump_start_time) >= dump_time_ms) {
246
logInfoF("SYSTEM", "DUMP TIMEOUT! Error!");
247
system_state = STATE_DUMP_TIMEOUT;
248
249
setRoSolenoid(false);
250
setDrainageSolenoid(false);
251
setPumpEnabled(false);
252
mqtt_control_allowed = false;
253
254
publishSystemState();
255
}
256
257
// STAGE 4: DELAY COMPLETED - RETURN TO NORMAL
258
if (system_state == STATE_PUMP_DELAYED_START && (now - pump_restart_time) >= pump_restart_delay) {
259
logInfoF("SYSTEM", "Back to Normal.");
260
system_state = STATE_NORMAL;
261
262
setPumpEnabled(true);
263
mqtt_control_allowed = true;
264
265
publishSystemState();
266
}
267
}
268
269
// Process pump control commands with debounce (300ms)
270
void handlePumpCommand() {
271
unsigned long now = millis();
272
switch(pump_cmd_state) {
273
case PUMP_CMD_IDLE:
274
break;
275
276
case PUMP_CMD_PENDING:
277
// Wait for debounce
278
if (now - pump_cmd_timestamp >= 300)
279
pump_cmd_state = PUMP_CMD_CONFIRMED;
280
break;
281
282
case PUMP_CMD_CONFIRMED:
283
// Execute command if state allows
284
if (mqtt_control_allowed && system_state != STATE_DUMP_TIMEOUT) {
285
setPumpEnabled(pump_cmd_pending_value);
286
}
287
pump_cmd_state = PUMP_CMD_IDLE;
288
break;
289
}
290
}
291
292
// ================== SENSORS AND HEARTBEAT ==================
293
294
// Flow meter interrupt
295
void IRAM_ATTR pulseCounter() {
296
portENTER_CRITICAL_ISR(&mux);
297
pulseCount++;
298
portEXIT_CRITICAL_ISR(&mux);
299
}
300
301
// Sensor polling (temperature and flow)
302
void handleSensorUpdate() {
303
if (millis() - last_sensor_update < sensor_interval) return;
304
last_sensor_update = millis();
305
306
sensors.requestTemperatures();
307
float t = sensors.getTempCByIndex(0);
308
if (t > -50 && t < 100) water_temperature = t;
309
310
// Read flow meter
311
uint32_t pulses;
312
portENTER_CRITICAL(&mux);
313
pulses = pulseCount;
314
pulseCount = 0;
315
portEXIT_CRITICAL(&mux);
316
317
float intervalVolume = pulses * FLOW_COEFFICIENT;
318
319
snprintf(mqtt_publish_buf, sizeof(mqtt_publish_buf), "%.2f", water_temperature);
320
publishMqtt(MQTT_TOPIC_WATER_TEMPERATURE, mqtt_publish_buf);
321
322
snprintf(mqtt_publish_buf, sizeof(mqtt_publish_buf), "%.2f", intervalVolume);
323
publishMqtt(MQTT_TOPIC_DUMPED_WATER_INTERVAL_VOLUME, mqtt_publish_buf);
324
}
325
326
// Periodic status update to Home Assistant
327
void publishStatusHeartbeat() {
328
if (millis() - last_status_update < STATUS_UPDATE_INTERVAL) return;
329
last_status_update = millis();
330
331
if (mqtt_client) {
332
publishRoSolenoidStatus();
333
publishDrainageSolenoidStatus();
334
publishPumpStatus();
335
publishSystemState();
336
337
snprintf(mqtt_publish_buf, sizeof(mqtt_publish_buf), "%ld", dump_time_ms / 60000);
338
publishMqtt(MQTT_TOPIC_DUMP_TIME, mqtt_publish_buf);
339
340
snprintf(mqtt_publish_buf, sizeof(mqtt_publish_buf), "%.1f", dump_temp_threshold);
341
publishMqtt(MQTT_TOPIC_DUMP_TEMP_THRESHOLD, mqtt_publish_buf);
342
}
343
}
344
345
// ================== MQTT HANDLER ==================
346
347
// MQTT event handler
348
static void mqtt_event_handler(void* handler_args, esp_event_base_t base, int32_t event_id, void* event_data) {
349
esp_mqtt_event_handle_t event = (esp_mqtt_event_handle_t) event_data;
350
switch((esp_mqtt_event_id_t)event_id) {
351
case MQTT_EVENT_CONNECTED:
352
logInfoF("MQTT","Connected");
353
354
// Subscribe to control topics
355
esp_mqtt_client_subscribe(mqtt_client, MQTT_TOPIC_RO_PUMP, 0);
356
esp_mqtt_client_subscribe(mqtt_client, MQTT_TOPIC_DUMP_TIME, 0);
357
esp_mqtt_client_subscribe(mqtt_client, MQTT_TOPIC_DUMP_TEMP_THRESHOLD, 0);
358
359
// Send full status on connection
360
publishRoSolenoidStatus();
361
publishDrainageSolenoidStatus();
362
publishPumpStatus();
363
publishSystemState();
364
365
snprintf(mqtt_publish_buf, sizeof(mqtt_publish_buf), "%.2f", water_temperature);
366
publishMqtt(MQTT_TOPIC_WATER_TEMPERATURE, mqtt_publish_buf);
367
break;
368
369
case MQTT_EVENT_DATA: {
370
if (event->topic_len >= sizeof(mqtt_topic_buf) || event->data_len >= sizeof(mqtt_data_buf)) break;
371
372
memcpy(mqtt_topic_buf, event->topic, event->topic_len);
373
mqtt_topic_buf[event->topic_len] = 0;
374
memcpy(mqtt_data_buf, event->data, event->data_len);
375
mqtt_data_buf[event->data_len] = 0;
376
377
// Pump on/off command
378
if (strncmp(mqtt_topic_buf, MQTT_TOPIC_RO_PUMP, event->topic_len) == 0) {
379
bool new_state = (atoi(mqtt_data_buf) != 0);
380
pump_cmd_pending_value = new_state;
381
pump_cmd_state = PUMP_CMD_PENDING;
382
pump_cmd_timestamp = millis();
383
}
384
// Change dump temperature threshold
385
else if (strncmp(mqtt_topic_buf, MQTT_TOPIC_DUMP_TEMP_THRESHOLD, event->topic_len) == 0) {
386
dump_temp_threshold = atof(mqtt_data_buf);
387
logInfoF("CONF", "New Temp: %.1f", dump_temp_threshold);
388
}
389
// Change dump time (in minutes)
390
else if (strncmp(mqtt_topic_buf, MQTT_TOPIC_DUMP_TIME, event->topic_len) == 0) {
391
dump_time_ms = atol(mqtt_data_buf) * 60000;
392
logInfoF("CONF", "New Time: %ld ms", dump_time_ms);
393
}
394
} break;
395
default:
396
break;
397
}
398
}
399
400
// Initialize MQTT client
401
void mqtt_setup() {
402
if (mqtt_client) {
403
esp_mqtt_client_stop(mqtt_client);
404
esp_mqtt_client_destroy(mqtt_client);
405
mqtt_client = NULL;
406
}
407
408
esp_mqtt_client_config_t mqtt_cfg = {};
409
410
#if defined(ESP_ARDUINO_VERSION_MAJOR) && ESP_ARDUINO_VERSION_MAJOR >= 3
411
mqtt_cfg.broker.address.hostname = MQTT_HOST;
412
mqtt_cfg.broker.address.port = MQTT_PORT;
413
mqtt_cfg.credentials.username = MQTT_USER;
414
mqtt_cfg.credentials.authentication.password = MQTT_PASSWORD;
415
#else
416
mqtt_cfg.host = MQTT_HOST;
417
mqtt_cfg.port = MQTT_PORT;
418
mqtt_cfg.username = MQTT_USER;
419
mqtt_cfg.password = MQTT_PASSWORD;
420
#endif
421
422
mqtt_client = esp_mqtt_client_init(&mqtt_cfg);
423
if (mqtt_client) {
424
esp_mqtt_client_register_event(mqtt_client, M
All specified libraries in the sketch must be installed in advance. Note that in the formulaintervalVolume = pulseCount * 0.1622168797, the coefficient 0.1622168797 means the number of milliliters per each revolution of the flowmeter turbine.
5

Setting up Home Assistant

Setting up Home Assistant
The connection between ESP32 and Home Assistant (HA) is established via an MQTT broker. In HA, create the following card:
tinkster@almalinux:~#
1
type: entities
2
entities:
3
- entity: sensor.water_temperature
4
secondary_info: last-changed
5
name: Water Temperature
6
icon: mdi:water
7
- entity: sensor.ro_system_state
8
secondary_info: last-changed
9
name: System Status
10
icon: mdi:water-alert
11
- entity: sensor.ro_solenoid_status
12
secondary_info: last-changed
13
name: RO Solenoid
14
icon: mdi:pipe-valve
15
- entity: sensor.drainage_solenoid_status
16
secondary_info: last-changed
17
name: Drain Solenoid
18
icon: mdi:pipe-valve
19
- entity: switch.ro_pump
20
secondary_info: last-changed
21
name: Pump
22
icon: mdi:pump
23
- entity: input_number.dump_temp_threshold
24
secondary_info: last-changed
25
name: Temperature Threshold
26
- entity: input_number.dump_time
27
name: Max Dump Time
28
secondary_info: last-changed
29
- entity: sensor.water_dump_counts_for_today
30
secondary_info: last-changed
31
name: Dump Count Today
32
- entity: sensor.average_dump_time_today
33
secondary_info: last-changed
34
name: Average Dump Time
35
icon: mdi:timer
36
show_header_toggle: false
37
title: Reverse Osmosis
38
state_color: true
В configuration.yaml add the following lines:
tinkster@almalinux:~#
1
sensor:
2
- platform: template
3
sensors:
4
average_dump_time_today:
5
unit_of_measurement: 'мин.'
6
friendly_name: "Average dump time today"
7
value_template: "{{ ((states('sensor.water_dumps_total_time_for_today')|float / states('sensor.water_dump_counts_for_today')|float) * 60)|round(1) }}"
8
- platform: history_stats
9
name: Water dump counts for today
10
entity_id: sensor.ro_system_state
11
state: "Warm water dump" # Changed from "Сброс тёплой воды"
12
type: count
13
start: "{{ now().replace(hour=0, minute=0, second=0) }}"
14
end: "{{ now() }}"
15
- platform: history_stats
16
name: Water dumps total time for today
17
entity_id: sensor.ro_system_state
18
state: "Warm water dump" # Changed from "Сброс тёплой воды"
19
type: time
20
start: "{{ now().replace(hour=0, minute=0, second=0) }}"
21
end: "{{ now() }}"
22
input_number:
23
dump_time:
24
name: Dump time
25
mode: slider
26
unit_of_measurement: "мин."
27
icon: mdi:timer
28
min: 10
29
max: 20
30
step: 1
31
dump_temp_threshold:
32
name: Dump temp threshold
33
mode: slider
34
unit_of_measurement: "°C"
35
icon: mdi:thermometer
36
min: 22
37
max: 31
38
step: 0.1
В automations.yaml add the following:
tinkster@almalinux:~#
1
- id: 'XXXXXXXXXXXX1'
2
alias: Send maximum water dump time value via MQTT
3
description: ''
4
trigger:
5
- platform: state
6
entity_id: input_number.dump_time
7
condition: []
8
action:
9
- data:
10
topic: homeassistant/ro_system/dump_time
11
payload: '{{ states(''input_number.dump_time'') }}'
12
retain: true
13
action: mqtt.publish
14
mode: single
15
- id: 'XXXXXXXXXXXX2'
16
alias: Send water temperature threshold value via MQTT
17
description: ''
18
trigger:
19
- platform: state
20
entity_id: input_number.dump_temp_threshold
21
condition: []
22
action:
23
- data:
24
topic: homeassistant/ro_system/dump_temp_threshold
25
payload: '{{ states(''input_number.dump_temp_threshold'') }}'
26
retain: true
27
action: mqtt.publish
28
mode: single
29
- id: 'XXXXXXXXXXXX3'
30
alias: Set maximum water dump time value from MQTT on the slider
31
description: ''
32
trigger:
33
- platform: mqtt
34
topic: homeassistant/ro_system/dump_time
35
condition: []
36
action:
37
service: input_number.set_value
38
data_template:
39
entity_id: input_number.dump_time
40
value: '{{ trigger.payload }}'
41
mode: single
42
- id: 'XXXXXXXXXXXX4'
43
alias: Set water temperature threshold value from MQTT on the slider
44
description: ''
45
trigger:
46
- platform: mqtt
47
topic: homeassistant/ro_system/dump_temp_threshold
48
condition: []
49
action:
50
- service: input_number.set_value
51
data_template:
52
entity_id: input_number.dump_temp_threshold
53
value: '{{ trigger.payload }}'
54
mode: single
6

Connecting the reverse osmosis system

Connect the water supply tube from the cold water to the inlet of the manifold block. Connect the outlet from the normally open (NO) electric ball valve to the inlet of the reverse osmosis system, and connect the outlet from the normally closed (NC) electric ball valve to the drain tube via a T-fitting. Then connect the manifold block to the control unit and test the system. In my case, the reverse osmosis system includes a booster pump, and it is also connected to the control unit. If the temperature sensor detects that the incoming water temperature exceeds the threshold, the water supply to the reverse osmosis system will close, and simultaneously, water will begin to discharge to the drain. The control unit will also turn off the reverse osmosis booster pump. After the water temperature drops, the reverse process will occur, and the booster pump will turn on 15 seconds after the electric ball valves begin to close. If for some reason the temperature does not drop below 2 degrees from the threshold temperature set on the slider and within the set drain time in Home Assistant, the drain will automatically close, and a red error LED on the control unit housing will light up.

Conclusion

Profit :)

Discussion (0)

No comments yet. Be the first!

Maker

Avatar
Anton Shagaev
Tomsk, RU

Anton is the Founding Engineer at Tinkster. He translates industrial reliability into software architecture, ensuring the platform's core is built to last. Anton studied oil and gas engineering in the United States and also holds two honors degrees from Tomsk Polytechnic University.

AI Project Assistant

Tinkster Neural Core

Hi! I am the AI assistant for this project. Ask me any questions about the assembly, code, or components.

Downloads

A-560Em RO Manual
1.4 MB