Upgrade of an inexpensive (Aliexpress) low-power 4 valve controller to a 4 valve MQTT/HA controlled irrigation system by adding an ESP8266 and some more stuff. I use it as a distributor after a Link-Tap valve, hence I wrote the Tasmota script specifically for that purpose. (safety built in)
Change the script for your purpose.
my Setup :
The Components
The picture shown it open, all fits into the original case, the only outside difference is the feed for the 3.3V.
Controller and Valves Automatic 4-zone Lcd Display Watering Timer Irrigation System Garden Water Timer Controller With 2 Solenoid Valves - Garden Water Timers - AliExpress
Plus an 74HC238E 3-to-8 decoder, a stepup converter 3.3V to 19V, some resistors and a 3.3V power supply.
The wiring (updated after Nickrout’s question, thx)
ESP8266 | 74HC238E | |
---|---|---|
gnd | GND | 8 |
GPIO 5 | 6 | |
gnd | 5 | |
gnd | 4 | |
GPIO 4 | 3 | |
GPIO 12 | 2 | |
GPIO 14 | 1 | |
VCC | ADC | |
VCC | EN | |
VCC | VCC | 16 |
I cut the battery compartment out which gave me room to wedge in the ESP8266.
Tasmota compiled with the script option (thank you https://github.com/benzino77/tasmocompiler)
I have the main valve (a Link-Tap) inside with solid pipes (and no more room for more pipes). The 4-valves are outside. Hence my Tasmota script “only” distributes that single on/off water feed onto the 4 separated irrigation segments. Default is set that all 4 segments are open and safeguarding within the Tasmota code prevents all 4 valves to be closed at the same time. (in order to prevent static pressure on the pipes if Link-Tap yet no segment would be open) Easy to see in the code, change as needed. (code at the end of this post as it is lengthy)
Template Config
- binary_sensor:
- name: "Irrigation4 Valve 1"
unique_id: "irrigation4_valve_1"
state: >
{{ 'on' if states('sensor.irrigation4_valves').split(',')[0] | int == 0 else 'off' }}
- name: "Irrigation4 Valve 2"
unique_id: "irrigation4_valve_2"
state: >
{{ 'on' if states('sensor.irrigation4_valves').split(',')[1] | int == 0 else 'off' }}
- name: "Irrigation4 Valve 3"
unique_id: "irrigation4_valve_3"
state: >
{{ 'on' if states('sensor.irrigation4_valves').split(',')[2] | int == 0 else 'off' }}
- name: "Irrigation4 Valve 4"
unique_id: "irrigation4_valve_4"
state: >
{{ 'on' if states('sensor.irrigation4_valves').split(',')[3] | int == 0 else 'off' }}
Script to open / close valves
irrigation_valve_open:
alias: irrigation_valve_open
sequence:
- service: mqtt.publish
data:
topic: cmnd/irrigation4_/VOPEN
qos: '2'
payload_template: '{{valve_number}}'
mode: single
icon: mdi:water-pump
irrigation_valve_close:
alias: irrigation_valve_close
sequence:
- condition: state
entity_id: input_boolean.irrigation4_mqtt
state: 'on'
- service: mqtt.publish
data:
topic: cmnd/irrigation4_/VCLOSE
qos: '2'
payload_template: '{{valve_number}}'
mode: single
icon: mdi:water-pump-off
and the automation to open a valve (the close is analogue)
I did not find a more elegant way for extracting the valve number from the entity_id, if you know, please tell me
- id: Irrigation_valve_open
alias: Irrigation_valve_open
description: ''
trigger:
- platform: state
entity_id:
- input_boolean.irrigation4_valve1
- input_boolean.irrigation4_valve2
- input_boolean.irrigation4_valve3
- input_boolean.irrigation4_valve4
to: 'on'
for:
hours: 0
minutes: 0
seconds: 10
condition: []
action:
- service: script.irrigation_valve_open
data:
valve_number: '{{trigger.entity_id.removeprefix(''input_boolean.irrigation4_valve'')}}'
mode: queued
“my” trigger to open all valves at the end of an irrigation cycle (again, prevent static pressure, hence a VOPENALL)
- id: '1660032786486'
alias: irrigation_stop
description: 'stop irrigation altogether '
trigger:
- platform: state
entity_id:
- switch.29a75f25004b1200_water_switch
to: 'off'
condition: []
action:
- service: mqtt.publish
data:
topic: cmnd/irrigation4_/VOPENALL
qos: '2'
payload: ' '
mode: single
plus an automation to reset the input_binaries if the controller resets or otherwise opens all valves. (the explicit OPENALL is added to the MQTT-msg to force a status change no matter what it was before, even if it already was 0,0,0,0)
- id: '1659980142774'
alias: irrigation4_reset
description: set all input_binary to open when 0,0,0,0 is sent from irrigation4
trigger:
- platform: state
entity_id:
- sensor.irrigation4_valves
to: 0.00,0.00,0.00,0.00
- platform: state
entity_id:
- sensor.irrigation4_valves
to: 0.00,0.00,0.00,0.00,OPENALL
condition: []
action:
- service: input_boolean.turn_on
data: {}
target:
entity_id:
- input_boolean.irrigation4_valve1
- input_boolean.irrigation4_valve2
- input_boolean.irrigation4_valve3
- input_boolean.irrigation4_valve4
mode: single
Below the Tasmota script code
>D
; 30 July 22 Bruno Initial Version with init
; 30 July 22 Bruno permanent array
; 31 July 22 Bruno publish valves...
; 6 Aug 22 Bruno v6 plain text string https://www.home-assistant.io/integrations/serial/#value_template-for-template-sensor
; 8 Aug 22 Bruno v7 openall and only change if different --> crash if all have to be set to closed -
; 8 Aug 22 Bruno what's making all reset crashing ? moved MQTT outside of STCH so it publishes only once
; 9 Aug 22 Bruno force open in VOPENALL, irrespective of previous status
;
; Pulse via 3-to-8 decoder
; gpio 14 = 0 open 1 = close
; gpio 12 = 0/1
; gpio 4 = 0/2
; gpio 5 = pulse 100ms
; Y0/Y1 = Valve 4
; Y2/Y3 = Valve 3
; Y4/Y4 = Valve 2
; Y6/Y7 = Valve 1
v=0
io=0
cnt=0
m:p:va=0 4
vchk=0
;;; cmnd/irrigation4_/VPULSE 1
>B
string=hello+"I booted"
print BOOT executed
print %string%
;set GPIO to output
print gpio to out
spinm(4 1)
spinm(5 1)
spinm(12 1)
spinm(14 1)
spin (5 0) ;; pulse to 0
delay(3000)
; ensure all valve values are set to close so openall opens them for sure
va[1]=1
va[2]=1
va[3]=1
va[4]=1
=#VOPENALL
;
; subroutines
#STCH(v io)
;pulse valve v for io=0=open; 1=close
print valve %v% %io%
spin(14 io) ;; set open / close
;
;set binary address for 3-to-8 decoder
if v>2 ; binary 0/2
then spin(4 0)
else spin(4 1)
endif
if v==1
or v==3 ;; binary 0/1
then spin(12 1)
else spin(12 0)
endif
;
;only pulse if change
if va[v]!=io
then spin(5 1) ;pulse
va[v]=io ;; store valve status
delay(100)
endif
spin(5 0)
;
delay(1000) ; to recharge the capacitor
#VCLOSE(v)
;safety check whether this is not the last valve closing. If it would then open all
vchk=va[1]+va[2]+va[3]+va[4]
if vchk==3
and va[v]==0 ;;v is the only valve still 0=open
then =#VOPENALL
else =#STCH(v 1)
endif
=>Publish tele/irrigation4_/VALVES %va[1]%,%va[2]%,%va[3]%,%va[4]%
#VOPEN(v)
=#STCH(v 0)
=>Publish tele/irrigation4_/VALVES %va[1]%,%va[2]%,%va[3]%,%va[4]%
#VSETONE(v)
spin(v 1)
=>Publish tele/irrigation4_/VALVES %va[1]%,%va[2]%,%va[3]%,%va[4]%
#VOPENALL
for cnt 1 4 1
va[cnt]=1 ; force open
=#VOPEN(cnt)
next
=>Publish tele/irrigation4_/VALVES %va[1]%,%va[2]%,%va[3]%,%va[4]%,OPENALL
>T
=>Publish tele/irrigation4_/VALVES %va[1]%,%va[2]%,%va[3]%,%va[4]%
>E
print MQTT event!
;>R
;print restarting now