xoseperez / espurna

Home automation firmware for ESP8266-based devices
http://tinkerman.cat
GNU General Public License v3.0
3k stars 638 forks source link

[Light & LED Controllers] smooth color transition and white temperature #1058

Closed Phil1988 closed 6 years ago

Phil1988 commented 6 years ago

First of all: Thanks Xose for the insane work you have done here!

Really dude you saved me maybe a month of fulltime coding and have done everything so amazingly modular that I could benefit from your work - so again thanks for sharing!

Long Story :) I have a couple of MiLight/Limitless RGBWW LED bulbs at home. They use a PL1167 RF chip and have a crappy one way transmission protocoll (no feedback of the lamp status). You have to use a cheap remote controller or buy a wifi bridge to group the bulbs and "translate" them to wifi. I have both but it works pretty badly and there are only white or RGB (at different brightnesses) I had enough of this and made a custom PCB with an ESP8266 and 4 MOSFETs to drive each channel by using PWM - and this is where my journey started :D First I flashed an OTA firmware to flash more easily and tried different approaches before I tried AiLight, which sadly needed the MY9291 LED-chip - which I dont have - and later tried the Souliss firmware that is used to control LYT8266 bulbs - which are hardware wise almost the same like my modified MiLight bulbs. Sadly the Souliss App worked pretty bad (only worked once it was freshly installed and has the same limitation to only use white or RGB) but finally I found you :D So I used the Arduino IDE to flash your firmware onto it (a hint at your wiki would be great, that latest ArduinoJson 6.x.x wont work - so latest working version is ArduinoJson 5.13.2). I had to change the pin configuration for me at the code/espurna/config/arduino.h but not much more that I remember. Then I connected do the bulb, changed the admin password, set everything up at the "Light" settings as well as the MQTT and generated the HASS Code (awesome dude!). I now have a ESP8266 driven bulb that has the correct status and allows mixed (white and RGB LEDs) colors thanks to you! Ah... and its also integrated to my Home Assistant ;) There are some small inperfections I found:

I like the color transmission feature to fade smoothly from one color to another.

I had no deeper look into your code (- because.. ehhhmm.. .where to start? :D :D ) but I think the colors are made of a 1 Byte (0-255) channel for each color + white.

When I fade the colors then I can see some flickering. I dont know if you can improve this with a fancy algorythm but it would be great if you have any idea how to make it smoother.

Lastly - at Home Assistant I would like to have:

The white temperature is at the "coldest" point the white LEDs with very little (almost nothing) light yellow from the RGB LEDs. The warmer I chose the more green and red is added.

I would like that the centerpoint is just bare white LEDs. Colder adds blue and warmer adds green+red (yellow and red).

Do you have any ideas where to start?

My current settings in the Light section of the bulb are: Use color: yes Use RGB picker: no Use white channel: yes Use white color temperature: no Use gama correction: no Use CSS style: yes and color transitions to 500ms

If you need more information then let me know.

xoseperez commented 6 years ago

Wow... so many things. I'm glad you (almost) made it work. It would be great if you could share your work, that custom PCB and how to hack the MiLights to turn them ESPurna-compatible.

As for your questions. I'm sorry I'm not sure I can help. ESPurna uses a different PWM driver (https://github.com/StefanBruens/ESP8266_new_pwm) that reduces flickering, especially when using blocking routines like EEPROM saving. But I guess there could be some still. Try modifying the LIGHT_MAX_PWM setting in general.h, check the ESP8266_new_pwm documentation.

The temperature color is calculated using Mitchell Charity's tables (see http://www.tannerhelland.com/4435/convert-temperature-rgb-algorithm-code/). The implementation is in the _fromKelvin in the light.ino module.

Phil1988 commented 6 years ago

Well ehhm... The PCB I made, has some mistakes as I used the ESP12E to use the bottom pins (GPIO6-GPIO11) to save space... https://images-na.ssl-images-amazon.com/images/I/71bJ-TywJ-L._SL1500_.jpg

What I didnt know was, that these pins are used for internal usage only - so the first test on setting GPIO7 or GPIO10 to turn the transistor on resulted in a reset.

So I did some changes and my first eagle board design (that took hours..... maybe days) was wrong. I changed it by cutting the copper lines and soldered new wires :D

Im now waiting for double sided copper clad boards (because I had only one side copper clad boards left and glued it together).

Next mistake was that I wanted to use a LM1117 3.3V voltage regulator - but I didnt knew that it was only rated to 12V (and this board has 16V) and checked the datasheet right before soldering (I know... late but luckly not too late :smiley: )

So I used a tiny buck converter (LM2596) and drilled a hole to the aluminium plate to connect the board/EPS8266 to it.

It was planed to be a neat nice and clean looking board sitting on the bulb and now its a bulky, double whopper, trace cutted and wires added prototyp-thing :D

So here are some pics..

Old PL1167 board: 00

Buck converter soldered to 16V power supply: 05

GND, 16V and 3.3V connected to the custom board: 04

Not working board (GPIO6-11) 01 As you can see here I recycled the parts from the PL1167 board. My new design only uses AO3400 mosfets and 100k pull-down gate resistors. Pleast dont judge the soldering here. While debugging (because of resets) I had to desolder the transisors and resisors 2 times... and the trace cutting and wire adding adds to the ugly appearance ;)

modified board as it is used and working now: 02

and finally some light: 03

my 2nd version of this board uses ESP12S (as it has no unusable bottom pins out and my tests with an ESP07 compared to the ESP12E turned out, that the onboard ceramic antenna is weaker than the PCB antennas) and is also smaller and (!!!) with no bugs :D

Ah... and as you can see in the pictures: I always have some dupont header pins out for debugging and flashing cause.... you know :D

Back to the topic ;) I had a look at https://github.com/StefanBruens/ESP8266_new_pwm but I had my doubts that it could generate 200ns pulses (PWM signal) - according to my measurements from the 80MHz STM32F103CB (aka Maple Mini) board. That board was able to put out "only" 8MHz PWMs (125ns) at doing nothing else. Not even the loop() (because the loop() needs ~400ns) - for more details see here: http://stm32duino.com/viewtopic.php?f=3&t=2080&p=27900#p27893

So I measured it :D messung_gate_lowlight_02 ...but 500kHz PWMs (2ms) is also "not bad".

I fount THIS a bit courios... any explaination? messung_drain_lowlight This is measured at the drain with low light.

If I capture a longer time I can also see this at the gate: messung_gate_lowlight_longer_period

This "block" repeats every 700ms and is 525ms long... To translate this: low level means MOSFET/LEDs are on, high level means MOSFET/LEDs are off.

so every 700 there is ~175ms of no PWM - may by blocking routines?

The good thing is, that you cant see this "delay" and the LEDs looks to be static (good slow eyes :D )

I will now check your adviced places and see if I can fix it for me - and report back.

Phil1988 commented 6 years ago

I have to admit that I dont understand this ESP8266_new_pwm with its duty cycle and stepsize as I am more thinking off pulse times and frequencys as speaking off PWM. So what does changing the period do?

Anyway: I did change the LIGHT_MAX_PWM to 1000 giving me shorter duty cycles and shorter stops: messung_gate_lowlight_longer_periodlight_max_pwm 1000

But this is not the source of this problem (I also tried LIGHT_MAX_PWM 20000).

Its hard to descripe and also hard to capture, but I tried it with my smartphone: https://youtu.be/NFzAn8ISPpY

I had to put the brighness to full otherwise my phone produces a PWM-flicker video. Look at the video at about 5sec.

There is a short dark flicker that is in person easyier to see. I also was able to capture this flicker (marked red): flicker

So my guess is still that it is not a PWM problem but more of the function that does this smooth fade (transition).

I also noticed right now, that this flicker happens exactly at the middle of the transition time.

Phil1988 commented 6 years ago

I wanted to fix the colortemp issue but found more issues after making plots and calculating new algorythms....

I am using ESPurna with HASS.

When I turn the bulb on, I can set its color with the colorcircle, set the brightness and "somehow" the colortemp.

The 3rd bar "Weißwert" (means white level in german) is without function (for whatever reason.. why not hide it then?)

The problem with the colortemperature bar is, that it only allowes temperatures from ~2000 - ~4100 I found this out per trail&error by setting some "if else" for different color temps (in kelvin).

so there is a big "dead zone" on the left side... And also the point where it starts is more like 6500K instead of 4100K. hass

any ideas where this problem is coming from and even better - how to solve it?

Phil1988 commented 6 years ago

Ok first: The "deadzone" is not really dead but there are too smalll changes to be noticed by my eyes.

Start the debugging (as Home Automation, MQTT etc. is completly new to me it will took a while).

I listened to my MQTT broker with putty (win7) and mosquitto_sub.

Values from the white temperatur slider are min (cold) 153 and max (warm) 500. So it should be a temperature range of 2000K-6500K.

in light.ino kelvin funktion there is a call: _light_mireds = constrain(round(1000000UL / kelvin), LIGHT_MIN_MIREDS, LIGHT_MAX_MIREDS);

Checked the range (\config\general.h) and its OK.

#define LIGHT_MIN_MIREDS        153      // Default to the Philips Hue value that HA also use.
#define LIGHT_MAX_MIREDS        500      // https://developers.meethue.com/documentation/core-concepts

also the right value is displayed in the mqtt-sub so this works.

Getting the mired value from the MQTT broker, set the light and broadcast it back is done by:

// Color temperature in mireds
        if (t.equals(MQTT_TOPIC_MIRED)) {
            _fromMireds(atol(payload));
            lightUpdate(true, mqttForward());
            return;
        }

mireds are given to kelvin by this:

    unsigned long kelvin = constrain(1000000UL / mireds, 1000, 40000);
    _fromKelvin(kelvin);
}

kelvin is of type unsigned long and calculation is correct. Range is matching Tanner Helland's algorythm (OK).

Lets go deeper and ask for the mired and kelvin values in the _fromKelvin function... but first: Xose you are crazy man! your debug implemantation is insane!

Seems like I discover more and more of these head shaking moments where I cant believe your work! back to topic:

  debugSend(("mireds: %ld \n"), _light_mireds);
  debugSend(("kelvin: %ld \n"), kelvin);
  kelvin /= 100;
  debugSend(("divided_kelvin: %ld \n"), kelvin);

Debug gives for lowest value: [360793] mireds: 500 [360795] kelvin: 2000 [360796] divided_kelvin: 20

for highest: [388999] mireds: 153 [389001] kelvin: 6535 [389002] divided_kelvin: 65

So... its all correct here.. but wait!

The kelvin-> light algorythm is based on this data: http://www.vendian.org/mncharity/dir3/blackbody/UnstableURLs/bbr_color.html

Its accurate and scientific but for our - or at least my use case its not really application-specific. The data goes from 1.000K to 40.000K so its far beyond our light possibillitys.

So lets modify this to our/my needs.

Warmest White: 2000K Coldest White: 6535K

calculated White midpoint: ((6535K - 2000K) / 2) +2000K = 4268K calculated white what doesnt look nice to me.

Optical midpoint: [444495] mireds: 322 [444496] kelvin: 3105 ~3100K

optical white I will use this as "mid white".... also if its not that accurate regarding to the real spectrum/wave lengths.

So time to calculate... During calculation I noticed a mistake of Tanner Helland in the blue chart. If you compare it with this table http://www.vendian.org/mncharity/dir3/blackbody/UnstableURLs/bbr_color.html then you see the blue value is 0 at 1900K.

His chart http://www.tannerhelland.com/wp-content/uploads/Modified_Temperature_to_Blue_plot.png is not even 0 at "10" (which is 1000K).

So time for playing with some math, graphs and interpolation....

Doing something like this: rgb

and a bit of this.. green small

moved everything a couple of times to get a good looking result...

and here is what came out (I cut the uploading, restart and reconnect part off): https://youtu.be/HlnA9wpQoyk It's still not perfect and needs some fine tuning but that will be made.

next thing on the list: make the "color transision" look good :D

Phil1988 commented 6 years ago

I have now tested the bulb for a long time and it had some problems with my first colorTemperaturAlgorythms....

Now its working stable and with great light!

here is my algorythm for anybody interessted:

  unsigned int red = (kelvin <= 31)
                     ? LIGHT_MAX_VALUE
                     : 255 *  fs_pow((double) (kelvin - 31), -0.19);
  unsigned int green = (kelvin < 31)
                       ? 2.2856 * ((kelvin * 5)-90)  + 117.864
                       : (kelvin > 31)
                         ? 275.66 *  fs_pow((double) (kelvin - 30), -0.155)
                         : LIGHT_MAX_VALUE;
  unsigned int blue = (kelvin >= 30)
                      ? LIGHT_MAX_VALUE
                      : -1.8696  *(kelvin*kelvin) + (115.47 * kelvin) - 1531;
zsq19958629 commented 6 years ago

Based on sonoff led hardware, espurna sonoff led firmware, how to write configuration. Yaml file of hass.io for adjusting brightness and color temperature? Thank you.

stale[bot] commented 6 years ago

This issue has been automatically marked as stale because it has not had recent activity. It will be closed in 7 days if no further activity occurs. Thank you for your contributions.

stale[bot] commented 6 years ago

This issue will be auto-closed because there hasn't been any activity for two months. Feel free to open a new one if you still experience this problem.

1043717432 commented 5 years ago

I have now tested the bulb for a long time and it had some problems with my first colorTemperaturAlgorythms....

Now its working stable and with great light!

here is my algorythm for anybody interessted:

  unsigned int red = (kelvin <= 31)
                     ? LIGHT_MAX_VALUE
                     : 255 *  fs_pow((double) (kelvin - 31), -0.19);
  unsigned int green = (kelvin < 31)
                       ? 2.2856 * ((kelvin * 5)-90)  + 117.864
                       : (kelvin > 31)
                         ? 275.66 *  fs_pow((double) (kelvin - 30), -0.155)
                         : LIGHT_MAX_VALUE;
  unsigned int blue = (kelvin >= 30)
                      ? LIGHT_MAX_VALUE
                      : -1.8696  *(kelvin*kelvin) + (115.47 * kelvin) - 1531;

Based on sonoff led hardware, espurna sonoff led firmware, how to write configuration. Yaml file of hass.io for adjusting brightness and color temperature? Thank you.

Phil1988 commented 5 years ago

As I dont own a sonoff LED bulb/hardware I cant test and answer that :(

1043717432 commented 5 years ago

因为我没有一个sonoff LED灯泡/硬件我不能测试并回答:(

Thank you

1043717432 commented 5 years ago

我想解决colortemp问题,但在制作情节和计算新的算法之后发现了更多的问题....

我正在使用ESPurna和HASS。

当我打开灯泡时,我可以用colorcircle设置它的颜色,设置亮度和“某种程度上”colortemp。

第3个栏“Weißwert”(意思是德语中的白色级别)没有功能(无论出于什么原因......为什么不隐藏呢?)

colortemperature bar的问题是,它只允许温度从〜2000 - 〜4100 我发现每条线索和错误,通过为不同的颜色温度设置一些“if else”(以开尔文为单位)。

所以左侧有一个很大的“死区”...... 而且它开始的点更像是6500K而不是4100K。 HASS

任何想法来自哪个问题甚至更好 - 如何解决?

How to configure such an effect, I am espruna xiaomi table lamp, do not know how to configure yaml in homeassistant