esphome / feature-requests

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

SGP30 sleep mode #1991

Open fran6120 opened 1 year ago

fran6120 commented 1 year ago

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

First of all, thanks to everyone who makes this great.

SGP30 has a high current draw (48 mAh) for solar/battery power projects.

In the datasheet you can read that the sensor can be put into sleep mode which has 2 μAh of current consumption.

I know that this sensor is not the best option for this kind of project, but if this feature could be easily implemented that would be really nice.

Please describe your use case for this integration and alternatives you've tried:

In my particular case, I use this sensor in a weather station made with esphome where I already use the deep_sleep function. With this implementation, for example, just like I do with esp8266 MCU, I could have the sensor off when the battery is low and on when the battery is full or when there is enough solar power.

Additional context

I am not a developer and I do not have the capacity to do this, but one of the options that I had thought of to do this is to establish a reference to a variable in the SGP30 configuration.

  - platform: sgp30
    eco2:
      name: "Nivel eCO2"
      accuracy_decimals: 1
    tvoc:
      name: "Nivel TVOC"
      accuracy_decimals: 1
    store_baseline: true
    baseline:
      eco2_baseline: 0x96EC
      tvoc_baseline: 0x996B
    address: 0x58
    compensation: 
      temperature_source: bme280_temperature
      humidity_source: bme280_humidity
    sleep_mode: "id of some sensor template or global variable state"    ------------------------
    update_interval: 1s

According to the datasheet:

The sensor starts powering-up after reaching the power-up threshold voltage VDD,Min specified in Table 3. After reaching this threshold voltage, the sensor needs the time tPU to enter the idle state. Once the idle state is entered it is ready to receive commands from the master. Each transmission sequence begins with a START condition (S) and ends with a STOP condition (P) as described in the I2C bus specification

So if the sleep_mode state is false, the sensor is initialized but if the sleep_mode state is true the sensor is not initialized and stays in idle mode.

I really don't know if this is possible and if once the esp8266 is running, after a while the state of the "sleep_mode" variable changes from true to false, the SGP30 can be initialized, and on the contrary if the state of the variable " sleep_mode" goes from false to true, the SGP30 can be restarted and remain inactive.

In the datasheet it is also mentioned:

The « sgp30_measure_test » command is intended for production line testing and verification only. It should not be used after having issued an “sgp30_iaq_init” command. For the duration of the « sgp30_measure_test » command, the sensor is operated in measurement mode with a supply current as specified in Table 3. After the command, the sensor is in sleep mode.

Maybe this way is more simple or functional.

Either way, whether it's possible or not, thanks for the effort.

fran6120 commented 1 year ago

After several unsuccessful attempts and not in the best way, I have managed to initialize sgp30 outside of void setup and make it work in my project. Now I can start the SGP30 when needed through another sensor, (in my case I use a homeassistant binary sensor and a template sensor).

By default the weather station turns on for 12 seconds, communicates with homeassistant and goes into deep sleep for one minute, and in this way continuously.

With a script I read the status of "prevent_deep_sleep" and I can interrupt the process to enter deep_sleep

binary_sensor: 
  - platform: homeassistant #                                                        
    name: Prevenir Deep Sleep
    id: prevenir_deep_sleep
    entity_id: input_boolean.prevenir_deep_sleep
    icon: 'mdi:sleep-off'
    publish_initial_state: True
    internal: true
    on_state:
      then:
        - lambda: 'id(sleep_on_boot_sgp30).update();'

"sleep_on_boot_sgp30" takes the state of "prevent_deep_sleep" and in this way I do not initialize the sgp30 saving 48 mAh

sensor:
  - platform: template
    name: "sleep sgp30"
    id: sleep_on_boot_sgp30
    lambda: 'return id(prevenir_deep_sleep).state;'    
    filters:
      - filter_out: nan
    internal: true
    update_interval: never
  - platform: sgp30
    eco2:
      name: "Nivel eCO2"
      accuracy_decimals: 1
    tvoc:
      name: "Nivel TVOC"
      accuracy_decimals: 1
    store_baseline: true
    address: 0x58
    compensation: 
      temperature_source: bme280_temperature
      humidity_source: bme280_humidity
    sleep_on_boot: true  
    sleep_sensor:
      sensor_id: sleep_on_boot_sgp30
    update_interval: 1s

In this way, the sensor can only be kept asleep from the power on, and once initialized, changing the state of "sleep_on_boot_sgp30" will not make it go back to sleep, the MCU would have to be restarted or a general reset of the i2c bus would be necessary, which would affect the other devices.

It's a botch but in my particular case it works fine.

As I said before, I have no idea about programming, so the code could be improved for sure.

I am attaching the code in case someone wants to take a look at it or in case it helps someone else.

Thank you.

sgp30_sleep_on_boot.zip