ESPHome help please, import value for HA and display it on LCD

I am not sure what I am doing wrong, this is my first attempt at ESPHome as I had it almost fully working with Tasmota. I wanted to try something with a tight HA integration… so ESPHome.

My display section:

display:
  - platform: lcd_pcf8574
    dimensions: 16x2
    address: 0x27
    lambda: |-
      it.printf(0,0,"Tank 1 Temp ", id(tank_temp).state);
      // Print the current time
      it.strftime(0,1,"%I:%M%p on %m/%d", id(my_time).now());

My sensor:

sensor:
  - platform: homeassistant
    id: tank_temp
    entity_id: sensor.esp_tank_sht3x_temperature
    internal: false

My sensor in HA

It appears that my sensor is being picked up by ESPHome, snippit from log file:

[20:27:33][C][homeassistant.sensor:030]: Homeassistant Sensor 'tank_temp'
[20:27:33][C][homeassistant.sensor:030]:   State Class: ''
[20:27:33][C][homeassistant.sensor:030]:   Unit of Measurement: ''
[20:27:33][C][homeassistant.sensor:030]:   Accuracy Decimals: 1
[20:27:33][C][homeassistant.sensor:031]:   Entity ID: 'sensor.esp_tank_sht3x_temperature'
[20:28:21][D][homeassistant.sensor:024]: 'sensor.esp_tank_sht3x_temperature': Got state 78.30
[20:28:21][D][sensor:094]: 'tank_temp': Sending state 78.30000  with 1 decimals of accuracy

So, what am I doing wrong? My display shows the following:
Row 0: Tank 1 Temp
Row 2: Time and date formated as expected

I am not sure why it fixed the problem, but adding formatting to the printf fixed the initial problem.

it.printf(0,0,"Tank 1 %.1f", id(tank_temp).state);

But, I just figured out… unlike Tasmota I cannot turn off the display. Tasmota creates a switch for the display. It does not appear that I can do the same for an I2c 1602LCD?

Yes, printf does require a format.

For lighting up see Character-Based LCD Display — ESPHome

So, to run without a motion sensor… would I just use the following? And if so, would I need to assign a GPIO to take high or low to trigger the backlight or would I somehow do it with an input_boolean?

  - platform: template
    id: backlight
    filters:
      - delayed_off: 90s
    on_press:
      then:
        - lambda: |-
            id(mydisplay).backlight();
    on_release:
      then:
        - lambda: |-
            id(mydisplay).no_backlight();

So, I am trying the following:

binary_sensor:
  - platform: homeassistant
    id: tank_backlight
    entity_id: input_boolean.esphome_backlight
    internal: false

  - platform: template
    id: backlight
    filters:
      - delayed_off: 10s
    on_press:
      then:
        - lambda: |-
            if (id(tank_backlight)=on) {
              id(mydisplay).backlight();
            } else: {
              id(mydisplay).no_backlight(); 
            }

The results… not what I want…

INFO ESPHome 2024.3.2
INFO Reading configuration /config/esphome/esphome-web-d05018.yaml...
ERROR Error while reading config: Invalid YAML syntax:

while parsing a block mapping
  in "/config/esphome/esphome-web-d05018.yaml", line 128, column 11
expected <block end>, but found '}'
  in "/config/esphome/esphome-web-d05018.yaml", line 133, column 11

Next try, seems to pass yaml check but bombs during compile. As you can tell, I am not a coder!

My switch state is registering in the ESP.
From units logs when state changes in HA.

[23:27:00][D][homeassistant.binary_sensor:026]: 'input_boolean.esphome_backlight': Got state ON
[23:27:00][D][binary_sensor:036]: 'tank_backlight': Sending state ON
[23:27:09][D][homeassistant.binary_sensor:026]: 'input_boolean.esphome_backlight': Got state OFF
[23:27:09][D][binary_sensor:036]: 'tank_backlight': Sending state OFF
  - platform: template
    id: backlight
    filters:
      - delayed_off: 10s
    on_press:
      then:
        - lambda: |-
            if (id(tank_backlight)=on) {
              id(mydisplay).backlight();
            } else: {
              id(mydisplay).no_backlight(); 
            }
Compiling .pioenvs/esphome_tank_test/src/main.cpp.o
/config/esphome/esphome-web-d05018.yaml: In lambda function:
/config/esphome/esphome-web-d05018.yaml:129:26: error: 'on' was not declared in this scope
             if (id(tank_backlight)=on) {
                          ^~
/config/esphome/esphome-web-d05018.yaml:129:26: note: suggested alternative: 'yn'
             if (id(tank_backlight)=on) {
                          ^~
                          yn
/config/esphome/esphome-web-d05018.yaml:131:13: error: expected primary-expression before ':' token
             } else: {
             ^
*** [.pioenvs/esphome_tank_test/src/main.cpp.o] Error 1

Well, if you want to use lambda’s you need some basics understanding of C++ :slight_smile: There are a lot of free courses to find on the internet…

For now change your code to:

  - platform: template
    id: backlight
    filters:
      - delayed_off: 10s
    on_press:
      then:
        - lambda: |-
            if (id(tank_backlight).state) {
              id(mydisplay).backlight();
            } else: {
              id(mydisplay).no_backlight(); 
            }

besides what Jos already corrected you also have to remove the colon here, it’s C/C++, not Python

1 Like

Guys, sorry for being so dense… it compiles now and loads but does nothing.

I think i can remove the binary_sensor, -platform: gpio section and replace it with my -platform: homeassistant since that is where the “switch” is coming from.

Here is what I have now:

display:
  - platform: lcd_pcf8574
    id: mydisplay
    dimensions: 16x2
    address: 0x27
    lambda: |-
      it.printf(0,0,"Tank 1 %.1fF", id(tank_temp).state);
      // Print the current time
      it.strftime(0,1,"%I:%M%p - %m/%d", id(my_time).now());
      // Result for 10:06 on august 21st 2018 -> "It is 10:06 on 21.08.2018"
      // Print 0 at the top left
      //  it.print("0");
      // Print 1 at the second row and second column.
      //  it.print(1, 1, "1");
  
output:
  - platform: ledc
    id: blue_led
    pin:
      number: GPIO25
      inverted: false
  
  - platform: ledc
    id: green_led
    pin:
      number: GPIO26
      inverted: false
  
  - platform: ledc
    id: red_led
    pin:
      number: GPIO27
      inverted: false
  
light:
  - platform: monochromatic
    name: "Blue LED"
    output: blue_led
    id: blueled

  - platform: monochromatic
    name: "Green LED"
    output: green_led
    id: redled

  - platform: monochromatic
    name: "Red LED"
    output: red_led
    id: greenled

time:
- platform: homeassistant
  id: my_time

sensor:
  - platform: homeassistant
    id: tank_temp
    entity_id: sensor.esp_tank_sht3x_temperature
    internal: false

binary_sensor:
  - platform: homeassistant
    id: tank_backlight
    entity_id: input_boolean.esphome_backlight
    internal: false
  
  - platform: template
    id: backlight
    on_press:
      then:
        - lambda: |-
            if (id(tank_backlight).state) {
              id(mydisplay).backlight();
            } else {
              id(mydisplay).no_backlight(); 
            }

Share the logs, perhaps the display is not detected.
You do have the PCF8574 GPIO expander module as described here Character-Based LCD Display — ESPHome ? How is it wired? You only posted parts of the yaml, the i2c-part seems to be missing?

The display is working, showing time and imported temperature variable.

Sorry, being brief. Visiting 88 yo mom a state away in hospital. Will be back on vpn this evening for more testing. Daughter at home seeing display and watching dogs.

Here are my logs… i2c device found and connections made from HA including an attempt to toggle the backlight a couple of times.

[I][wifi:303]: WiFi Connecting to 'dd-wrt_vap'...
[I][wifi:594]: WiFi Connected!
[C][wifi:408]:   Local MAC: D4:8A:FC:D0:50:18
[C][wifi:413]:   SSID: 'dd-wrt_vap'[redacted]
[C][wifi:416]:   IP Address: 192.168.1.231
[C][wifi:420]:   BSSID: 84:D8:1B:BA:F1:F4[redacted]
[C][wifi:421]:   Hostname: 'esphome_tank_test'
[C][wifi:423]:   Signal strength: -46 dB ▂▄▆█
[C][wifi:427]:   Channel: 1
[C][wifi:428]:   Subnet: 255.255.255.0
[C][wifi:429]:   Gateway: 192.168.1.1
[C][wifi:430]:   DNS1: 192.168.1.7
[C][wifi:431]:   DNS2: 192.168.1.2
[D][wifi:603]: Disabling AP...
[C][web_server:124]: Setting up web server...
[C][ota:096]: Over-The-Air Updates:
[C][ota:097]:   Address: esphome_tank_test.home:3232
[C][ota:103]:   OTA version: 2.
[C][api:025]: Setting up Home Assistant API server...
[I][app:062]: setup() finished successfully!
[W][wifi:165]: Warning cleared
[W][api:152]: Warning set: unspecified
[I][app:102]: ESPHome version 2024.3.2 compiled on Apr 13 2024, 10:16:06
[I][app:104]: Project esphome.web version 1.0
[C][wifi:580]: WiFi:
[C][wifi:408]:   Local MAC: D4:8A:FC:D0:50:18
[C][wifi:413]:   SSID: 'dd-wrt_vap'[redacted]
[C][wifi:416]:   IP Address: 192.168.1.231
[C][wifi:420]:   BSSID: 84:D8:1B:BA:F1:F4[redacted]
[C][wifi:421]:   Hostname: 'esphome_tank_test'
[C][wifi:423]:   Signal strength: -47 dB ▂▄▆█
[C][wifi:427]:   Channel: 1
[C][wifi:428]:   Subnet: 255.255.255.0
[C][wifi:429]:   Gateway: 192.168.1.1
[C][wifi:430]:   DNS1: 192.168.1.7
[C][wifi:431]:   DNS2: 192.168.1.2
[C][logger:166]: Logger:
[C][logger:167]:   Level: DEBUG
[C][logger:169]:   Log Baud Rate: 115200
[C][logger:170]:   Hardware UART: UART0
[C][i2c.arduino:059]: I2C Bus:
[C][i2c.arduino:060]:   SDA Pin: GPIO21
[C][i2c.arduino:061]:   SCL Pin: GPIO22
[C][i2c.arduino:062]:   Frequency: 400000 Hz
[C][i2c.arduino:065]:   Recovery: bus successfully recovered
[I][i2c.arduino:075]: Results from i2c bus scan:
[I][i2c.arduino:081]: Found i2c device at address 0x27
[C][ledc.output:164]: LEDC Output:
[C][ledc.output:165]:   Pin GPIO25
[C][ledc.output:166]:   LEDC Channel: 0
[C][ledc.output:167]:   PWM Frequency: 1000.0 Hz
[C][ledc.output:168]:   Bit depth: 16
[C][ledc.output:164]: LEDC Output:
[C][ledc.output:165]:   Pin GPIO26
[C][ledc.output:166]:   LEDC Channel: 1
[C][ledc.output:167]:   PWM Frequency: 1000.0 Hz
[C][ledc.output:168]:   Bit depth: 16
[C][ledc.output:164]: LEDC Output:
[C][ledc.output:165]:   Pin GPIO27
[C][ledc.output:166]:   LEDC Channel: 2
[C][ledc.output:167]:   PWM Frequency: 1000.0 Hz
[C][ledc.output:168]:   Bit depth: 16
[C][template.binary_sensor:028]: Template Binary Sensor 'backlight'
[C][light:103]: Light 'Blue LED'
[C][light:105]:   Default Transition Length: 1.0s
[C][light:106]:   Gamma Correct: 2.80
[C][light:103]: Light 'Green LED'
[C][light:105]:   Default Transition Length: 1.0s
[C][light:106]:   Gamma Correct: 2.80
[C][light:103]: Light 'Red LED'
[C][light:105]:   Default Transition Length: 1.0s
[C][light:106]:   Gamma Correct: 2.80
[C][homeassistant.time:010]: Home Assistant Time:
[C][homeassistant.time:011]:   Timezone: 'CST6CDT,M3.2.0,M11.1.0'
[C][lcd_pcf8574:024]: PCF8574 LCD Display:
[C][lcd_pcf8574:025]:   Columns: 16, Rows: 2
[C][lcd_pcf8574:026]:   Address: 0x27
[C][lcd_pcf8574:027]:   Update Interval: 1.0s
[C][esp32_ble:374]: ESP32 BLE:
[C][esp32_ble:376]:   MAC address: D4:8A:FC:D0:50:1A
[C][esp32_ble:377]:   IO Capability: none
[C][esp32_ble_server:200]: ESP32 BLE Server:
[C][esp32_improv.component:261]: ESP32 Improv:
[C][esp32_improv.component:266]:   Status Indicator: 'NO'
[C][captive_portal:088]: Captive Portal:
[C][web_server:169]: Web Server:
[C][web_server:170]:   Address: esphome_tank_test.home:80
[C][mdns:115]: mDNS:
[C][mdns:116]:   Hostname: esphome_tank_test
[C][ota:096]: Over-The-Air Updates:
[C][ota:097]:   Address: esphome_tank_test.home:3232
[C][ota:103]:   OTA version: 2.
[C][api:139]: API Server:
[C][api:140]:   Address: esphome_tank_test.home:6053
[C][api:144]:   Using noise encryption: NO
[C][improv_serial:032]: Improv Serial:
[C][homeassistant.binary_sensor:039]: Homeassistant Binary Sensor 'tank_backlight'
[C][homeassistant.binary_sensor:040]:   Entity ID: 'input_boolean.esphome_backlight'
[C][homeassistant.sensor:030]: Homeassistant Sensor 'tank_temp'
[C][homeassistant.sensor:030]:   State Class: ''
[C][homeassistant.sensor:030]:   Unit of Measurement: ''
[C][homeassistant.sensor:030]:   Accuracy Decimals: 1
[C][homeassistant.sensor:031]:   Entity ID: 'sensor.esp_tank_sht3x_temperature'
[D][api:102]: Accepted 192.168.1.6
[W][api:165]: Warning cleared
[D][api.connection:1159]: Home Assistant 2024.4.3 (192.168.1.6): Connected successfully
[D][time:049]: Synchronized time: 2024-04-13 18:37:03
[D][homeassistant.binary_sensor:026]: 'input_boolean.esphome_backlight': Got state OFF
[D][binary_sensor:034]: 'tank_backlight': Sending initial state OFF
[D][homeassistant.sensor:024]: 'sensor.esp_tank_sht3x_temperature': Got state 78.30
[D][sensor:094]: 'tank_temp': Sending state 78.30000  with 1 decimals of accuracy

Here is the current state of config on the device. I have a feeling it is an id problem, but only guessing. This is an aqurium monitor I am building as I really do not like the units on the market. Tasmota almost works, but getting HA variables into it is a pain and the display is not a friendly. I have not tried ESPeasy, but have used it many times in the past with D1’s, OLEDs and MQTT imports. I may have to try it, but really like the tight integration with HA that ESPHome brings with it.

i2c:
  sda: GPIO21
  scl: GPIO22
  frequency: 400kHz

display:
  - platform: lcd_pcf8574
    id: mydisplay
    dimensions: 16x2
    address: 0x27
    lambda: |-
      it.printf(0,0,"Tank 1 %.1fF", id(tank_temp).state);
      // Print the current time
      it.strftime(0,1,"%I:%M%p - %m/%d", id(my_time).now());
      // Result for 10:06 on august 21st 2018 -> "It is 10:06 on 21.08.2018"
      // Print 0 at the top left
      //  it.print("0");
      // Print 1 at the second row and second column.
      //  it.print(1, 1, "1");
  
output:
  - platform: ledc
    id: blue_led
    pin:
      number: GPIO25
      inverted: false
  
  - platform: ledc
    id: green_led
    pin:
      number: GPIO26
      inverted: false
  
  - platform: ledc
    id: red_led
    pin:
      number: GPIO27
      inverted: false
  
light:
  - platform: monochromatic
    name: "Blue LED"
    output: blue_led
    id: blueled

  - platform: monochromatic
    name: "Green LED"
    output: green_led
    id: redled

  - platform: monochromatic
    name: "Red LED"
    output: red_led
    id: greenled

time:
- platform: homeassistant
  id: my_time

sensor:
  - platform: homeassistant
    id: tank_temp
    entity_id: sensor.esp_tank_sht3x_temperature
    internal: false

binary_sensor:
  - platform: homeassistant
    id: tank_backlight
    entity_id: input_boolean.esphome_backlight
    internal: false
  
  - platform: template
    id: backlight
    on_press:
      then:
        - lambda: |-
            if (id(tank_backlight).state) {
              id(mydisplay).backlight();
            } else {
              id(mydisplay).no_backlight(); 
            }

I am not a C++ programmer, I am a 34 year veteran network and facility engineer that has an adequate knowledge of bash scripting with a little perl and python thrown in. But, we have a herd of programmers at my university that writes our tools and utilities and we worry about networks. I am going to have to start watching tutorials as I really do like ESPHome initially.

From that log i don’t see an attempt to turn the backlight on or off. How are you doing this?

I defined an input_boolean and trigger it from developer tools and from an automation.

Exchange from the ESP logfile:

[19:18:07][D][homeassistant.binary_sensor:026]: 'input_boolean.esphome_backlight': Got state ON
[19:18:07][D][binary_sensor:036]: 'tank_backlight': Sending state ON
[19:18:11][D][homeassistant.binary_sensor:026]: 'input_boolean.esphome_backlight': Got state OFF
[19:18:11][D][binary_sensor:036]: 'tank_backlight': Sending state OFF

I am using this in esphome:

binary_sensor:
  - platform: homeassistant
    id: tank_backlight
    entity_id: input_boolean.esphome_backlight
    internal: false
  
  - platform: template
    id: backlight
    on_press:
      then:
        - lambda: |-
            if (id(tank_backlight).state) {
              id(mydisplay).backlight();
            } else {
              id(mydisplay).no_backlight(); 
            }


in Section “Backlight Control” in Character-Based LCD Display — ESPHome it says:
The jumper on the PCF8574 board needs to be closed for the backlight control to work
don’t have such hardware, thus have no idea what jumper this is about, but maybe worth to check

Armin

Yes I already pointed to that. I assumed that as a result @mattlward would have sorted that. But on reflection, he hasn’t mentioned it.

Yes the jumper is closed. I have tested with 2 different boards, both are somewhat different but both have great information displayed but not backlight control.

Am i doing the switch state import correctly? It almost feels like the state is published to the ESP but is not being acted upon.

So, it dawned on me today while I was mowing that there is not a physical button being pressed to turn of the backlight.

So, I did 2 things to test this problem:

  1. I set up my display to print the state of the binary sensor for the backlight control. Starting at line 13 below/
display:
  - platform: lcd_pcf8574
    id: mydisplay
    dimensions: 16x2
    address: 0x27
    lambda: |-
        //Print tank temperature on row 0
        //it.printf(0,0,"T1=%.1fF", id(tank_temp).state);
        //it.printf(10, 0, "H1=%s", id(tank_heat).state.c_str());
        //it.printf(0, 1, "BL=%", id(tank_backlight).state);
        // Print the current time on row 1
        //it.strftime(0,1,"%I:%M%p %m/%d", id(my_time).now());
        if (id(tank_backlight).state) {
        it.print(0, 0, "state: ON");
        } else {
        it.print(0, 0, "state: OFF");
        }

This did in fact toggle from on to off and back to on with the correct indicators on my display.

  1. I tried to convert the “platform: template” to reflect a state change in the binary sensor as the trigger…
- platform: template
    id: backlight
    on_state:
      then:
          lambda: |-
            if (id(tank_backlight).state) {
            // Binary sensor is on
            id(mydisplay).backlight();
            } else {
            // Binary sensor is off
            id(mydisplay).no_backlight(); 
            }

While I do see the state indicator on the display change, the actual backlight state does not change. I do not think the above lambda is seeing the transition.

Is there a way to poke a value into ESPHome, similar to changing the state of a gpio just to see that it works and is possible to control?

I might be missing something here, but why don’t you just put the code to switch on/off the backlight into the lambda for the display? Where you above have the code to print the state?
Of course there might be a short delay after altering the input in home assistant, before the next update interval, but you are using the 1 second interval ?
Sounds a bit like a workaround as it does not react directly to altering the input… but… might work at least until you figure out a better solution

Ok, so that was so simple! And it works very well.

For others that only know as much about C++ as I do, I am posting my display section.

display:
  - platform: lcd_pcf8574
    id: mydisplay
    dimensions: 16x2
    address: 0x27
    lambda: |-
      //Print tank temperature and heater state on row 0
      it.printf(0,0,"T1=%.1fF", id(tank_temp).state);
      it.printf(10, 0, "H1=%s", id(tank_heat).state.c_str());
      // Print the current time on row 1
      it.strftime(0,1,"%I:%M%p %m/%d", id(my_time).now());
      if (id(tank_backlight).state) {
      // Binary sensor is on
      // Control backlight on mydisplay
      // Binary sensor is on in HA
      id(mydisplay).backlight();
      } else {
      // Binary sensor is off in HA
      id(mydisplay).no_backlight(); 
      }
1 Like