-
Notifications
You must be signed in to change notification settings - Fork 4.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Added SetOption37 for RGB remapping #5326
Added SetOption37 for RGB remapping #5326
Conversation
meanwhile removed at adc781b
created by mistake
Ingenius! As each permutation actually needs 2 bits per color change it must be possible to add the white channel too. So suppose we use 2 bits per color (2 bits is 0,1,2,3) for RGBW. Then the 8-bit param byte bits could be used like WWBBGGRR. Just shift them out by 2 to get the index in the copy cur_col. So
What do you think? |
Edit: Never mind I missed that this just does that. |
The only problem I see is that quite frequently we have 2 kinds of whites (cold and warm), which gives 5 channels in total. For a complete N-to-N mapping we'd need a value domain of N ** N, this was 3 ** 3 = 27 for the rgb-to-rgb and it's 4 ** 4 = 256 for the rgbw-to-rgbw you mentioned, and these indeed fit in one byte. For an rgbwc-to-rgbwc mapping we'd need 5 ** 5 = 3125, which is unfortunately too big for one option. So I see three (somewhat) consistent ways to extend this rgb-only mapping:
Finding a numerical encoding is not a big deal, the problem is choosing the <= 256 combinations we'd like to support, so the question is what do the users actually need? |
It is that way, at least that's how I intend it :) |
I think what the user currently needs is RGB control and as you might have seen for Neopixel color control there is also a selection for one white channel. So I think let's go for the one byte option and see what the future brings. |
OK, I'll check the Neo features and try to implement something similar, with one param byte. |
I have an Idea for a full 5 channel mapping in seven eeprom bytes, but probably needs to much program space. Will try it later today. |
No problem. Rgrding Neo features I think just add up to 4 color bytes instead of three. If you want to I can do it based on your work. |
Posted in the other pull request with kinda the same thing... would this work with duplicating channels as well? Like if you had a My9291/My9231 bulb with 1 chip/4 channels (much like the standard AiLight), but it had channels mapped like CW/WW/CW/WW? I've also seen another with 2 chips/6 channels with CW,CW,G,R,B. They can definitely be all over the place. |
I think there are two different issues here:
This pull request is only about color mapping where the hardware has already been defined but the colors are wrongly connected. Mapping hardware pins to colors opens up a can of worms. |
I don't see that the whites are any different from colors. They are separate LED groups controlled just like rgb. I understand the original issue was only for rgb, but I don't believe it makes sense to make a change and not deal with the whites at the same time. |
I see two problematic points, a conceptual and a technical one. The conceptual problem is the number of the channels. If we don't want to use dynamic structures everywhere (including in the saved settings), then we must set a fixed number of channels we 'allocate' compile-time. If this is too low, then we can't handle every situation, if it is too high, then we're wasting resources everywhere else. The current number of channels is MAX_PWMS=5, that is {r,g,b,w,c}, the individual values we'd like to set to change the light, and up to now it seems to cover the vast majority of the devices. If a device has 6 channels, we can't handle it at all, because we get only 5 values from the user. It's a nice idea, but it would require a huge amount of re-consideration and re-implementation, it would 'open up a can of worms', as @arendst phrased it :). (And then we shouldn't stop at just assigning channels, but have a mixing matrix instead, etc.) The technical issue is that now we have a very limited number of config param bytes available (that is, without changes that would affect the whole codebase), so the configuration space of the channel mapping should fit in one byte. A generic 4-to-4 mapping fits, but that's all. As soon as we exhaust these param bytes, the next feature that requires one would be possible only via incompatible changes, so one feature mustn't use up more than what's absolutely necessary. So, it's indeed a nice idea, but it seems that it would require too extensive design-level changes to the codebase, and now at least we should start with a 'cheaper' change and learn what we can from it. Most probably that's why @arendst added that '...and see what the future brings.' to the end :). |
I'm ok with 5 as that would seem to handle everything tasmota is capable in terms of color control. Here's the changes I made for my Lohas bulbs. Not being very familiar with the code yet, I may not have done it in the most appropriate way, but it worked for me. I only post this to show what I had to do to get these bulbs to work. If your changes can accommodate this, great. If not, I'm perfectly fine using a one-off custom build for them. Wouldn't want folks spending an inordinate amount of time on a small subset of bulbs. Sonoff.ino - Change the AILigh base to RGBWC instead of RGBW **TO xdrv_04_light.ino - Rearrange the color channels for RGBWC **TO This bulb does have 2 white channels, but what I configured for warm is just a tiny less cold version of cold. No idea why they have 2 banks of cold leds instead of 1 cold, 1 warm. Maybe they just wanted a really bright cold white when both are turned on. The color temp difference I see could just be natural variations of the same leds. |
Based on this I tried to implement a full 5 color remapper, the best I could come up is +160byte compared to this pull request. It allows mapping any channel to any channel but 1 channel could be mapped only to one channel so RGBCwWw => BGRWwCw is valid, but RGBCwWw=>RGBRG is not. I made a pull request against the repository of @gsimon75 available here: gsimon75-iot#5 Here is the color mapping table: https://docs.google.com/spreadsheets/d/1ovEWyUBObOYYAl8ey6K6LffHhiniRXuIq7iivyxmyEU/edit?usp=sharing |
it saves 24 bytes of code
3fa335e
to
0a4a21a
Compare
I've reverted the RGBW 4-to-4 mapping, and I'm merging the permutation-based approach of @netpok , but there are some minor loose ends (initializing the param to a sane default, recalculating the mapping when the SetOption37 arrives, etc.), and I'll do some testing before I commit the merge :). |
@netpok: Nice work, thanks for the contribution! I've added a few things:
I haven't updated the wiki yet, just in case the reviewers find something we haven't noticed... |
Question for you. Based on this change would I still set my bulb to AILights and then use this setoption to fix the colors? Or would I use a template based of AILight? As I pointed out in my code change the AILight assumes 4 channels, but I have 5. Thanks again for your work on this. |
If I get it right, you need two changes:
As far as I see, if you choose SONOFF_B1 instead of AILIGHT, it accomplishes exactly this change.
Now, that's the trouble point. All the proposed RGBWC remapping happens before the So it is not a problem of device-agnostic channel remapping, but of supporting a not-fully-standard variant of SONOFF_B1. I don't think we can solve it here, but it may be worth a separate issue, so it won't get forgotten but doesn't block this one. As of how to solve that, the only way I see is by having a separate To make such a thing choosable from build config, we'd need some sort of sub-model define, like Unfortunately I don't see any feasible way to add this degree of flexibility :(, maybe some of the more experienced developers have some idea... On the other hand, if/when that sort of bulbs start spreading on the market, we'll have to face this problem nevertheless, so it's worth thinking about it anyway. |
I removed the initialization because I assumed, that the default values are zero based on the lots of commented out equals zero lines. Of course if that's not the case then my bad and sorry. Also I removed the defines to save flash, but I did forget that those will be stripped anyways if they aren't used. Also I left out the live update because of the same reasons. |
6.4.1.19 20190222 * Add command SetOption37 for RGBCW color mapping (#5326)
I added the option to the wiki, but the color mapping table should be probably migrated to the wiki from my spreadsheet I will do it when I have some time (of course anyone can do it ;)), but till then I will leave the spreadsheet available. |
@netpok : Well done :) ! |
Spreadsheet to wiki conversion done: SetOption37, and I've linked it to the short description in the SetOption list |
A MY9291 has 4 channels. This is what you get with the "AILight" device type. A MY9231 has 3 channels, but can be daisy chained. You get a two chip configuration with the "Sonoff B1" device type. What would be ideal is a configuration option to Map Channels to colors, including an "Empty" Channel. Either have the device type set the number of channels (4 for AILight, 6 for Sonoff B1) and then offer Channel Selectors for each channel name Tasmota is aware of (Red, Green, Blue. Cold White, Warm White) or offer a text field that should be filled with a string like "RGB0WC" to denote which channel goes to which color. SetOption37, as implemented here, doesn't seem to allow any way to access the 6th channel, which my Bulb device uses (mine is 0CWGRB). So, I'm unable to access the Blue LEDs. This way the duty matrix is would be configurable since different devices will use the channels differently. As it is now, without a code change specific to this device, I am unable to use Tasmota. Alternately, SetOption37 could provide 6 channels in the matrix (instead of 5 like it does now). This would support the most common device configurations (one MY9291 or two MY9231s) but would require more than 120 "options" to enumerate them all (720 - 5040 depending on implementation). |
The problem is that currently setoption37 resides in an 8bit variable, so to implement this it would need some changes. Just to confirm, there is no known configuration in which you can access all leds, right? |
Looks like he can't access 6 channels? Only other configs I know of are the ones with duplicate colors on multiple channels. |
@netpok I'll admit, I didn't try all 119 variations available in SetOption37. But after trying the ones that were in the same order as my LED channels, I tried those in reverse order, and those with the second chip listed first. No matter what I did, channel 6 was not accessible. The device is a LOHAS RGBW bulb (Tuya OEM firmware). It's made more complicated because white is actually two channels (though both channels are basically the same temperature of light). I didn't even try to address that issue, yet, and just settled for the one white channel. If it helps any, I was able to get this running using ESPHome with no issues, though I'd prefer to use Tasmota. |
The issue does occur in the config of @dlashua, so we should think up some solution for it, even if it won't be easy :), but we must keep the backward compatibility. The current solution is able only to permute the 5 channels (R,G,B,W,C), it isn't possible neither to skip one channel, nor to assign the same component to more than one channel, so it cannot solve his problem. The reason for this limitation is that (as of now) the configuration space for this re-mapping must fit into one uint8_t, the permutations require 5! = 120 so it fits, an arbitrary remapping of {none,R,G,B,W,C} to six channels would require 6 ^ 6 = 46656 configurable values so it would require two bytes. The SetOptionNN values are stored as an uint8_t array here, the size of this array is limited to 18, because the other indexes are already assigned to other purposes (see the parser code here), currently the indices 32..37 are assigned, 38..49 are available, so if we absolutely must, then we can allocate more, the question is how many do we need? If we make this a generic config item, we shouldn't just consider this particular model, but try to solve all the similar cases as well. With 2 bytes we could do a 6-channel full remapping, but will it be enough for all similar cases? With 3 bytes it could support 9 channels, with 4 bytes 12. I'd say 12 channels are impractical, but I would've said that for 6, and yet there they are :)... Can we define a reasonable limit for the number of channels to support? We must, because the config is stored as a block in the flash, but once we settle for a number, then it'll be that, it can't be extended later, and it'll use up those bytes forever, even on devices that doesn't even need this. On the other hand, there is a different approach. Instead of extending the complexity of the config for being able to support everything and anything, we could consider this as a 3rd My92x1-based device type (in addition to AiLight and B1), and implement these local specialities in model-specific code, rather than in general config. Now the decision (AiLight or B1) is based on the presence or absence of the 2nd white channel here, so a 3rd choice doesn't fit there, but it is possible to distinguish based directly on the module type, like for the As we have far more available space for the code than for the config, and this way whatever we do, it wouldn't affect any other device type at all, I'd rather vote for this approach. What do you think? |
I'm currently leaning towards the full six channel mapping because it would solve the issue for all, there is even a free location for it at 7BC. But the question is should we use a 5 to 6 or a 6 to 6 mapping. I'm using some drivers to drive led strips at multiple places so I can see the use of 6 channels, but in general probably way easier to go with 5 to 6 mapping. The other solution I can think right now is just use 3 bits of data from flag2 (or steal it from somewhere, there are some variable which have free bits) and use it to mark the empty channel of the my92x chips, but this doesn't solve the same colored channels. |
In the case of @DavinKD above, he needs {{R,G,B,W,0,0},{R,G,B,W,C,0}} instead of {{R,G,B,W,0,0},{W,C,0,G,R,B}}, so for these twin-my92x1 cases we do have 12 channels, 6 for the first chip and 6 for the second, see here. Sure, in this case the first 6 channels are identical, but in the original cases it was a plain RGB-to-BGR, and in the So AFAIK, what we need here is a free remapping of {zero,R,G,B,W,C} to 12 channels, meaning 6 ^ 12, and that would require 32 bits. On one hand, this whole redundant channel thing makes sense only for the My92x1, so it seems to be a very specific workaround for one particular model, and it would be an overkill to design a generic mechanism just to cover it. On the other hand, if we implemented this, then we would no longer need the distinction of AiLight vs. B1, nor the whole Both approaches have benefits, but it's not a trivial decision, so I suggest opening a separate issue for it, so that it isn't lost in all the discussions above :). |
Jeez, 12 channels, but why... I currently don't even see why these chips are better than a simple pwm, but that won't change what the manufacturers are putting them in their device. Also I opened the new thread: #5490 |
I don't believe my light had 12 channels, just 6 like the other dual myxxxx setups. However, I did have 2 CW channels like digiblur on his recent stream. So I would need the same color mapped on 2 channels. |
David how did you do this for the LOHAS bulbs? How did you enter this into the command line using the SetOption37 ? I was a bit lost on how you mapped yours since I have some that are exactly like what you have. |
The option value is interpreted as a 3-digit ternary number, each digit telling where the corresponding channel is mapped from: the rightmost digit being for channel 0, the middle digit for channel 1, the leftmost digit for channel 2.
The digit values are 0=red, 1=green, 2=blue, so:
etc.
Just changing the option does not trigger the color change, you must either set a new color or send a 'power off/on' command.
Related to: Issue #5310