Adafruit_NeoPixel icon indicating copy to clipboard operation
Adafruit_NeoPixel copied to clipboard

getPixelColor description unclear

Open scottalmond opened this issue 7 years ago • 2 comments

In my application I would like to highlight just one pixel by having it blink between full brightness and half-brightness. My assumption was that if I used all even RGBW values for that pixel's color, I could: get the pixel color, >>1 to divide all colors by 2, then save the dimmer pixel color. However, even when using even color values I'm getting leakage into adjacent colors, ie a fully bright green pixel blinks to cyan, a fully red pixel blinks to yellow.

It appears the "getPixelColor()" does NOT return the "previously set pixel color" as indicated by the method description but instead scales it by brightness. This means simply fetching the color through getPixelColor() and then resetting it through setPixelColor() changes the pixel color depending on the brightness setting.

The work-around that I found worked was to set brightness to 127, fetch the color, reset brightness back to the original value, then set the pixel color to >>1 color value. strip.setBrightness(127); uint32_t dim_color=strip.getPixelColor(blinking_index)>>1; strip.setBrightness(original_brightness); if(millis()&0x100) strip.setPixelColor(blinking_index,dim_color);

scottalmond avatar Mar 12 '19 12:03 scottalmond

You're correct, getPixelColor() returns the pixel's RGB values after the brightness setting has been applied. Retrieving the original color value is not possible.

Rather than doing your brightness cruft, can you just force the most-significant-bit of each RGB value to zero when you calculate dim_color?

uint32_t dim_color=(strip.getPixelColor(blinking_index)>>1) & 0x7F7F7F7F;

moose4lord avatar Apr 07 '19 12:04 moose4lord

Ah, you encountered the NeoPixel library’s Achilles heel. Tried to cover this a bit in the docs but it’s been tough to explain…

Short answer: it’s OK to use setBrightness() or getPixelColor() in one’s sketch, but not both. It has to do with some microcontrollers not being fast enough to perform brightness scaling “on the fly” as the data’s being sent out the wire, so we sneak this in by doing the brightness scaling in setPixelColor()…result being, what’s stored in RAM isn’t really the color you passed in, and there’s no way to get the original value back (unless, like, we used double the RAM, which isn’t gonna fly).

If you leave setBrightness() out of your code then the values returned by getPixelColor() will match those that were set with setPixelColor(). So the approach then, if you don’t want maxi-brightness colors, is to not use 255 or thereabouts in your RGB levels, but instead scale these back in your own code.

Alternately, if using setBrightness(), then setPixelColor() and getPixelColor() won’t match. An approach you can use then is to treat the strip as a write-only resource…that is, your own program state should contain any/all information necessary to generate the strip contents each time. This is what I usually aim for in my own projects.

Been thinking about a solution that would allow both to be used at the same time, but it’s gonna be complicated and might not actually be possible, so this is what we’re stuck with for now.

In the meantime though, yes, I’ll try to make this limitation more clear in the documentation.

PaintYourDragon avatar Apr 07 '19 15:04 PaintYourDragon