KY-018 lux measurement in esphome

I’ve just finished building the bruh automations multisensor and it’s working great. But I’m having trouble figuring out how get the correct lux value from the voltage number. As of now I’m using the cookbook example but it’s giving me a value that is maxed out at 200lux when it’s dark and lowers it when it’s bright. I can’t get my head around how to get it right. When dark the V value is 1.0V and it goes down when it gets brighter.

I think you’ll need to apply a different formula to the voltage level. The one in the cookbook seems to be for the temt6000 sensor, not an LDR sensor.

There is some sample code here

However it seems to be based on a 5v range, not a 1v range. Hope that might help.

Thank you. I’ll try to figure out how to implement it into esphome :+1:

Great can you share with me your formular? If you can share it will be helpful for many esphome users : )

when I get it working I will :slight_smile:

thx I’ll open if I find it, have a good esphome : )

good stuff!

Did anyone figure this out?

can you share the [KY-018] with esphome code ?

I didn’t get it to show the correct values. Mine is backwards. I get 200lux at max when it is dark och then it goes down when it gets brighter :stuck_out_tongue:

Did you ever figure it out?

The response for lux vs LDR resistance is not just a log response, it is a log-log response, i.e both x and y axes are logarithmic! Therefore you need to use a double inverse log (ie 10^x) to get lux from resistance. I used a light meter to measure lux vs resistance and plot this graph (the blue line).

The magic to produce the red line on the graph is in the line of code below where “ret” is the actual lux value.

float ret = pow(10, intercept) * pow(resistance, slope);

As you can see when it’s very bright the formula deviates quite a bit, but it’s ok for most purposes.

You will need to determine the straight line slope and intercept values (the two const float values in the yaml below) using a lux meter with your specific LDR, or you can try using my values and see if they work!!

  - platform: resistance
    sensor: ldr_voltage
    configuration: DOWNSTREAM
    resistor: 47.2kOhm
    name: LDR Resistance
    id: ldr_resistance
    internal: true

  - platform: template
    name: LDR Lux
    id: ldr_lux
    icon: "mdi:brightness-7"
    unit_of_measurement: lx
    update_interval: 5s
    lambda: |-
      const float slope = -0.84;
      const float intercept = 4.65;
      float resistance = id(ldr_resistance).state;

      if (resistance < 400.0)
        // Prevent calculated lux from reaching infinity
        resistance = 400.0;
      float ret = pow(10, intercept) * pow(resistance, slope);
      ESP_LOGW("ldr lux", "LDR voltage=%.3fV, resistance=%.1fkOhm, Light=%.2flx", id(ldr_voltage).state, id(ldr_resistance).state / 1000.0, ret);
      return ret;
1 Like

amazing work!

1 Like

I’m also using KY-018.

Do you know the formula from analogRead(analogsensorPin) output you get on NodeMCU/Arduino to transform this value into lux ?

I’ve tried some formulas around, but they all give me weird results…

       float AR = analogRead(analogsensorPin); 
        float voltage = AR * (5.0/1025) * 1000;
        float resistance = 10000 * ( voltage / ( 5000.0 - voltage) );
        lux = (500.0 / resistance)*1000;

Can this be a good approximation for KY-018?Preformatted text

For anyone else that ends up here I altered the lamba to below to make it work as expected. The snippet is from the EspHome configuration. No light is close to 0lux and max light is close to 200lux.

  - platform: adc
    pin: A0
    name: "Kitchen Light Sensor"
    update_interval: 5s
    unit_of_measurement: lx
      - lambda: |-
          return (x / 10000.0) * -2000000.0 + 200;

The Sensor i use is cheap and looks like this.


Hi there,
Has anyone else had success with this?
Seems to max out at 200 lux, thing is when it’s unplugged from KY-018 the readings don’t really change much.
I used @NickB 's code on my nodemcu esp8266.

[14:01:03][D][sensor:126]: 'Bedroom Light Sensor': Sending state 199.80469 lx with 2 decimals of accuracy
[14:01:09][D][sensor:126]: 'Bedroom Light Sensor': Sending state 199.41406 lx with 2 decimals of accuracy
[14:01:13][D][sensor:126]: 'Bedroom Light Sensor': Sending state 197.07031 lx with 2 decimals of accuracy
[14:01:19][D][sensor:126]: 'Bedroom Light Sensor': Sending state 197.26562 lx with 2 decimals of accuracy
[14:01:23][D][sensor:126]: 'Bedroom Light Sensor': Sending state 199.80469 lx with 2 decimals of accuracy
[14:01:28][D][sensor:126]: 'Bedroom Light Sensor': Sending state 199.80469 lx with 2 decimals of accuracy```

My sensor also was returning inverted values at first

This lambda seems to work for now with NickB’s code:
Returned values are now from around 0 to around 1635:

return ((x / 10000.0) * -20000000.0) + 1635;