Irrigation scheduler

i understand. I’m not trying to be mean to you or make things hard but I just don’t believe that doing it for you or giving you the code to copy and paste is actually helping you at all. I’m happy to help you, help yourself. I’m happy to take the time and work on it with you but you need to post whatever you’re trying and i’ll work through it with you. A lot of what you are doing here is basic stuff and it’s stuff that you’re going to need to use for a lot of projects and you should really have an understanding of the basics if you want to keep doing projects. You need to post what you have and the errors. Errors can be as simple as simple spacing errors and you need to shift some things around with the space bar or the backspace key. Errors aren’t a reason to delete it all and look for all new code to copy and paste. If you read the error, it tells what the error is and where it is at, it’s not a reason to abandon everything.
post what you have and the errors.

I completely agree with you, in fact I don’t think and I don’t want to get a code already written and working, as I intend to create many projects with ESPHome in the future, however I wouldn’t know where to start to start understanding the basics of programming in YAML . I’ve searched for numerous tutorials on the net but it’s all extremely confusing, with guides they start explaining one thing and then they put a lot of in-depth links that do nothing but create total confusion in my head that makes me discourage. I have been using Arduino for years and I have a basic knowledge of C++ and I have always found clear guides, tutorials and insights on the subject that have allowed me to create many projects independently. However, as I said earlier, all the guides I found to be able to start this project didn’t give me anything understandable.

I will try to write a code to the best of my ability and then I will post it maybe including comments to explain the logic behind my code and point out the errors!

I totally understand where your coming from. If your code is crap and full of errors that’s ok! like i said, i’m happy to help you. All that i ask is you try. First you need to set up a basic sprinkler config. If we look at the documentation there are several examples so lets just start there. It doesn’t need to be complete and working perfectly but see what you can do.

this might seem like overkill for what your doing but this allows you to easily add new valves, zones, customize times and settings for each valve and zone if you decide you want to add more later. Using this from the start gives you a huge advantage because you won’t need to rebuild the whole system and redo the code later. You can simply just copy and paste one of your valves and timers that you already have and rename them. This is very flexible with what you can do with it.

I will definitely take the time to delve into this guide over the weekend. If I may ask you something in the meantime, I don’t understand why pumps and valves must both necessarily be entered in the code as shown in the guide…

They do not. It is only in case you have a valve/switch for pump that you would like to turn on prior to irrigation start.
For instance, here is my code for my 8ch esp8266 board. I am using 5 relays (as I have 5 zones, 2 for lawn, 1 for field and 2 for drippers). I have defined switches by GPIO and before was operating just switches from HA. However I like the overlap feature, so when I start cycle,zones that are enabled cycle one after another with 5s overlap (so the pump is constantly working instead of stopping and starting in few seconds/minutes again).
Before, I was using one of irrigation controls from HACS, but bad thing was that most of configuration could be done from yaml only which isn’t very friendly. Also each on/off operation was executed from HA. So in case your HA died, you would be watering forever :slight_smile: I did have workaround for that - within ESPHome I have set maximum time that I never exceed, for instance:

switch:
  - platform: gpio
    pin: GPIO16
    name: "Drippers Corner"
    icon: "mdi:water"
    id: relay1
    on_turn_on:
    - delay: 3600s
    - switch.turn_off: relay1

This ensures that relay turns off after 1 hour no matter what - but I usually run it for shorter amount of time, so this is just worst-case-fallback.
This whole sprinkler controller in ESP has a benefit that code and operations run on ESPHome board (not from HA) - so even if HA dies after you started it, it will turn off after defined time because board will take care of it.

So below my full config:

esphome:
  name: gardenwatering8ch

esp8266:
  board: esp12e
  early_pin_init: false

# Enable logging
logger:

#web_server:
#  port: 80

# Enable Home Assistant API
api:
  services:
    - service: set_multiplier
      variables:
        multiplier: float
      then:
        - sprinkler.set_multiplier:
            id: irrigation_controller
            multiplier: !lambda 'return multiplier;'
    - service: start_full_cycle
      then:
        - sprinkler.start_full_cycle: irrigation_controller
    - service: start_single_valve
      variables:
        valve: int
      then:
        - sprinkler.start_single_valve:
            id: irrigation_controller
            valve_number: !lambda 'return valve;'
    - service: next_valve
      then:
        - sprinkler.next_valve: irrigation_controller
    - service: previous_valve
      then:
        - sprinkler.previous_valve: irrigation_controller
    - service: shutdown
      then:
        - sprinkler.shutdown: irrigation_controller
    - service: start_queue
      then:
        - sprinkler.start_from_queue: irrigation_controller
    - service: pause
      then:
        - sprinkler.pause: irrigation_controller
    - service: resume
      then:
        - sprinkler.resume: irrigation_controller

ota:
  password: xxx

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

  # Enable fallback hotspot (captive portal) in case wifi connection fails
  ap:
    ssid: xxx
    password: xxx

captive_portal:

switch:
  - platform: gpio
    pin: GPIO16
    name: "Drippers Corner"
    icon: "mdi:water"
    id: relay1
  - platform: gpio
    pin: GPIO14
    name: "Lawn South"
    icon: "mdi:grass"
    id: relay2
  - platform: gpio
    pin: GPIO12
    name: "Field"
    icon: "mdi:carrot"
    id: relay3
  - platform: gpio
    pin: GPIO13
    name: "Lawn West"
    icon: "mdi:grass"
    id: relay4
  - platform: gpio
    pin: GPIO15
    name: "Drippers House"
    icon: "mdi:water"
    id: relay5
  - platform: gpio
    pin: GPIO00
    name: Relay6
    id: relay6
  - platform: gpio
    pin: GPIO04
    name: Relay7
    id: relay7
  - platform: gpio
    pin: GPIO05
    name: Relay8
    id: relay8

sprinkler:
  - id: irrigation_controller
    main_switch: "Irrigation Cycle Start"
    auto_advance_switch: "Irrigation Auto Advance"
    standby_switch: "Irrigation Standby Switch"
    multiplier_number: "Lawn Sprinkler Multiplier"
    repeat_number: "Lawn Sprinkler Repeat"
    valve_overlap: 5s
    valves:
      - valve_switch: "Irrigation Drippers House"
        enable_switch: "Enable Irrigation Drippers House"
        run_duration_number:
          id: irrigation_drippers_house_run_duration
          name: "Irrigation Drippers House Duration"
          initial_value: 60
          max_value: 90
          unit_of_measurement: min
        valve_switch_id: relay5
      - valve_switch: "Irrigation Drippers Corner"
        enable_switch: "Enable Irrigation Drippers Corner"
        run_duration_number:
          id: irrigation_drippers_corner_run_duration
          name: "Irrigation Drippers Corner Duration"
          initial_value: 60
          max_value: 90
          unit_of_measurement: min
        valve_switch_id: relay1 
      - valve_switch: "Irrigation Field"
        enable_switch: "Enable Irrigation Field"
        run_duration_number:
          id: irrigation_field_run_duration
          name: "Irrigation Field Duration"
          initial_value: 25
          max_value: 45
          unit_of_measurement: min
        valve_switch_id: relay3  
      - valve_switch: "Irrigation Lawn South"
        enable_switch: "Enable Irrigation Lawn South"
        run_duration_number:
          id: irrigation_lawn_south_run_duration
          name: "Irrigation Lawn South Duration"
          initial_value: 15
          max_value: 30
          unit_of_measurement: min
        valve_switch_id: relay2 
      - valve_switch: "Irrigation Lawn West"
        enable_switch: "Enable Irrigation Lawn West"
        run_duration_number:
          id: irrigation_lawn_west_run_duration
          name: "Irrigation Lawn West Duration"
          initial_value: 15
          max_value: 30
          unit_of_measurement: min
        valve_switch_id: relay4

sensor:
  - platform: template
    name: "Irrigation Zone Remaining Time"
    icon: mdi:progress-clock    
    unit_of_measurement: 'Min'
    accuracy_decimals: 0
    update_interval: 10s   
    lambda: |-
      if (id(irrigation_controller).time_remaining_active_valve().has_value())
      {
        return id(irrigation_controller).time_remaining_active_valve().value() / 60;
      }
      else
      {
        return 0;
      }

I am still struggling to figure out times (remaining on all enabled, the only one that works is remaining time on zone). Anyone could advise how can I achieve it? I would like to see at least remaining time on cycle (currently enabled valves?)

Are you talking about a full cycle time remaining? So if zones 1-2 have completed then you want time remaining for 3,4,5?

Yes. Docs say how to get it, but I was unable to “copy” my only sensor for remaining time on zone and just adjusting different values. Got some errors if I did it.

Several methods are available for this purpose:

uint32_t total_cycle_time_all_valves()

uint32_t total_cycle_time_enabled_valves()

uint32_t total_cycle_time_enabled_incomplete_valves()

uint32_t total_queue_time()

optional<uint32_t> time_remaining_active_valve()

optional<uint32_t> time_remaining_current_operation()

Note that, as with several of the earlier examples, the time_remaining_... methods each return an optional type. If the optional returned has_value(), a valve is active/running; if it does not has_value(), no valve is active, meaning the controller is idle.

OK, I think I have figured it out:

sensor:
  - platform: template
    name: "Irrigation Zone Remaining Time"
    id: time_remaining_active_valve
    icon: mdi:progress-clock    
    device_class: duration
    unit_of_measurement: min
    update_interval: 2s   
    lambda: |-
      if (id(irrigation_controller).time_remaining_active_valve().has_value())
      {
        return id(irrigation_controller).time_remaining_active_valve().value() / 60;
      }
      else
      {
        return 0;
      }

  - platform: template
    name: "Irrigation Total Cycle Time All Valves"
    id: total_cycle_time_all_valves
    icon: mdi:progress-clock    
    device_class: duration
    unit_of_measurement: min
    update_interval: 2s  
    lambda: |-
      return id(irrigation_controller).total_cycle_time_all_valves();

  - platform: template
    name: "Irrigation Total Cycle Time Enabled Valves"
    id: total_cycle_time_enabled_valves
    icon: mdi:progress-clock    
    device_class: duration
    unit_of_measurement: min
    update_interval: 2s  
    lambda: |-
      return id(irrigation_controller).total_cycle_time_enabled_valves();

  - platform: template
    name: "Irrigation Total Cycle Time Incomplete Valves"
    id: total_cycle_time_enabled_incomplete_valves
    icon: mdi:progress-clock    
    device_class: duration
    unit_of_measurement: min
    update_interval: 2s  
    lambda: |-
      return id(irrigation_controller).total_cycle_time_enabled_incomplete_valves();

Which gives me:
image