Skip to content
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

Bug in Neopixel getPixelColor function - and proposed fix for library #384

Open
KayleeAmelia opened this issue Apr 6, 2024 · 0 comments

Comments

@KayleeAmelia
Copy link

KayleeAmelia commented Apr 6, 2024

Hi all,
I... have never done a github upload before. So I hope I'm doing this right.

I noticed a problem with the getPixelColor function in Neopixel library, when using non-default brightness settings. Comments on lines 3311-3315 note innaccuracy as a known issue, however, I have managed to fix it.

In "Adafruit_NeoPixel.cpp", from line 3310 onwards:

if (brightness) {
      // Stored color was decimated by setBrightness(). Returned value
      // attempts to scale back to an approximation of the original 24-bit
      // value used when setting the pixel color, but there will always be
      // some error -- those bits are simply gone. Issue is most
      // pronounced at low brightness levels.
      
	  return (((uint32_t)(p[rOffset] *255) / (brightness-1)) << 16) |
             (((uint32_t)(p[gOffset] *255) / (brightness-1)) << 8) |
             ((uint32_t)(p[bOffset] *255) / (brightness-1));//returns the adjusted rgb colour, accounting for brightness.
	//old return was return (((uint32_t)(p[rOffset] << 8) / brightness) << 16) |
        //     (((uint32_t)(p[gOffset] << 8) / brightness) << 8) |
        //     ((uint32_t)(p[bOffset] << 8) / brightness);
    }

And a bit further along:

    } else { // Is RGBW-type device
    p = &pixels[n * 4];
    if (brightness) { // Return scaled color
      return (((uint32_t)(p[wOffset] *255) / (brightness-1)) << 24) |
             (((uint32_t)(p[rOffset] *255) / (brightness-1)) << 16) |
             (((uint32_t)(p[gOffset] *255) / (brightness-1)) << 8) |
             ((uint32_t)(p[bOffset] *255) / (brightness-1));
	  /*return (((uint32_t)(p[wOffset] << 8) / brightness) << 24) |
             (((uint32_t)(p[rOffset] << 8) / brightness) << 16) |
             (((uint32_t)(p[gOffset] << 8) / brightness) << 8) |
             ((uint32_t)(p[bOffset] << 8) / brightness);
	  */ //old version
    } else { // Return raw color

In short, it seems that the error was an 'off by one' type error.
I have thoroughly tested the first block using an ESP32-S3, but cannot test the second block, as I do not have RGBW LEDs.
Tested using ESP32-S3 on Arduino IDE 2.3.0

How have I tested this? My sketch repeatedly grabs the old colour from a neopixel, changed it, then changes it back. I have left this running for several hours, and the only rounding error is the initial rounding used from the first setPixelColor command with brightness applied, and restoring and re-writing the colour several thousand times has produced no further rounding errors.
I offer this fix, in the hope that it helps someone, and hoping the fix makes it into the next update for Neopixel library.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant