I’ve recently completed an ESP32 based project for control and monitoring equipment on my Koi Carp pond.
This necessitated designing a board in Kicad, getting it printed, building, testing and installing.
I’m pleased to say that the design and construction have been successful.
The board has:
16 x 5V outputs
18 x Inputs
2 x 1 Wire inputs
On board reset switch
On board Wifi LED
On board Status LED
On board 5V LED
On board 12V LED
12V PSU
5V PSU
So, if there is any interest in this, I’d gladly support anyone with either supplying the board, KiCad files and documentation.
It can, of course, be used for any project, not just Koi ponds!
7 Likes
Very nice work - i wish my soldering skills were up to that level !!
Craig
Hi Ash, really impressive layout. I’m interested in the board/files/documentation if you would share it kindly?
We have a (sort of) similar setup and have some issues. Maybe you can help us out?
Hi all,
We’re trying to setup 1x ESP32 with 2x8ch relay modules (please find wiring scheme).
The relay modules receive power and can be invididual toggled as switches in home assistant.
We tried to attach a pushbutton to the ESP to trigger a scene in HASS.
However, it keeps turning on/off without even pushing a button (see log).
YAML config - binary sensor part:
binary_sensor:
- platform: gpio
name: "esp01_button01"
id: esp01_button01
pin:
number: GPIO34
mode: I…
ashscott
(Ash)
November 6, 2020, 1:11pm
5
Here’s the ESPHome file I’m using:
esphome:
name: pond_control_2
platform: ESP32
board: esp-wrover-kit
on_boot:
then:
- binary_sensor.template.publish:
id: enable_water_fill
state: ON
- binary_sensor.template.publish:
id: drum_filter_recovery_mode
state: OFF
- binary_sensor.template.publish:
id: drum_empty
state: OFF
- binary_sensor.template.publish:
id: pond_control_restarted
state: On
globals:
- id: water_change_amount_variable
type: int
restore_value: no
initial_value: '25'
- id: drum_wash_timer_variable
type: int
restore_value: no
initial_value: '10'
- id: spindrifter_off_timer_variable
type: int
restore_value: no
initial_value: '20'
- id: heron_scarer_on_timer_variable
type: int
restore_value: no
initial_value: '5'
wifi:
ssid: !secret dryderdale_wifi_SSID
password: !secret dryderdale_wifi_password
manual_ip:
static_ip: 10.0.1.116
gateway: 10.0.1.1
subnet: 255.255.255.0
ap:
ssid: "Pond Control"
password: !secret OTA_password
web_server:
port: 80
auth:
username: admin
password: !secret OTA_password
status_led:
pin:
number: GPIO0
inverted: True
api:
ota:
safe_mode: True
password: !secret OTA_password
captive_portal:
logger:
level: debug
dallas:
- pin: GPIO26
update_interval: 60s
i2c:
sda: 21
scl: 22
pcf8574:
- id: 'expander_1'
address: 0x20
pcf8575: False
- id: 'expander_2'
address: 0x24
pcf8575: False
time:
- platform: homeassistant
id: homeassistant_time
on_time:
###########################
##### Waterfall timer #####
###########################
# Every morning Spring to Autumn
- minutes: 00
hours: 10
months: 4,5,6,7,8,9,10
then:
- switch.turn_on: waterfall_pump
- minutes: 00
hours: 22
months: 4,5,6,7,8,9,10
then:
- switch.turn_off: waterfall_pump
- minutes: 00
hours: 10
months: 11,12,1,2,3
then:
- switch.turn_on: waterfall_pump
- minutes: 10
hours: 10
months: 11,12,1,2,3
then:
- switch.turn_off: waterfall_pump
########################################
###### Weekly Water Change Control #####
########################################
- minutes: 00
hours: 08
days_of_week: THU
then:
- script.execute: do_water_change
###################
##### Outputs #####
###################
switch:
- platform: restart
name: "Restart koi pond control"
id: restart_pond_control
- platform: gpio
pin: GPIO2
name: "Drum motor"
id: drum_motor
inverted: true
restore_mode: RESTORE_DEFAULT_OFF
- platform: gpio
pin: GPIO4
name: "Drum wash pump"
id: drum_wash_pump
inverted: true
restore_mode: RESTORE_DEFAULT_OFF
- platform: gpio
pin: GPIO5
name: "Main pump"
id: main_pump
inverted: true
icon: mdi:water-pump
restore_mode: RESTORE_DEFAULT_ON
- platform: gpio
pin: GPIO12
name: "Waterfall pump"
id: waterfall_pump
inverted: true
restore_mode: RESTORE_DEFAULT_ON
- platform: gpio
pin: GPIO13
name: "Skimmer pump"
id: skimmer_pump
inverted: true
icon: mdi:water-pump
restore_mode: RESTORE_DEFAULT_ON
- platform: gpio
pin: GPIO14
name: "Spindrifter air"
id: spindrifter_air
inverted: true
icon: mdi:air-filter
restore_mode: RESTORE_DEFAULT_ON
- platform: gpio
pin: GPIO15
name: "Anoxic air"
id: anoxic_air
inverted: true
icon: mdi:air-filter
restore_mode: RESTORE_DEFAULT_ON
- platform: gpio
pin: GPIO16
name: "Pond lights"
id: pond_lights
inverted: true
restore_mode: RESTORE_DEFAULT_OFF
- platform: gpio
pin: GPIO17
name: "Water fill valve"
id: water_fill_valve
inverted: true
restore_mode: RESTORE_DEFAULT_OFF
- platform: gpio
pin:
pcf8574: expander_1
number: 5
mode: OUTPUT
name: "Ozone air"
inverted: True
icon: mdi:air-filter
restore_mode: RESTORE_DEFAULT_ON
id: ozone_air
- platform: gpio
pin:
pcf8574: expander_1
number: 6
mode: OUTPUT
inverted: False
id: wifi_connected_led
- platform: gpio
pin:
pcf8574: expander_1
number: 0
mode: OUTPUT
inverted: True
id: fish_feeder
restore_mode: ALWAYS_OFF
- platform: gpio
pin:
pcf8574: expander_1
number: 7
mode: OUTPUT
inverted: True
name: "Heron scarer"
id: heron_scarer
restore_mode: ALWAYS_OFF
##################
##### Inputs #####
##################
binary_sensor:
- platform: gpio
pin:
number: GPIO18
mode: INPUT_PULLUP
name: "Drum motor toggle"
id: drum_motor_toggle
filters:
- invert:
on_press:
then:
- switch.turn_on: drum_motor
on_release:
then:
- switch.turn_off: drum_motor
- platform: gpio
pin:
number: GPIO19
mode: INPUT_PULLUP
name: "Drum wash pump toggle"
filters:
- invert:
on_press:
then:
- switch.turn_on: drum_wash_pump
on_release:
then:
- switch.turn_off: drum_wash_pump
- platform: gpio
name: "Main pump toggle"
pin:
number: GPIO36
mode: INPUT_PULLUP
id: main_pump_toggle
on_press:
then:
- switch.toggle: main_pump
- platform: gpio
name: "Waterfall pump toggle"
pin:
number: GPIO33
mode: INPUT_PULLUP
id: waterfall_pump_toggle
on_press:
then:
- switch.toggle: waterfall_pump
- platform: gpio
name: "Skimmer pump toggle"
pin:
number: GPIO23
mode: INPUT_PULLUP
inverted: False
id: skimmer_pump_toggle
on_press:
then:
- switch.toggle: skimmer_pump
- platform: gpio
pin:
number: GPIO25
mode: INPUT_PULLUP
name: "Spindrifter air toggle"
id: spindrifter_air_toggle
on_press:
then:
- switch.toggle: spindrifter_air
- platform: gpio
pin:
number: GPIO27
mode: INPUT_PULLUP
name: "Anoxic air toggle"
id: anoxic_air_toggle
on_press:
then:
- switch.toggle: anoxic_air
- platform: gpio
pin:
number: GPIO32
mode: INPUT_PULLUP
name: "IR sensor"
id: ir_sensor
filters:
- invert:
- delayed_on_off: 100ms
on_press:
then:
- if:
condition:
and:
- binary_sensor.is_off: disable_spindrifter_ir
then:
- script.execute: do_turn_off_spindrifter_and_skimmer
- script.execute: do_turn_on_heron_scarer
- platform: gpio
pin:
number: GPIO34
mode: INPUT_PULLUP
name: "Water meter sensor"
id: water_meter_sensor
- platform: gpio
name: "Water level high sensor"
pin:
pcf8574: expander_1
number: 2
mode: INPUT
inverted: False
id: water_level_high_sensor
on_release:
then:
- switch.turn_off: water_fill_valve
- if:
condition:
- binary_sensor.is_on: drum_filter_recovery_mode
then:
- binary_sensor.template.publish:
id: drum_filter_recovery_mode
state: OFF
- binary_sensor.template.publish:
id: enable_water_fill
state: ON
- platform: gpio
name: "Water level low sensor"
pin:
pcf8574: expander_1
number: 3
mode: INPUT
inverted: False
id: water_level_low_sensor
on_press:
then:
- if:
condition:
and:
- binary_sensor.is_on: water_level_high_sensor # inhibit wash if drum wash low level
- binary_sensor.is_on: enable_water_fill
then:
- switch.turn_on: water_fill_valve
on_release:
then:
- if:
condition:
- binary_sensor.is_on: drum_filter_recovery_mode
then:
- script.execute: do_recovery_drum_wash
- platform: gpio
pin:
number: GPIO35
mode: INPUT_PULLUP
name: "Drum low level switch"
id: drum_low_level_switch
on_press:
then:
- if:
condition:
and:
- binary_sensor.is_off: drum_wash_low_level_switch # inhibit wash if drum wash low level
- binary_sensor.is_off: disable_drum_wash
then:
- if:
condition:
- binary_sensor.is_off: drum_filter_recovery_mode
then:
- script.execute: do_drum_wash
on_release:
then:
- if:
condition:
- binary_sensor.is_off: drum_wash_low_level_switch
then:
- binary_sensor.template.publish:
id: drum_empty
state: OFF
- platform: gpio
name: "Drum wash low level switch"
pin:
pcf8574: expander_1
number: 4
mode: INPUT
inverted: False
id: drum_wash_low_level_switch
on_press:
then:
- switch.turn_off: drum_wash_pump
- if:
condition:
and:
- binary_sensor.is_on: drum_wash_low_level_switch
- binary_sensor.is_on: drum_low_level_switch
then:
- binary_sensor.template.publish:
id: drum_empty
state: ON
- binary_sensor.template.publish:
id: drum_filter_recovery_mode
state: ON
- binary_sensor.template.publish:
id: enable_water_fill
state: OFF
- switch.turn_on: water_fill_valve
- platform: gpio
pin:
number: GPIO39
mode: INPUT_PULLUP
name: "Manual Water Fill"
id: manual_water_fill
filters:
- invert:
on_click:
- min_length: 1s
max_length: 2s
then:
- script.execute: do_water_change
- min_length: 3s
max_length: 5s
then:
- switch.turn_on: water_fill_valve
on_press:
then:
- switch.toggle: water_fill_valve
- platform: gpio
pin:
pcf8574: expander_1
number: 1
mode: INPUT
inverted: False
name: "Ozone air toggle"
id: ozone_air_toggle
on_press:
then:
- switch.toggle: ozone_air
- platform: gpio
pin:
pcf8574: expander_2
number: 0
mode: INPUT
inverted: False
name: "pond control restart"
on_press:
then:
- switch.toggle: restart_pond_control
- platform: gpio
pin:
pcf8574: expander_2
number: 1
mode: INPUT
inverted: False
name: "Fish feeder PB"
on_press:
then:
- switch.turn_on: fish_feeder
on_release:
then:
- switch.turn_off: fish_feeder
- platform: status
name: "Pond control"
### Binary sensors to HA ###
- platform: template
name: "Water change in progress"
id: water_change_in_progress_binary
- platform: template
name: "Drum wash in progress"
id: drum_wash_in_progress
- platform: template
name: "Drum filter in recovery mode"
id: drum_filter_recovery_mode
on_press:
then:
- script.execute: do_recovery_first_drum_wash
- platform: template
name: "Enable water fill"
id: enable_water_fill
- platform: template
name: "Drum empty"
id: drum_empty
- platform: template
name: "Pond control has restarted"
id: pond_control_restarted
### Binary sensors from HA ###
- platform: homeassistant
name: "Manual drum wash"
entity_id: input_boolean.manual_drum_wash
id: manual_drum_wash
on_press:
then:
- if:
condition:
- binary_sensor.is_off: drum_filter_recovery_mode
then:
- script.execute: do_drum_wash
- platform: homeassistant
name: "Manual spindrifter off"
entity_id: input_boolean.manual_spindrifter_off
id: manual_spindrifter_off
on_press:
then:
- script.execute: do_turn_off_spindrifter_and_skimmer
- platform: homeassistant
name: "Manual water change"
entity_id: input_boolean.manual_water_change
id: manual_water_change
on_press:
then:
- script.execute: do_water_change
- platform: homeassistant
name: "Manual cancel water change"
entity_id: input_boolean.manual_cancel_water_change
id: manual_cancel_water_change
- platform: homeassistant
name: "Disable heron scarer"
entity_id: input_boolean.disable_heron_scarer
id: disable_heron_scarer
- platform: homeassistant
name: "Disable spindrifter IR"
entity_id: input_boolean.disable_spindrifter_ir
id: disable_spindrifter_ir
- platform: homeassistant
name: "Disable drum wash"
entity_id: input_boolean.disable_drum_wash
id: disable_drum_wash
### Sensors ###
sensor:
- platform: dallas
address: 0x570119279E6EDF28
name: "Pond Water Temperature"
id: pond_water_temperature
icon: mdi:temperature-celsius
- platform: dallas
address: 0x7301192788034C28
name: "Pond Air Temperature"
id: pond_air_temperature
icon: mdi:temperature-celsius
- platform: integration
name: "Water change rate"
id: pond_water_change
accuracy_decimals: 0
sensor: water_meter_pulse_counter
time_unit: min
- platform: pulse_counter
pin: GPIO34
name: "Water meter"
id: water_meter_pulse_counter
accuracy_decimals: 0
update_interval: 60s
unit_of_measurement: 'litres'
### Values from Home Assistant ###
- platform: homeassistant
name: "Water change amount"
entity_id: sensor.water_change_amount
id: water_change_amount
on_value:
then:
- globals.set:
id: water_change_amount_variable
value: !lambda 'return x;'
- platform: homeassistant
name: "Drum wash timer"
entity_id: sensor.drum_wash_timer
id: drum_wash_timer
on_value:
then:
- globals.set:
id: drum_wash_timer_variable
value: !lambda 'return x;'
- platform: homeassistant
name: "Spindrifter off timer"
entity_id: sensor.spindrifter_off_timer
id: spindrifter_off_timer
on_value:
then:
- globals.set:
id: spindrifter_off_timer_variable
value: !lambda 'return x;'
- platform: homeassistant
name: "Heron scarer on timer"
entity_id: sensor.heron_scarer_on_timer_2
id: heron_scarer_on_timer
on_value:
then:
- globals.set:
id: heron_scarer_on_timer_variable
value: !lambda 'return x;'
### Scripts ###
script:
- id: do_water_change
then:
- sensor.integration.reset: pond_water_change
- if:
condition:
switch.is_on: water_fill_valve
then:
- binary_sensor.template.publish:
id: water_change_in_progress_binary
state: ON
else:
- binary_sensor.template.publish:
id: water_change_in_progress_binary
state: ON
- switch.turn_on: water_fill_valve
- wait_until:
condition:
or:
- lambda: 'return id(pond_water_change).state >= id(water_change_amount_variable);'
- binary_sensor.is_on: manual_cancel_water_change
- switch.turn_off: water_fill_valve
- binary_sensor.template.publish:
id: water_change_in_progress_binary
state: OFF
- id: do_drum_wash
then:
- switch.turn_on: drum_motor
- switch.turn_on: drum_wash_pump
- binary_sensor.template.publish:
id: drum_wash_in_progress
state: ON
- delay: !lambda 'return id(drum_wash_timer_variable) * 1000;'
- switch.turn_off: drum_motor
- switch.turn_off: drum_wash_pump
- binary_sensor.template.publish:
id: drum_wash_in_progress
state: OFF
- id: do_recovery_first_drum_wash
then:
- switch.turn_on: drum_motor
- switch.turn_on: drum_wash_pump
- delay: !lambda 'return id(drum_wash_timer_variable) * 2000;'
- switch.turn_off: drum_motor
- switch.turn_off: drum_wash_pump
- id: do_recovery_drum_wash
then:
- switch.turn_on: drum_motor
- switch.turn_on: drum_wash_pump
- delay: !lambda 'return id(drum_wash_timer_variable) * 1000;'
- switch.turn_off: drum_motor
- switch.turn_off: drum_wash_pump
- id: do_turn_off_spindrifter_and_skimmer
then:
- switch.turn_off: spindrifter_air
- switch.turn_off: skimmer_pump
- delay: !lambda 'return id(spindrifter_off_timer_variable) * 1000;'
- switch.turn_on: spindrifter_air
- switch.turn_on: skimmer_pump
- id: do_turn_on_heron_scarer
then:
- if:
condition:
- binary_sensor.is_off: disable_heron_scarer
then:
- switch.turn_on: heron_scarer
- delay: !lambda 'return id(heron_scarer_on_timer_variable) * 1000;'
- switch.turn_off: heron_scarer
interval:
- interval: 10s
then:
- if:
condition:
wifi.connected:
then:
- switch.turn_on: wifi_connected_led
else:
- switch.turn_off: wifi_connected_led
Have you got this hardwired on set up on a breadboard? I experienced some random on/off changes whilst breadboard. All went away once hardwired.
Do the logs show the output being switched?
ashscott
(Ash)
November 6, 2020, 1:18pm
6
From your diagram it looks like you are powering the relays from the ESP32. This is not good!
Do you have a link for that board?
ashscott
(Ash)
November 6, 2020, 1:25pm
7
Here’s a jpg of the circuit:
Hi Ashscott! First of all thanks for your comments on our setup and sorry for responsing just now!
Currently we’re using a breadboard like wire style. the ESP we’re using is the esp32 devkit1 36 pins (layout) . The logs shows the output being switched continously, yes.
Another issue we experience is that we run out of I/O ports (didnt overtought the design) for other devices rather than relais. We’re running into more issues as we’re trying to improve(??) our design.
Therefor your setup you mention in your first post would be really helpful and solve all our problems.
Is it possible for you to send us your KiCad files so we try to make a print for our own?
ashscott
(Ash)
November 16, 2020, 9:39am
9
Sure. Let me know where to send the download link.
Thanks very much! You may send the files to [email protected] .
Do you use a specific program to convert/print the kicad files?
elmo2002
(elmo2002)
September 28, 2023, 7:31pm
12
Hi Ashscott
I know ow this is an old thread, but do you still happen to have the files that you could share? This is exactly what I am currently doing with 3 separate esp32s so would like to combine them.
Many thanks
ashscott
(Ash)
September 28, 2023, 8:37pm
13
I’ll need to have a look. I’ll get back to you.
Send me a PM and I’ll add it to my list.