esphome / feature-requests

ESPHome Feature Request Tracker
https://esphome.io/
409 stars 26 forks source link

TSL2591 support #267

Open nirkons opened 5 years ago

nirkons commented 5 years ago

Describe the problem you have/What new integration you would like

The TSL2561 is currently supported, however it is discontinued (by adafruit at least) and replaced by the TSL2591. Please describe your use case for this integration and alternatives you've tried:

LUX measurements Additional context

thanks

NotaLabs commented 5 years ago

Hi, i got the sensor working using the Custom Sensor Tutorial.

First you need to create the file "tsl2591.h" in your ESPHome directory. The content of "tsl2591. h" should be:

#include "esphome.h"
#include "Adafruit_TSL2591.h"

class Tsl2591 : public PollingComponent, public Sensor {
 public:
  // constructor
  Tsl2591() : PollingComponent(15000) {}
  Adafruit_TSL2591 tsl = Adafruit_TSL2591(2591);

  void setup() override {
    if (!tsl.begin()) 
    {
      ESP_LOGD("ERROR","Could not find a TSL2591 Sensor. Did you configure I2C?");
    } 
    tsl.setGain(TSL2591_GAIN_LOW);      //We use the lowest possible gain.
    tsl.setTiming(TSL2591_INTEGRATIONTIME_600MS); //We use the longest possible Integration Time for accurate Results.
    //For more details on Gain and Integration Time see the Adafruit Repository for the TSL2591 Sensor
  }
  void update() override {   
    uint16_t x = tsl.getLuminosity(TSL2591_VISIBLE);  //We only measure the visible light
    publish_state(x);
  }
};

We also need to make sure all dependencys of our code are fulfilled. Our code uses the Adafruit TSL2591 Library which can be installed using pio lib install "Adafruit TSL2591 Library". We also need to install the Adafruit Unified Sensor Library pio lib install "Adafruit Unified Sensor".

Now we can create the configuration file for our sensor node. Make sure to include the dependencies:

esphome:
  includes:
    - tsl2591.h
  libraries:
    - "Adafruit TSL2591 Library"

Add the Sensor (I added a filter which doesnt publish measurements that are zero, because the sensor would occasionally report zero when it got to bright):

sensor:
- platform: custom
  lambda: |-
    auto my_sensor = new Tsl2591();
    App.register_component(my_sensor);
    return {my_sensor};

  sensors:
    name: "TSL2591 Brightness" 
    unit_of_measurement: lux
    filters:
    - filter_out: 0

Also make sure to use and configure the i2c component according to your device. (Example for ESP8266/Wemos D1 Mini Pro)

i2c:
  sda: 4
  scl: 5

Feel free to message me if something is unclear. English is not my first language.

w1tw0lf commented 4 years ago

Thank you for this. Helped me getting it working. I have 2 of these sensors. One works perfectly and the other one now and then shoots to 65535 lux when it is dark and the middle of the night. Any reason why it would do that ?

RGN01 commented 4 years ago

Thank you @NotaLabs for your very helpful guide. I'm confused by this step pio lib install "Adafruit TSL2591 Library" - where do I run it from? Is it within HASS.IO somehow?

My installation follows this very helpful guide https://gist.github.com/frenck/32b4f74919ca6b95b30c66f85976ec58 and runs hass.io on Ubuntu 18.04.1 LTS

Apologies if this is documented somewhere - I've not been able to find it.

NotaLabs commented 4 years ago

Hi @RGN01, like the commands provided in your guide, you should be able to run my commands in the Linux terminal. pio is short for plattformio and is the framework that esphome uses. By running pio lib install "Adafruit TSL2591 Library" the librarys get installed by plattformio and can be used by esphome.

RGN01 commented 4 years ago

Unfortunately that didn't work. Running it from the Ubuntu console gave errors and I ebentually tried the --global optionm which installed it but it did not work in HASS.IO

I also tried a terminal option on HASSIO direct but that will not work either.

I'll keep trying

w1tw0lf commented 4 years ago

If you running esphome as an addon to hassio, you would need to run it within the esphome container. That is how I got it to work. Unfortunately it seems that you need to re run it everytime you restart if you want to make changes.

RGN01 commented 4 years ago

Thank you @w1tw0lf - please could you explain how you "run it within the esphome container" Is that via the hassio front end?

Apologies for the questions but I'm very confused about this at the moment.

@OttoWinter, it would be great if this could be included into the mainstream esphome at some time please.

w1tw0lf commented 4 years ago

@RGN01 Installed portainer with in the terminal of Ubuntu:

sudo docker run -dit --restart unless-stopped -d -p 8000:8000 -p 9999:9000 -v /var/run/docker.sock:/var/run/docker.sock -v portainer_data:/data portainer/portainer

Once installed accessed portainer via http://"Ubuntu ip":9999 and connected to the console of the esphome container. Run this from the console:

platformio lib --global install "Adafruit TSL2591 Library" && platformio lib --global install "Adafruit Unified Sensor"

RGN01 commented 4 years ago

Thank you so much, @w1tw0lf - I really appreciate the help!

Fantastic - that seems to have installed. Now to test the esphome code.

RGN01 commented 4 years ago

OK, it has compiled so now to test. Again, @w1tw0lf I just want to say how grateful I am - this morning I was considering using an Arduino for the tsl2591 and then using MQTT or serial UART to send the data to my esphome node! This is SOO much more elegant and I have you to thank.

w1tw0lf commented 4 years ago

Pleasure @RGN01 not my hard work. Just guiding you in the right direction.

Just as fyi, added a filter for 65535 as mentioned for 0 and solved the issue as well.

RGN01 commented 4 years ago

Thanks again - I have done that!

smnlevesque commented 4 years ago

Thank you for this guide. Like @RGN01 i'm a little bite confused with the commands. I run hass.io on virtual box so i'm not sure if the same solution apply. Any help would be appreciated

w1tw0lf commented 4 years ago

@smnlevesque if you have the addon running via hass.io for esphome, just follow my guide here: https://github.com/esphome/feature-requests/issues/267#issuecomment-578031579

pfleidi commented 4 years ago

For reference: I was able to install the library by logging into my HassOS supervisor using these instructions.

After logging in as root and using the login command, you can find your esphome container and log into it:

docker exec -it `docker ps | grep esphome | awk '{print $1}'` /bin/bash

Once you've successfully logged into the container, you can install the libraries as described above:

platformio lib --global install "Adafruit TSL2591 Library" && platformio lib --global install "Adafruit Unified Sensor"
OttoWinter commented 4 years ago

I want to clear something up here

None of that platformio lib install is not required.

Adding the library to the libraries var in the esphome: section will already install the library in the project. If that's not the case, it's an error and please report it.

thanasisloi7 commented 4 years ago

Hello, could you please help me with the similar Waveshare TSL2581 sensor ?

wjcarpenter commented 4 years ago

FWIW, I had to include a minimal spi definition even though I am not using SPI at all. Otherwise, compilation failed looking for SPI.h.

wjcarpenter commented 4 years ago

My TSL2591 arrived today, and this custom sensor implementation worked first time. Thanks @nirkons!

That's right before I learned that platform: custom doesn't support update_interval. (While experimenting with the sensor, I have to wait 15s for each fresh value.) I opened feature request #782 to ask for it. [Edit: I later realized that the polling interval is given in the superclass constructor in tls2591.h. I didn't notice that before.]

RGN01 commented 4 years ago

FWIW, I had to include a minimal spi definition even though I am not using SPI at all. Otherwise, compilation failed looking for SPI.h.

I'm trying to get it to work following @OttoWinter advice above and have an SPI error so please could you share what you mean by "minimal 'spi' definition'?

Much appreciated.

wjcarpenter commented 4 years ago

could you share what you mean by "minimal 'spi' definition'?

I used a block like this (at the same YAML level as my i2c: block). Since I wasn't actually using SPI, I just picked some GPIO numbers that I wasn't using for anything. I don't know if that matters, so later I looked up the actual pin numbers for my board and used them.

spi:
  clk_pin:  12
  miso_pin: 13

I started with just the spi: line, and the helpful error messages in the esphome dashboard config editor told me what config items I still needed. I stopped when it stopped complaining. :-)

RGN01 commented 4 years ago

Thank you - that was very helpful. I did the same but as I'm using an ESP-01 there are not many spare pins so I ended up with the following, which seems to work OK!

spi:
  clk_pin: GPIO1
  mosi_pin: GPIO1
  miso_pin: GPIO1
SergeyAnokhin commented 3 years ago

My config. Calculate "TRUE" full luminocity value but Im not sure about Visible & Infrared

esphome\tsl2591.h

#include "esphome.h"
#include "Adafruit_TSL2591.h"

class Tsl2591 : public PollingComponent, public Sensor {
 public:
  // constructor
  Tsl2591(uint8_t channel) : PollingComponent(60000) {
    Channel = channel;
  }
  Adafruit_TSL2591 tsl = Adafruit_TSL2591(2591);
  uint8_t Channel;

  void setup() override {
    ESP_LOGD("tsl2591","Setup");
    if (!tsl.begin()) 
    {
      ESP_LOGD("ERROR","Could not find a TSL2591 Sensor. Did you configure I2C?");
    } 
    //tsl.setGain(TSL2591_GAIN_LOW);    // 1x gain (bright light)
    tsl.setGain(TSL2591_GAIN_MED);    // 25x gain
    //tsl.setGain(TSL2591_GAIN_HIGH);   // 428x gain
    tsl.setTiming(TSL2591_INTEGRATIONTIME_600MS); //We use the longest possible Integration Time for accurate Results.
    //For more details on Gain and Integration Time see the Adafruit Repository for the TSL2591 Sensor
  }
  void update() override {

    uint32_t lum = tsl.getFullLuminosity();
    uint16_t ir, full;
    ir = lum >> 16;
    full = lum & 0xFFFF;

    uint32_t lux;
    switch(Channel)
    {
      case TSL2591_VISIBLE: // = 2
        // lux = tsl.calculateLux(full - ir, 0);
        ESP_LOGD("tsl2591","===> Luminocity: %d x (Raw, Visible)", full - ir);
        publish_state(full - ir);
        break;
      case TSL2591_INFRARED: // = 1
        // lux = tsl.calculateLux(ir, 0);
        ESP_LOGD("tsl2591","===> Luminocity Raw: %d x (Raw, Infrared)", ir);
        publish_state(ir);
        break;
      default: // Full: // = 0
        lux = tsl.calculateLux(full, ir);
        ESP_LOGD("tsl2591","===> Luminocity: %d Lux (Corrected, Full)", lux);
        publish_state(lux);
        break;
    }
  }
};

esphome\nodemcu_v3_01.yaml

esphome:
  name: nodemcu_v3_01
  platform: ESP8266
  board: nodemcuv2
  includes:
    - tsl2591.h
  libraries:
    - "Adafruit TSL2591 Library"

# it seems that working well without this ????
# i2c:
#   sda: D2
#   scl: D1

# spi:
#   clk_pin: GPIO1
#   mosi_pin: GPIO1
#   miso_pin: GPIO1

sensor:
  - platform: custom
    lambda: |-
      auto visible = new Tsl2591(TSL2591_VISIBLE);
      App.register_component(visible);
      auto infrared = new Tsl2591(TSL2591_INFRARED);
      App.register_component(infrared);
      auto full = new Tsl2591(0);
      App.register_component(full);
      return {visible, infrared, full};
    sensors:
      - name: "NodeMcuV3.01 TSL2591 Visible Lux" 
        unit_of_measurement: x
        icon: mdi:brightness-5
        filters:
        - filter_out: 65535
      - name: "NodeMcuV3.01 TSL2591 Infrared Lux" 
        unit_of_measurement: x
        icon: mdi:brightness-5
        filters:
        - filter_out: 65535
      - name: "NodeMcuV3.01 TSL2591 Lux" 
        unit_of_measurement: lux
        icon: mdi:brightness-5
        filters:
        - filter_out: 65535

image

wrobell commented 3 years ago

Hi, i got the sensor working using the Custom Sensor Tutorial.

First you need to [...]

I can confirm above instructions work like a charm. Would be great to get official ESPHome support for this sensor, though.

For reference this is the code I am using

#include "esphome.h"
#include "Adafruit_TSL2591.h"

class Tsl2591 : public PollingComponent, public Sensor {
 public:
  Tsl2591() : PollingComponent(1000) {}
  Adafruit_TSL2591 tsl = Adafruit_TSL2591(2591);

  void setup() override {
    if (!tsl.begin())
    {
      ESP_LOGD("ERROR","Could not find a TSL2591 Sensor. Did you configure I2C?");
    }
    tsl.setGain(TSL2591_GAIN_MED);
    tsl.setTiming(TSL2591_INTEGRATIONTIME_600MS);
  }
  void update() override {
    uint32_t full = tsl.getFullLuminosity();
    uint16_t ch0 = full & 0xffff;
    uint16_t ch1 = full >> 16;
    float lux = tsl.calculateLux(ch0, ch1);

    publish_state(lux);
  }
};
wjcarpenter commented 3 years ago

I've just submitted PRs for adding TSL2591 support to ESPHome. You should see the links just above this comment. If you are able and willing, feel free to take that for a spin. If you hit problems, let me know. (If you comment in this thread, I will see it.)

wjcarpenter commented 3 years ago

A couple of notes about some things mentioned in this thread.

wjcarpenter commented 3 years ago

I re-implemented the integration to use ESPHome I2C instead of the Adafruit library. That eliminates the faux transitive dependency on SPI and also provides some other ESPHome I2C benefits. Those changes are reflected in the current state of the PRs mentioned above.

I had been using the Adafruit library for about a year without realizing it had built into it a big delay (600ms) when taking a reading. Luckily, my ESP8266 only had 2 pollable sensor components, so the delay didn't matter. But it's a pretty big delay if you have other stuff on your ESP device. I did some stuff to deal with that in my code changes. If you are interested, you can read about it these commit comments: https://github.com/esphome/esphome/pull/2131/commits/babb9a389e1e6f1730c45c4d927846a979818a4c

w1tw0lf commented 3 years ago

Thank you @wjcarpenter

updated to the beta that was release and moved over to the TSL2591 support through ESPHome. All look good so far. No issues from me on this.

Only thing I had to do was change glass_attenuation_factor: 14.4 to glass_attenuation_factor: 28.8 from the example, as it was halving the lux reading I had before. In otherwords, where I use to get a reading of 100 lux it was giving me 50 lux.

wjcarpenter commented 3 years ago

That's unexpected. With the default values of 53 for device factor and 7.7 for glass attenuation factor, the calculated lux should come out to about the same values as the Adafruit library. (There is a small difference if you are using high or max gain values, on the order of less than 10% difference.)

~But I can see now I've got some misplaced parentheses in my calculation. I'll correct that.~

No, I take it back. Double-checking, I see that my calculation does match the Adafruit calculation.

So now I'm not too sure why you saw what you saw, w1tw0lf. The 14.4 in the example was just an example. The default is 7.7. It would make sense if you said you needed to divide 14.4 in half, but not doubling it.

wjcarpenter commented 3 years ago

FYI, following a suggestion from @oxan, I modified the code to use set_interval to take readings with power save mode. (Actually, always, but it only matters for power save mode.) So, you can safely use power save mode (the default) without impacting the global ESPHome update loop.

w1tw0lf commented 3 years ago

@wjcarpenter clean built after making changes and not seeing any changes. Lux reporting same results as just before.

w1tw0lf commented 3 years ago

@wjcarpenter here is a screenshot of the past 8 hours. Screenshot 2021-08-11 184405 white: old way shared here. red: glass_attenuation_factor @ 14.4 green: glass_attenuation_factor @ 28.8

wjcarpenter commented 3 years ago

Thanks for following up. I've been looking at the code a bit and still haven't spotted why it would be that different in the lux calculation. But, at least you have a workaround. I'm glad I decided to expose those 2 factors as config items.

0x90ChuckTessela commented 1 year ago

I apologize for posting well over a year after the last comment, but I wasn't sure this warranted a new issue/feature request.

I've been using the TSL2591 Sensor Component (https://esphome.io/components/sensor/tsl2591.html) for a while and it has been working well. My only inquiry is to why the active gain being used in "auto" mode isn't published as a value by the component.

When transitioning between extremes (very dark, to very bright or vice-versa) the auto gain mode appears to function correctly; however, without a "gain" readout for what is being used to determine the raw values/lux, it can create a misleading situation where a low light level reads as higher than a high light level.

As far as I can tell, without publishing the component's current gain for readings, relative brightness/values can become rather meaningless when the component is set to auto gain.

Is there a reason this isn't exposed, or can this component be updated to publish the active gain when set to "auto"?

wjcarpenter commented 1 year ago

That's a good question. What you've said makes sense. The "auto" gain was not in the original support for the component but was added later by another developer. Even though you were hesitant, I think you should open another issue, as a bug or a feature request, so it gets better attention. Anybody who has the time and inclination could add emitting that value.

0x90ChuckTessela commented 1 year ago

went ahead and opened an issue: https://github.com/esphome/issues/issues/4031

Thanks!