|
@ -1,79 +0,0 @@ |
|
|
#pragma once |
|
|
|
|
|
|
|
|
|
|
|
#include <array> |
|
|
|
|
|
#include <stdexcept> |
|
|
|
|
|
|
|
|
|
|
|
namespace esphome { |
|
|
|
|
|
namespace rgbww { |
|
|
|
|
|
namespace yeelight_bs2 { |
|
|
|
|
|
|
|
|
|
|
|
class RGBLight |
|
|
|
|
|
{ |
|
|
|
|
|
public: |
|
|
|
|
|
float red = 0; |
|
|
|
|
|
float green = 0; |
|
|
|
|
|
float blue = 0; |
|
|
|
|
|
float white = 0; |
|
|
|
|
|
|
|
|
|
|
|
void set_color(float red, float green, float blue, float brightness, float state) |
|
|
|
|
|
{ |
|
|
|
|
|
// Overall, the RGB colors are very usable when simply scaling the |
|
|
|
|
|
// RGB channels with the brightness, but around the white point, |
|
|
|
|
|
// the color is a bit on the red side of the spectrum. The following |
|
|
|
|
|
// scaling was created to fix that. |
|
|
|
|
|
|
|
|
|
|
|
// These functions were created, based on actual measurements while |
|
|
|
|
|
// using the original firmware, to generate white light |
|
|
|
|
|
// (i.e. when RGB = [1,1,1]). |
|
|
|
|
|
auto b = brightness * 100.0f; |
|
|
|
|
|
auto red_w = 1.00f - (-0.0000121426 * b * b - 0.147576 * b + 93.2335) / 100.0f; |
|
|
|
|
|
auto green_w = 1.00f - (-0.0000242425 * b * b - 0.340449 * b + 88.4423) / 100.0f; |
|
|
|
|
|
auto blue_w = 1.00f - (-0.0000085869 * b * b - 0.109649 * b + 94.2026) / 100.0f; |
|
|
|
|
|
|
|
|
|
|
|
// For colors that are not around the white point, we can scale the |
|
|
|
|
|
// RGB channels with the requested brightness, resulting in a very |
|
|
|
|
|
// usable color. Not 100% the same as the original firmware, but |
|
|
|
|
|
// sometimes even better IMO. |
|
|
|
|
|
auto red_c = red * brightness; |
|
|
|
|
|
auto green_c = green * brightness; |
|
|
|
|
|
auto blue_c = blue * brightness; |
|
|
|
|
|
|
|
|
|
|
|
auto level_red = red_c; |
|
|
|
|
|
auto level_green = green_c; |
|
|
|
|
|
auto level_blue = blue_c; |
|
|
|
|
|
|
|
|
|
|
|
//// The actual RGB values are a weighed mix of the above two. |
|
|
|
|
|
//// The closer to the white point, the more the white point |
|
|
|
|
|
//// value applies. |
|
|
|
|
|
//auto min = red; |
|
|
|
|
|
//if (blue < min) min = blue; |
|
|
|
|
|
//if (green < min) min = green; |
|
|
|
|
|
//if (min < 0.8f) min = 0.0f; |
|
|
|
|
|
//auto level_red = red_w * min + red_c * (1.0f - min); |
|
|
|
|
|
//auto level_green = green_w * min + green_c * (1.0f - min); |
|
|
|
|
|
//auto level_blue = blue_w * min + blue_c * (1.0f - min); |
|
|
|
|
|
//ESP_LOGD("rgb_light", "min=%f, red_w=%f, red_c=%f, red=%f", min, red_w, red_c, level_red); |
|
|
|
|
|
|
|
|
|
|
|
//// A tweak that I noticed in the original firmware and that |
|
|
|
|
|
//// were confirmed to be required to get the RGB mode to behave. |
|
|
|
|
|
////if (level_red == 1.0f && level_blue > 0.1f && level_green == 0.0f) { |
|
|
|
|
|
//// level_green = 1.0f - (0.955804f - 0.00334462f * level_blue); |
|
|
|
|
|
////} |
|
|
|
|
|
////if (level_red == 1.0f) { |
|
|
|
|
|
//// level_red = level_blue > 0.1f ? 0.873f : 0.9f; |
|
|
|
|
|
////} |
|
|
|
|
|
//if (level_red > 0.9f) level_red = 0.9f; |
|
|
|
|
|
//if (level_green > 0.9f) level_green = 0.9f; |
|
|
|
|
|
//if (level_blue > 0.9f) level_blue = 0.9f; |
|
|
|
|
|
|
|
|
|
|
|
// Invert the signal. The LEDs in the lamp's circuit are brighter |
|
|
|
|
|
// when the pwm levels on the GPIO pins are lower. |
|
|
|
|
|
this->red = 1.0f - level_red; |
|
|
|
|
|
this->green = 1.0f - level_green; |
|
|
|
|
|
this->blue = 1.0f - level_blue; |
|
|
|
|
|
} |
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
} // namespace yeelight_bs2 |
|
|
|
|
|
} // namespace rgbww |
|
|
|
|
|
} // namespace esphome |
|
|
|