Displaying System Status to LCD

I have managed to setup my sprinkler system but I am having issues trying to display the status of the sprinkler on the LCD.

I have tried multiple threads relating to displaying of sensors but it seems none of them seem to be working.

This is the code I currently have:

# Based on ESPHome Sprinkler Controller - https://esphome.io/components/sprinkler.html
# Change Log
# 2025 01 01 - Initial Compilation

esp32:
  board: esp32dev
  framework:
    type: arduino



# Establish Substitutions
substitutions:
### Modify only the following 6 lines.
  zone_1_name: Front Garden Dripper
  zone_2_name: Front Garden Sprinkler
#  zone_3_name: 
#  zone_4_name: Drip Lane B
  software_version: 2023 05 10 V07
  sensor_update_frequency: 1s
  log_level: debug # Enable levels logging https://esphome.io/components/logger.html
  # none, error, warn, info, debug (default), verbose, very_verbose
##############################################
#  DO NOT CHANGE ANYTHING BELOW THIS LINE  ###
##############################################
  zone_1_valve_id: valve_0
  zone_2_valve_id: valve_1
#  zone_3_valve_id: valve_2
  esphome_name: irrigation
  esphome_platform: espressif32
  esphome_board: esp32dev
  esphome_comment: Irrigation Control
  esphome_project_name: JAYA.Three Valve Irrigation Control
  esphome_project_version: Irrigation Controller, $software_version
  devicename: irrigation_controller
  upper_devicename: "Irrigation Controller"


#Define Project Deatils and ESP Board Type
esphome:
  name: $esphome_name
  comment: $esphome_comment
  project:
    name: $esphome_project_name
    version: $esphome_project_version
  on_boot:
    priority: -100
    then:
      # Set default state for Valve Status
      - text_sensor.template.publish:
          id: valve_status
          state: "Idle"
      # Set multiplier to 60, convert seconds to minutes
      - sprinkler.set_multiplier:
          id: $devicename
          multiplier: 60
wifi:
  ssid:
  password: 

# Enable fallback hotspot (captive portal) in case wifi connection fails
  ap:
    ssid: 
    password:
  
logger:
  level: ${log_level}
  logs:
    text_sensor: WARN
  
ota:
  - platform: 
    password: 


# Enable Web server.
web_server:
  port: 80

# Sync time with Home Assistant.
time:
  - platform: homeassistant
    id: homeassistant_time

# LCD Display
i2c:
  sda: GPIO21
  scl: GPIO22

display:
  - platform: lcd_pcf8574
    id: irrigation_display
    dimensions: 20x4
    address: 0x27
    lambda: |-
      it.print(0,0, "${esphome_comment}");
      it.strftime(0,1," %H:%M %d-%b-%Y", id(homeassistant_time).now());
      it.printf(0,2, "System Status: %s", id(valve_status).state ? "True" : "False");

###############################################
# Enable Home Assistant API
###############################################
api:
  encryption:
    key: 

###############################################
# Binary Sensor.
###############################################
binary_sensor:
  - platform: homeassistant
    # prevent deep sleep - Needs further investigation on usefullness
    id: prevent_deep_sleep
    name: "$upper_devicename Prevent Deep Sleep"
    entity_id: input_boolean.prevent_deep_sleep  

###############################################
# Text sensors with general information.
###############################################
text_sensor:
  - platform: version # Expose ESPHome version as sensor.
    name: $esphome_name ESPHome Version
    hide_timestamp: false
  - platform: wifi_info
    ip_address:
      name: "$esphome_name IP"
    ssid:
      name: "$esphome_name SSID"
    bssid:
      name: "$esphome_name BSSID"
  
# Expose Time Remaining as a sensor.
  - platform: template
    id: time_remaining
    name: $upper_devicename Time Remaining
    update_interval: $sensor_update_frequency
    icon: "mdi:timer-sand"
    lambda: |-
      int seconds = round(id($devicename).time_remaining_active_valve().value_or(0));
      int days = seconds / (24 * 3600);
      seconds = seconds % (24 * 3600);
      int hours = seconds / 3600;
      seconds = seconds % 3600;
      int minutes = seconds /  60;
      seconds = seconds % 60;
        return {
          ((days ? String(days) + "d " : "") + 
          (hours ? String(hours) + "h " : "") +
          (minutes ? String(minutes) + "m " : "") +
          (String(seconds) + "s")).c_str()};


  # Expose Progress Percent as a sensor.
  - platform: template
    id: progress_percent
    name: $upper_devicename Progress %
    update_interval: $sensor_update_frequency
    icon: "mdi:progress-clock"
    lambda: |-
      int progress_percent = round(((id($devicename).valve_run_duration_adjusted(id($devicename).active_valve().value_or(0)) - id($devicename).time_remaining_active_valve().value_or(0)) * 100 / id($devicename).valve_run_duration_adjusted(id($devicename).active_valve().value_or(0))));
      std::string progress_percent_as_string = std::to_string(progress_percent);
      return progress_percent_as_string +"%";

  # Expose Valve Status as a sensor.
  - platform: template
    id: valve_status
    name: $upper_devicename Status
    update_interval: never
    icon: "mdi:information-variant"

  - platform: template # Expose the board type as a sensor
    id: espboard_type
    icon: "mdi:developer-board"
    name: $esphome_name ESPBoard
    lambda: |-
      return to_string("${esphome_board}");

# https://esphome.io/devices/nodemcu_esp8266.html
# Enable On-Board Status LED.
status_led:
  pin:
    # Pin D2 / GPIO4
    number: GPIO04
    inverted: false

sensor:
  # Uptime sensor.
  - platform: uptime
    name: $upper_devicename Uptime

  # WiFi Signal sensor.
  - platform: wifi_signal
    name: $upper_devicename WiFi Signal
    update_interval: 60s

###############################################
# Configuration to set multiplier via number 
############################################### 
number:
  - platform: template
    id: $zone_1_valve_id
    name: $zone_1_name
    min_value: 1
    max_value: 60
    step: 1
    unit_of_measurement: min
    icon: "mdi:timer-outline"
    mode: box # Defines how the number should be displayed in the UI
    lambda: "return id($devicename).valve_run_duration(0);"
    set_action:
      - sprinkler.set_valve_run_duration:
          id: $devicename
          valve_number: 0
          run_duration: !lambda 'return x;'
  - platform: template
    id: $zone_2_valve_id
    name: $zone_2_name
    min_value: 1
    max_value: 60
    step: 1
    unit_of_measurement: min
    icon: "mdi:timer-outline"
    mode: box # Defines how the number should be displayed in the UI
    lambda: "return id($devicename).valve_run_duration(1);"
    set_action:
      - sprinkler.set_valve_run_duration:
          id: $devicename
          valve_number: 1
          run_duration: !lambda 'return x;'
#  - platform: template
#    id: $zone_3_valve_id
#    name: $zone_3_name
#    min_value: 1
#    max_value: 60
#    step: 1
#    unit_of_measurement: $uom
#    icon: "mdi:timer-outline"
#    mode: box # Defines how the number should be displayed in the UI
#    lambda: "return id($devicename).valve_run_duration(2);"
#    set_action:
#      - sprinkler.set_valve_run_duration:
#          id: $devicename
#          valve_number: 2
#          run_duration: !lambda 'return x;'


###############################################
# Main Sprinkler Controller
###############################################
sprinkler:
  - id: $devicename
    main_switch:
      name: "Start/Stop/Resume"
      id: main_switch
    auto_advance_switch: "Auto Advance"
    valve_open_delay: 2s
    valves:
      - valve_switch: $zone_1_name
        enable_switch: Enable $zone_1_name
        pump_switch_id: sprinkler_pump
        run_duration: 10s #Note: This value is not seconds but is converted to minutes
        valve_switch_id: ${devicename}_1
      - valve_switch: $zone_2_name
        enable_switch: Enable $zone_2_name
        pump_switch_id: sprinkler_pump 
        run_duration: 15s #Note: This value is not seconds but is converted to minutes
        valve_switch_id: ${devicename}_2
#      - valve_switch: $zone_3_name
#        enable_switch: Enable $zone_3_name
#        run_duration: 15s
#        valve_switch_id: ${devicename}_3
#      - valve_switch: $zone_4_name
#        enable_switch: Enable $zone_4_name
#        run_duration: 15s
#        valve_switch_id: ${devicename}_4
  
button:
  - platform: template
    id: sprinkler_pause
    name: "Pause"
    icon: "mdi:pause"
    on_press:
      then:
        - text_sensor.template.publish:
            id: valve_status
            state: "Paused"
        - sprinkler.pause: $devicename


####################################################
# Switch Control to restart the irrigation system.   
####################################################
switch:
  - platform: restart
    name: "Restart $devicename"

  - platform: gpio
    name: Borehole Pump
    restore_mode: RESTORE_DEFAULT_OFF
    id: sprinkler_pump
    pin: GPIO27
    inverted: true
   

# Switch for the NTC https://esphome.io/components/sensor/ntc.html, Prevent self heating by switching the voltage on a GPIO
#  - platform: gpio
#   pin: 
#      number: GPIO5 #GPIO16 # Pin D0
#      inverted: false
#    id: ntc_vcc

####################################################
# Hidden I/O  Switches to control irrigation valve relays
####################################################
  - platform: gpio
    name: Relay Board Pin IN1
    restore_mode: RESTORE_DEFAULT_OFF # Prevents GPIO pin from going high during boot
    internal: true # Prevents GPIO switch NAME from showing up in Home Assistant
    id: ${devicename}_1
    on_turn_on:
      - text_sensor.template.publish:
          id: valve_status
          state: "$zone_1_name Active"
    on_turn_off:
      - text_sensor.template.publish:
          id: valve_status
          state: "Idle"
    pin: GPIO26 #D26
    inverted: true
  - platform: gpio
    name: Relay Board Pin IN2
    restore_mode: RESTORE_DEFAULT_OFF # Prevents GPIO pin from going high during boot
    internal: true # Prevents GPIO switch NAME from showing up in Home Assistant
    id: ${devicename}_2
    on_turn_on:
      - text_sensor.template.publish:
          id: valve_status
          state: "$zone_2_name Active"
    on_turn_off:
      - text_sensor.template.publish:
          id: valve_status
          state: "Idle"
    pin: GPIO25 # D25
    inverted: true
#  - platform: gpio
#    name: Relay Board Pin IN3
#    restore_mode: RESTORE_DEFAULT_OFF # Prevents GPIO pin from going high during boot
#    internal: true # Prevents GPIO switch NAME from showing up in Home Assistant
#    id: ${devicename}_3
#    on_turn_on:
#      - text_sensor.template.publish:
#          id: valve_status
#          state: "$zone_3_name Active"
#    on_turn_off:
#      - text_sensor.template.publish:
#          id: valve_status
#          state: "Off"
#    pin: GPIO27 # D27
#    inverted: true
#  - platform: gpio
#    name: Relay Board Pin IN4
#    restore_mode: RESTORE_DEFAULT_OFF # Prevents GPIO pin from going high during boot
#    internal: true # Prevents GPIO switch NAME from showing up in Home Assistant
#    id: ${devicename}_4
#    on_turn_on:
#      - text_sensor.template.publish:
#          id: valve_status
#          state: "$zone_4_name Active"
#    on_turn_off:
#      - text_sensor.template.publish:
#          id: valve_status
#          state: "Idle"
#    pin: GPIO15 # D8
#    inverted: true

From the error code I understand it cannot convert vale_status but I am not sure how to fix this.

Mind to share? :thinking:

/config/esphome/irrigation.yaml: In lambda function:
/config/esphome/irrigation.yaml:98:57: error: could not convert 'valve_status->esphome::template_::TemplateTextSensor::<anonymous>.esphome::text_sensor::TextSensor::state' from 'std::__cxx11::string' {aka 'std::__cxx11::basic_string<char>'} to 'bool'
       it.printf(0,2, "System Status: %s", id(valve_status).state ? "True" : "False");
                                           ~~~~~~~~~~~~~~^~~~~
*** [.pioenvs/irrigation/src/main.cpp.o] Error 1

id(valve_status).state is a string. If the string is either the character 0 or 1 then I would change the comparison to:

id(valve_status).state == "1" ? "True" : "False"

If it’s something else, you need to know what string represents True and use that in the comparison.

1 Like

Thanks, this helped in printing to the lcd but using either 1 and 0, the lcd prints False.

Step in the right direction though but as recommended, I’m going to have a look at what the string values are for each state.

And what you get out with:
it.printf(0,2, “System Status: %s”, id(valve_status).state.c_str());

ps. I didn’t read your whole code…

Just get a blank after System Status:

There must be something in the code I am not seeing but essentially thought it was as simple as printing “valve_status” as the following code pushes the correct status to HA.

  # Expose Valve Status as a sensor.
  - platform: template
    id: valve_status
    name: $upper_devicename Status
    update_interval: never
    icon: "mdi:information-variant"

image

I expect this is printing pretty much everything on top of each other.
try
0,0
0,20
0,40