claytonjn / hass-circadian_lighting

Circadian Lighting custom component for Home Assistant
Apache License 2.0
756 stars 89 forks source link

Support RGBW LED strips with dedicated cold white LED #239

Closed YahyaAlfayad closed 7 months ago

YahyaAlfayad commented 8 months ago

When adding a RGBW LED strip such as SK6812, circadian lighting tries to set the temperature using either RGB, XY or CT modes. Those modes result in a translation from the specified values to RGBW values. When translated, the resulted value enables the cold white LED which results in a pink light instead of a warm white. This pull request introduces a new mode -RGBW- where it calculates the values from RGB values after disabling the white LED. That results in a pure white colour when max RGB values are set because the chip can interpret those values correctly and a warm white colour after sunset.

The following picture is how it looked before modifications raised in this pull request:

IMG_8806

The following 2 pictures are after the modifications. The white colour is the result of before sunset time and the warm white is when the sun at lowest. All pictures are obtained with min_brightness set to 60

IMG_8807 IMG_8808

The switch setting looks like the following

switch:
  - platform: circadian_lighting
    name: Bedroom circadian lighting
    lights_ct:
      - light.bedroom_ceiling_lights_2
    lights_rgbw:
      - light.bed_backlight_left
      - light.bed_backlight_right
    min_brightness: 60

The settings of circadian lighting component look like the following:

circadian_lighting:
  sunrise_time: "04:30:00"
  sunset_time: "20:30:00"
claytonjn commented 8 months ago

Perhaps I'm missing something, but my understanding of the advantage of RGBW LED lights over RGB lights is that the white channel is added for more accurate white colors across the color temperature range - it seems backwards to me that the white channel would be explicitly disabled, I would expect that R, G, B channels should be disabled and only W would be used for the most accurate result. I don't know what integration your particular lights are using, but I would assume that this would happen by default if you configure the lights under lights_ct...is that not the case?

YahyaAlfayad commented 8 months ago

You are right and that is the reason why I went with RGBW (cold white variant). I am using it with WLED on ESP8266. The problem is that when the RGB or colour temperature values are translated into RGBW, the R and W values are the dominant ones which results in a pink colour instead of warm white/yellowish one. My guess is that translation might work for RGBWW (the warm white variant) but not for RGBW (the cold white variant). It kinda make sense when you add red to a cold white, it becomes a lighter red (pink) but when you add red to a warm white (yellow) it becomes even warmer. The point regarding the accuracy of white makes total sense. I also think power consumption wise (and brightness wise) having the full cold white when needed on is better than disabling it completely and relying on the RGB channels only. I am exploring now as a work around to find cutoff values when before them the white channel will be enabled and below then when the intention is to have a warm colour after sunset, the white channel would be disabled and rely on the RGB. I am also thinking of changing the new setting to be lights_rgbcw instead of lights_rgbw to make it clear that it is for cold white LED strips. I'd love to hear your thoughts about it and if you know if the warm white LED strips work as intended.

claytonjn commented 8 months ago

Ah, I think what I was missing is that for your strips there is only a single W diode (per LED grouping) that is a fixed temperature - I only have personal experience with Hue and LIFX strips, and in both cases there is both a warm white and a cool white diode in addition to RGB, so when a color temperature is set the RGB diodes are completely disabled and the warm/cool W diodes are balanced to result in the correct temperature. It looks like those are referred to as RGBWW so I apologize for the confusion there.

It seems odd to me that for an RGBW light a light.turn_on service call with rgb_color would behave differently than with rgbw_color and 0 for the W channel; to me that seems like a shortcoming of the integration which is responsible for translating the "generic" service call to the device specific call. I wonder what the behavior is if rgbw_color is used for a light that only supports RGB channels - does it just drop the W from the service call? If so, the simple fix might be to just keep the Circadian Lighting inputs the same and have every lights_rgb adjustment actually call with rgbw_color and 0 for W.

YahyaAlfayad commented 7 months ago

I've been experimenting with the different settings on WLED side and I found that WLED does an additional conversion on its side. I managed to influence that conversion by adjusting the Auto calculate white channel from RGB and Global override for Auto-calculate white setting to Accurate. The default value is None and that results in the pink colour as in the pictures I shared previously. After setting it to Accurate, I got the desired result using lights_ct: setting on circadian lighting. This workaround works well for me now so you can discard this merge request.

image image