UV Index with LTR390-UV sensor

I just started with this sensor and am getting (using defaults) on my window sill in direct sun.

Daylight: 52428.60156 lx
Ambient Light: 262143.00000
UV Index: 0.14000 UVI
UV: 322.00000

UV Index should be 6.5 right now.

I have the Waveshare UV (C) board with LTR390-UV-01 sensor.

For the glass you want Far UV Grade Fused Silica Quartz. This is frequently sold in 30mm squares. I have one and it does not affect the readings from quick testing. My regular windows reduce UVI reading by one decimal place (0.14 → 0.014).

Plan on installing this in a weather station so the readings will probably change.

looks like your UV Index value is equally weird

Sadly enough I have the same weird index values…

I have the same weird index values. And I think I figured out the issues. I opened an issue in the esphome github, the details are there:

Until it is fixed in the esphome depository, here are the possible workarounds:

workaround 1:
The resolution config does not work, so leave it at 18-bit default.
The UVI calculation depends on the resolution config and gain config, so calculate your own using this formula:
UVI = ( uv / 2300 * wfac ) * 4 * ( 18 / gain )
The first part is the original formula.
The x 4 is to adjust for being at default 18-bit resolution instead of 20-bit.
The x 18 / gain is to adjust for actual gain configured vs x18 gain assumed in the original formula.

workaround 2:
Use the esphome external components method to override the ltr390 component.

Set up the external component by downloading the ltr390 files from the esphome github, you should get 4 files in the ltr390 directory. Overwrite the ltr390.cpp file by the file I attached in the opened issue above (the attached file should be renamed to ltr390.cpp).

1 Like

It would be great if they could fix that, I would love to include that sensor in my new irrigation controller

Does this lamda look right?
Also, are the wfac and gain correct assuming I’m not changing any of the defaults?
I’m still getting UVI values about 1/4 what is published for my zip code.

    lambda: |-
      const float wfac = 1.0;   // wfac
      const float gain = 3.0;   // gain
      return ( ((id(${devicename}_UV).state * wfac) / 2300) * 4 * ( 18 / gain ));

I haven’t read all the comments but I want to remmenber that the LTR390 UV measure doesn’t return the index, the index must be calculated.

Hi,

i’m trying this workaround, but it’s failing with:

Failed config

sensor.ltr390: [source <unicode string>:373]
  platform: ltr390
  uv_index: 
    name: Weather Station ltr390 UV index
    id: ltr390_uv_index
  uv: 
    name: Weather Station ltr390 uvs
    id: ltr390_uvs
    
    [lambda] is an invalid option for [uv]. Please check the indentation.
    lambda: |-
      float wfac = 1.0;   // wfac
      float gain = 3.0;   // gain
      return ( ((id(ltr390_uvs).state * wfac) / 2300) * 4 * ( 18 / gain ));
  light: 
    name: Weather Station ltr390 light
    id: ltr390_light
  ambient_light: 
    name: Weather Station ltr390 ambient light
    id: ltr390_ambient_light
  resolution: 20
  update_interval: 10s

for the sniplet.

# UV and Ambient Light
  - platform: ltr390
    uv_index:
      name: "${friendly_name} ltr390 UV index"
      id: ltr390_uv_index
    uv:
      name: "${friendly_name} ltr390 uvs"
      id: ltr390_uvs
      lambda: |-
        float wfac = 1.0;   // wfac
        float gain = 3.0;   // gain
        return ( ((id(ltr390_uvs).state * wfac) / 2300) * 4 * ( 18 / gain ));
    light:
      name: "${friendly_name} ltr390 light"  
      id: ltr390_light
    ambient_light:
      name: "${friendly_name} ltr390 ambient light"
      id: ltr390_ambient_light
    resolution: 20
    update_interval: 10s

Any advise, please?

The error message makes it clear: you can’t have a lambda here.

See the docs: what are you trying to return? I think you want this in an on_value: section. See here:

Thank you, changed to:

# UV and Ambient Light
  - platform: ltr390
    uv_index:
      name: "${friendly_name} ltr390 UV index"
      id: ltr390_uv_index
    uv:
      name: "${friendly_name} ltr390 uvs"
      id: ltr390_uvs
      on_value: 
        then:
          lambda: |-
            float wfac = 1.0;   // wfac
            float gain = 3.0;   // gain
            return ( ((id(ltr390_uvs).state * wfac) / 2300) * 4 * ( 18 / gain ));
    light:
      name: "${friendly_name} ltr390 light"  
      id: ltr390_light
    ambient_light:
      name: "${friendly_name} ltr390 ambient light"
      id: ltr390_ambient_light
    resolution: 20
    update_interval: 10s

no syntx error, but by compling, error.

Dependency Graph
|-- AsyncTCP-esphome @ 2.0.1
|-- WiFi @ 2.0.0
|-- FS @ 2.0.0
|-- Update @ 2.0.0
|-- ESPAsyncWebServer-esphome @ 3.1.0
|-- DNSServer @ 2.0.0
|-- ESPmDNS @ 2.0.0
|-- noise-c @ 0.1.4
|-- Wire @ 2.0.0
|-- ArduinoJson @ 6.18.5
Compiling .pioenvs/weather-station/src/main.cpp.o
: In lambda function:
:386:71: error: return-statement with a value, in function returning ‘void’ [-fpermissive]
*** [.pioenvs/weather-station/src/main.cpp.o] Error 1
========================== [FAILED] Took 6.12 seconds ==========================

what could i be doing wrong?

You are using on_value: when you should be using filters:, assuming you want to replace the value of the UV entity.

    uv:
      name: "${friendly_name} ltr390 uvs"
      id: ltr390_uvs
      filters: 
        lambda: |-
          float wfac = 1.0;   // wfac
          float gain = 3.0;   // gain
          return (x * wfac / 2300 * 4 * 18 / gain);

Thank you so much!

I’m not having any luck receiving data from my Gravity LTR390-UV. It’s connected to a ESP32ThingPlus using the default pins SDA: GPIO23 and SCL: GPIO22.

I’m at a point where I at least get the device discovered. I have experimented with a few different approaches using code others have found works. What should I expect to see? has anyone any suggestions on how I could test to see if it’s even functional. beginning to think I’ve got a dud sensor.

[14:13:02][C][i2c.arduino:054]:   SDA Pin: GPIO23
[14:13:02][C][i2c.arduino:055]:   SCL Pin: GPIO22
[14:13:02][C][i2c.arduino:056]:   Frequency: 50000 Hz
[14:13:02][C][i2c.arduino:059]:   Recovery: bus successfully recovered
[14:13:02][I][i2c.arduino:069]: Results from i2c bus scan:
[14:13:02][I][i2c.arduino:075]: Found i2c device at address 0x1C

my yaml is as follows:

i2c:
  sda: GPIO23
  scl: GPIO22
  scan: true

sensor:
  - platform: ltr390
    uv:
      name: "UV"
    uv_index:
      name: "UV Index"
    light:
      name: "Light"
    ambient_light:
      name: "Ambient Light"
    resolution: 19
    gain: X3
    window_correction_factor: 1
    update_interval: 5s

Hi, Liteon, the manufacturer of the LTR390 made a revision of the datasheet were he say that UV sensivity for the sensor is not 2300 but 1400 FYI => LTR390/LTR-390UV-01_Final_ DS_V1.4.pdf at main · levkovigor/LTR390 (github.com)

so, to have it right, shall 2300 in the formula ( ((id(ltr390_uvs).state * wfac) / 2300) * 4 * ( 18 / gain )); be replaced by 1400, so ( ((id(ltr390_uvs).state * wfac) / 1400) * 4 * ( 18 / gain ));?

no data. interestingly, no errors. image

In theory yes, I did it on my setup and UVI are now a 30% higher than expected so I think I will stick to 2300

Hi all, chiming in to say that the discussion has been updated over on Github ltr390 light sensor reports very low UVI values and resolution settings not working · Issue #4380 · esphome/issues · GitHub and I’ve submitted a PR to hopefully address the UVI issue.

I know they updated the esphome page for this sensor, but I’m a little confused on which integration time to pick. There’s a chart at the bottom to find the correct integration time but:

  1. They say the default gain should be X18
  2. They say the default resolution should be 20

These are two different rows in the table - I would pick integration time of 100 based on the gain and 400 based on the resolution.

Any ideas what the correct integration time would be with those default gains/resolutions?

Hi! I have exactly the same problem! Did you manage to solve it somehow?