Led gradient over four colors by CO2 sensor

HI,

my idia is to change color my ESPhome 8212 leds based on CO2 values from my sensor so to create gradient over over blue, green, orange, red. Any idea how to do that please?

1 Like

Do you want to do this in the ESPHome code or in a home assistant automation?

Hi @tom_l, better for HA but I don’t mind for both as it might be usefull for others too :slight_smile:

HA would definitely be easier.

  1. what is your CO2 sensor entity_id?
  2. what id your light entity_id?
  3. what CO2 sensor values to you want to switch to each colour?
  1. sensor.co2
  2. light.yeelight
  3. 400 - blue, 800 - green, 1200 orange, 4000 red

I could map the exact colors to the values, but the challenge here for me is to create fluent gradient in between those values.

- id: co2_to_colour_light
  alias: 'CO2 to Colour Light'
  trigger:
    platform: state
    entity_id: sensor.co2
  action:
    service: light.turn_on
    data_template:
      brightness: 255
      color_name: >-
        {% if states('sensor.co2')|int > 4000 ) %}
          red
        {% elif states('sensor.co2')|int > 1200 ) %}
          orange
        {% elif states('sensor.co2')|int > 800 ) %}
          green
        {% elif states('sensor.co2')|int > 400 ) %}
          blue
        {% else ) %}
          fuchsia
        {% endif ) %}

You can pick any other named colour for the less than 400 ‘else’ case from here.

I’d suggest a more logical colour scheme would be

red > 4000
orange > 1200
yellow > 800
green > 400
blue < 400

But feel free to use whatever you want.

Thanks for this solution, this is what I have now working.

However this will not create the fluent color gradient in between the values. See the picture of what I meant for reference, the colors in the example are random. Ie each number unit of ppm have respective color. I can do it so CO2 level will match the brightness but don’t know how to match the gradient as the color is defined at least by two numbers.

Oh right. I see. The only way I know of that you could do that would be to create a lambda effect in esphome based on the sensor data. While I know ‘of’ it I do not know ‘how’.

1 Like

It will be easy in HA too but needs to figure lets say the gradient mathematical function.

There in no way to address individual LEDs in the strip from Home Assistant to create the transition. You have to do it in the ESP.

As you are controlling the color by light component from HA you can do something like

trigger:
   - platform: state
   - entity_id: sensor.co2
action:
    - service: light.turn_on
      data:
        entity_id: light.leds
        rgb_color: [variable1,variable2,variable3]

The variables will be controlled by the formula based on CO2 value

And they will light the whole string from end to end with a solid colour defined by your 3 variables, with no gradient, just like my automation above.

Sorry there might be misunderstanding. Yes, I want each co2 value have specific color based on that gradient but the strip as you said will always have solid respective color.

Ok so you want the whole string to be the same colour but instead of stepped levels you want a gradual change.

My advice would be to use hscolor instead of rgb. That way you can keep the saturation constant and just map the hue to the CO2 value with some function.

Oh! Thanks! That would be easiest. Thanks. Ill post the automation here when I am done :slight_smile:

This hue (0-360) might help:

IMG_0525

Looks like you need to map a 0-12000 CO2 value to 236-0 hue.

Hue = (-0.02 * states('sensor.co2')|int + 236)|int

1 Like

This template for hs color should work. I will test when I am home :slight_smile: thanks for helping @tom_l

{% if states('sensor.co2') | int < 2000 %}
  {{ (states('sensor.co2') - 400) * 0,15 | float | round(0) | int}}
{% else %}
  0
{% endif %} 

I ended up to:

- id: co2wledpasekpostel
  alias: 'Světlo: Wled založeno na CO2'
  trigger:
    platform: state
    entity_id: light.svetla_pod_posteli
  condition: 
  - condition: state
    entity_id: group.myroom
    state: home
  action:
  - service: light.turn_on
    entity_id: light.svetla_pod_posteli
    data_template:
      hs_color: 
        - >
          {% if states('sensor.co2') == 'unavailable'  %}
            360
          {% elif states('sensor.co2') | float < 2000 %}
            {{ ((states('sensor.co2') | float - 400) * 0.15) | round(0) | int }}
          {% elif states('sensor.co2') | float > 2000 %}
            0
          {%else%}
          {% endif %} 

Will se how its working in few hours :slight_smile: Thanks again for coop @tom_l

Dears, whats wrong with the code I am writing please? Maybe @pnbruckner might help. I am kind of lost :confused:

- id: co2wledpasekpostel
  alias: 'Světlo: Wled založeno na CO2' 
  trigger:
    platform: state
    entity_id: light.svetla_pod_posteli
  condition: 
  - condition: state
    entity_id: group.myroom
    state: home
  action:
  - service: light.turn_on
    data_template:
      entity_id: light.svetla_pod_posteli
      hs_color: >
        {% if states('sensor.co2') == 'unavailable' %}[360,100]
        {% elif states('sensor.co2') | float < 2000 %}[{{ ((states('sensor.co2') | float - 400) * 0.15) | round(0) | int }},100]
        {%else%}[1,100]
        {% endif %}

I gave you the equation above.

  action:
  - service: light.turn_on
    data_template:
      entity_id: light.svetla_pod_posteli
      hs_color: >
       [ {{ (-0.02 * states('sensor.co2')|int + 236)|int }} , 100 ]

This only works from 0 to 12000ppm though. Go outside that range and you will get errors.