Only seeing "NAN" on display instead of sensor value

I’ve been at this for awhile and I just can’t figure it out. I have a sensor in Home Assistant called sensor.keg_quarter_percent_remaining. The sensor is a float and shows a percentage. I am trying to display this value on an OLED on an ESPHome device. Whenever I try and display any sensors, I am just seeing “NAN” on the display. Not sure why this is:

#...initial core code above...

# Enable I2C bus for OLED display
i2c:
  sda: D2
  scl: D1
  scan: True

font:
  - file: 'slkscr.ttf'
    id: font1
    size: 20


# Declare the sensor component
sensor:
  - platform: homeassistant
    id: keg_quarter_percent_remaining
    entity_id: sensor.keg_quarter_percent_remaining
    internal: True


# Declare the OLED display component
display:
  - platform: ssd1306_i2c
    model: "SSD1306 128x64"
    address: 0x3C
    id: oled_display
    lambda: |-
      it.printf(0, 0, id(font1), "Data: %f", id(keg_quarter_percent_remaining).state);
      it.printf(0, 20, id(font1), "%.1f%%", id(keg_quarter_percent_remaining).state);

Ideally, I would like to show data from sensorA by default but if I enable a toggle (e.g. input_boolean.quaterkeg ) then it shows data from sensorB instead. At this point though, I can’t even get a single sensor to display properly so I’m trying to figure that out first.

Edit: Here are a look at the sensors I am using which are templates from another ESPHome device:
image

Here is the template where the sensor gets populated by:

  - platform: template
    sensors:
      keg_quarter_percent_remaining:
        friendly_name: "Keg Quarter Percent Remaining"
        unique_id: keg_quarter_percent_remaining_sensor
        value_template: "{{ (states('sensor.keg_quarter_liquid_weight') | float / 1040) * 100 | round(0) }}"
        unit_of_measurement: "%"
        

Any help is greatly appreciated. Thank you

What does your ESPHome log say? Can you see the sensor being populated there?

I think so? I don’t have anything else similar to compare it to unfortunately to know what to look for:

[22:27:49][C][homeassistant.sensor:030]: Homeassistant Sensor 'keg_quarter_percent_remaining'
[22:27:49][C][homeassistant.sensor:030]:   State Class: ''
[22:27:49][C][homeassistant.sensor:030]:   Unit of Measurement: ''
[22:27:49][C][homeassistant.sensor:030]:   Accuracy Decimals: 1
[22:27:49][C][homeassistant.sensor:031]:   Entity ID: 'sensor.keg_quarter_percent_remaining'

I use text sensors - but numeric should be fine. For example:

text_sensor:
  - platform: homeassistant
    name: "Pressure MSL hPa"
    entity_id: sensor.atmospheric_pressure_msl
    id: pressure

And in the log, when the value changes, I see:

[13:31:05][D][homeassistant.text_sensor:017]: 'sensor.atmospheric_pressure_msl': Got state '1026.7'

Note that the value will populate on startup, but it then won’t update until it changes in HA, so if it doesn’t change it won’t get logged. Force the value to change somehow and make sure the ESPHome log updates.

Thanks for the help here. Hrm, yeah, I just changed the value twice and the log didn’t move. It is using the same secrets as the other ESPHome devices I have and connects to the WiFi successfully. Not sure what the problem could be why its not reading the value from Home Assistant… Is there a way to verify connectivity otherwise?

I assume you are getting the log via network? if so you have connectivity. You would get an error if api: wasn’t defined properly.

Maybe try it as a text sensor and see if the result differs.

Right, the logs are from wireless.

Just changed sensor to text_sensor and rather than “NAN” on the OLED I now get “0.00000000”. I still don’t see anything changing in the logs though. Not sure if this is helpful or not

Out of ideas… It’s probably something obvious we are missing. Maybe change the ESPHome sensor name so it doesn’t match the HA one? Clutching at straws here.

Try using %s rather than %f in your printf statement, just to confirm whether the value is on the device but it can’t convert it to a float.

Another idea if you still didn’t solve the issue: try this for your sensor:

- platform: template
    sensors:
      keg_quarter_percent_remaining:
        friendly_name: "Keg Quarter Percent Remaining"
        unique_id: keg_quarter_percent_remaining_sensor
        value_template: "{{ ( (states('sensor.keg_quarter_liquid_weight') | float(0) ) / 1040) * 100 | round(0) }}"
        unit_of_measurement: "%"

I added some brackets and the float(0) default = 0 value.
Does that work?

@Troon
I tried changing %f to %s in the printf statement while the sensor was still a text_sensor and it led to the OLED showing what looks like spaces. They are spaces filled in with color, but no value. I changed the text_sensor back to sensor while leaving the %s in place, and I am getting random characters for the value that are constantly changing, very odd.

@thusassistint
I also updated my template to what you said (and reverted to original code mentioned in the post) and I am still getting DATA: NAN unfortunately.

EDIT and side note - I took a different sensor, a living room temperature reading from an Ecobee sensor, and put it in place of the sensor here to see if anything populated on the OLED. I am still getting NAN. It seems like a connection issue between the ESPHome and Home Assistant, but my other devices with the same secrets and similar configs in ESPHome work fine, it is on the same network, and the API connection per the logs is successful. Not sure what is going on. Changed the logging to VERBOSE as well but hasn’t been helpful thus far.

Make sure you have a logger: line to your ESPHome config, then append this to the end of the sensor definition:

    on_value:
      then:
        - logger.log:
            format: "Received: %s"
            args: ['id(keg_quarter_percent_remaining).state']

Reload, and watch the logs.

Added that to the sensor, installed, changed value and watched logs. Unfortunately no change in logs or on OLED screen on ESPHome device.

For reference, sensor area now looks like:

# Declare the sensor component
sensor:
  - platform: homeassistant
    id: keg_quarter_percent_remaining
    entity_id: sensor.keg_quarter_percent_remaining  

    on_value:
      then:
        - logger.log:
            format: "Received: %s"
            args: ['id(keg_quarter_percent_remaining).state']

According to the ESPHome Display component page: “To display a text string from a text_sensor, append .c_str() to the end of your variable.”

So does this work:

# Declare the OLED display component
display:
  - platform: ssd1306_i2c
    model: "SSD1306 128x64"
    address: 0x3C
    id: oled_display
    lambda: |-
      it.printf(0, 0, id(font1), "Data: %f", id(keg_quarter_percent_remaining).state.c_str());
      it.printf(0, 20, id(font1), "%.1f%%", id(keg_quarter_percent_remaining).state.c_str());

I received an error when compiling it:

So I changed the sensor category to text_sensor and we are getting data on the OLED! However, the data is incorrect / not what is being shown in Home Assistant…

image

I adjusted the value and the change happened in Home Assistant but it remained the same on the OLED. Im not sure where that 1.9% is coming from. Does this mean the sensor is being seen as a text sensor? Im in general very confused. The logs remain the same, no activity on value changes. I also added c.str() to the logger line to see if that helped with logging updates but it did not.

Side question - I would like the data to be updated on the OLED when the sensor data changes. I assume this automatically happens periodically?

1 Like

It has been figured out! When I initially set this device up, I added it under the whole ‘device found’ area in Integrations / ESPHome. For whatever reason, it was removed though, and I had to add it again. The values are now showing properly (as a float or %f). Thanks so much for all of the help here, it is really appreciated. I was pulling my hair out on this.

5 Likes

Thank you so much for sharing the Solution!

I never thought that I have to activate the es-home device in Integrations, to receive data (as I was the whole time in HA) :man_facepalming: It took me forever to find the problem, until I read your solution.

3 Likes

So glad it helped someone else out! It was driving me crazy. Glad you are all set.

2 Likes

I always get the same 1.9 and do not know, where it comes from. See my issue:
“Sensordaten zwischen zwei Nodemcu austauschen und auf Display anzeigen”

SOLVED!

This is how it works:

text_sensor:
  - platform: homeassistant
    name: "sauna-temperatur"
    id: temp
    entity_id: sensor.home_saunatemperatur

display:
  - platform: ssd1306_i2c
    model: "SSD1306 128x64"
    id: oled_display
#    invert: true
#    reset_pin: D0 
    lambda: |-
      it.printf(0, 0, id(my_font16), TextAlign::TOP_LEFT, "Sauna:");
      it.printf(128, 0, id(my_font16), TextAlign::TOP_RIGHT, "°C");
      it.printf(64, 16, id(my_font48), TextAlign::TOP_CENTER, "%s", id(temp).state.c_str());

Care for the:
“text_sensor”
and display the value using: “%s” and “.c_str()”