From 89b3f85c18877d183cab47a36916a87b2fbed35e Mon Sep 17 00:00:00 2001 From: Michael Miller Date: Sun, 11 Dec 2016 14:51:35 -0800 Subject: [PATCH] NeoPixelBrightnessBus (#143) --- .../NeoPixelBrightness/NeoPixelBrightness.ino | 83 +++++++++++ library.json | 2 +- library.properties | 2 +- src/NeoPixelBrightnessBus.h | 138 ++++++++++++++++++ src/NeoPixelBus.h | 5 +- src/internal/NeoBrightnessBus.h | 121 +++++++++++++++ 6 files changed, 347 insertions(+), 4 deletions(-) create mode 100644 examples/NeoPixelBrightness/NeoPixelBrightness.ino create mode 100644 src/NeoPixelBrightnessBus.h create mode 100644 src/internal/NeoBrightnessBus.h diff --git a/examples/NeoPixelBrightness/NeoPixelBrightness.ino b/examples/NeoPixelBrightness/NeoPixelBrightness.ino new file mode 100644 index 0000000..01af6cb --- /dev/null +++ b/examples/NeoPixelBrightness/NeoPixelBrightness.ino @@ -0,0 +1,83 @@ +// NeoPixelBrightness +// This example will cycle brightness from high to low of +// three pixels colored Red, Green, Blue. +// This demonstrates the use of the NeoPixelBrightnessBus +// with integrated brightness support +// +// There is serial output of the current state so you can +// confirm and follow along +// + +#include // instead of NeoPixelBus.h + +const uint16_t PixelCount = 3; // this example assumes 3 pixels, making it smaller will cause a failure +const uint8_t PixelPin = 14; // make sure to set this to the correct pin, ignored for Esp8266 + +#define colorSaturation 255 // saturation of color constants +RgbColor red(colorSaturation, 0, 0); +RgbColor green(0, colorSaturation, 0); +RgbColor blue(0, 0, colorSaturation); + +// Make sure to provide the correct color order feature +// for your NeoPixels +NeoPixelBrightnessBus strip(PixelCount, PixelPin); + +// you loose the original color the lower the dim value used +// here due to quantization +const uint8_t c_MinBrightness = 8; +const uint8_t c_MaxBrightness = 255; + +int8_t direction; // current direction of dimming + +void setup() +{ + Serial.begin(115200); + while (!Serial); // wait for serial attach + + Serial.println(); + Serial.println("Initializing..."); + Serial.flush(); + + // this resets all the neopixels to an off state + strip.Begin(); + strip.Show(); + + direction = -1; // default to dim first + + Serial.println(); + Serial.println("Running..."); + + // set our three original colors + strip.SetPixelColor(0, red); + strip.SetPixelColor(1, green); + strip.SetPixelColor(2, blue); + + strip.Show(); +} + + +void loop() +{ + uint8_t brightness = strip.GetBrightness(); + Serial.println(brightness); + + delay(100); + + // swap diection of dim when limits are reached + // + if (direction < 0 && brightness <= c_MinBrightness) + { + direction = 1; + } + else if (direction > 0 && brightness >= c_MaxBrightness) + { + direction = -1; + } + // apply dimming + brightness += direction; + strip.SetBrightness(brightness); + + // show the results + strip.Show(); +} + diff --git a/library.json b/library.json index e361d73..30fddf2 100644 --- a/library.json +++ b/library.json @@ -8,7 +8,7 @@ "type": "git", "url": "https://github.com/Makuna/NeoPixelBus" }, - "version": "2.2.4", + "version": "2.2.5", "frameworks": "arduino", "platforms": "*" } diff --git a/library.properties b/library.properties index 5661f88..3216c01 100644 --- a/library.properties +++ b/library.properties @@ -1,5 +1,5 @@ name=NeoPixelBus by Makuna -version=2.2.4 +version=2.2.5 author=Michael C. Miller (makuna@live.com) maintainer=Michael C. Miller (makuna@live.com) sentence=A library that makes controlling NeoPixels (WS2811, WS2812 & SK6812) and DotStars (APA102) easy. diff --git a/src/NeoPixelBrightnessBus.h b/src/NeoPixelBrightnessBus.h new file mode 100644 index 0000000..2a86ee9 --- /dev/null +++ b/src/NeoPixelBrightnessBus.h @@ -0,0 +1,138 @@ +/*------------------------------------------------------------------------- +NeoPixelBus library wrapper template class that provides overall brightness control + +Written by Michael C. Miller. + +I invest time and resources providing this open source code, +please support me by dontating (see https://github.com/Makuna/NeoPixelBus) + +------------------------------------------------------------------------- +This file is part of the Makuna/NeoPixelBus library. + +NeoPixelBus is free software: you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as +published by the Free Software Foundation, either version 3 of +the License, or (at your option) any later version. + +NeoPixelBus is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with NeoPixel. If not, see +. +-------------------------------------------------------------------------*/ + +#pragma once + +#include "NeoPixelBus.h" + +template class NeoPixelBrightnessBus : + public NeoPixelBus +{ +public: + NeoPixelBrightnessBus(uint16_t countPixels, uint8_t pin) : + NeoPixelBus(countPixels, pin), + _brightness(0) + { + } + + NeoPixelBrightnessBus(uint16_t countPixels, uint8_t pinClock, uint8_t pinData) : + NeoPixelBus(countPixels, pinClock, pinData), + _brightness(0) + { + } + + NeoPixelBrightnessBus(uint16_t countPixels) : + NeoPixelBus(countPixels), + _brightness(0) + { + } + + void SetBrightness(uint8_t brightness) + { + // Due to using fixed point math, we modifiy the brightness + // before storing making the math faster + uint8_t newBrightness = brightness + 1; + + // Only update if there is a change + if (newBrightness != _brightness) + { + // calculate a scale to modify from old brightness to new brightness + // + uint8_t oldBrightness = _brightness - 1; // unmodify brightness value + uint16_t scale; + + if (oldBrightness == 0) + { + scale = 0; // Avoid divide by 0 + } + else if (brightness == 255) + { + scale = 65535 / oldBrightness; + } + else + { + scale = (((uint16_t)newBrightness << 8) - 1) / oldBrightness; + } + + // re-scale existing pixels + // + uint8_t* ptr = this->Pixels(); + uint8_t* ptrEnd = ptr + this->PixelsSize(); + while (ptr != ptrEnd) + { + uint16_t value = *ptr; + *ptr++ = (value * scale) >> 8; + } + + _brightness = newBrightness; + this->Dirty(); + } + } + + uint8_t GetBrightness() const + { + return _brightness - 1; + } + + void SetPixelColor(uint16_t indexPixel, typename T_COLOR_FEATURE::ColorObject color) + { + if (_brightness) + { + uint8_t* ptr = (uint8_t*)&color; + uint8_t* ptrEnd = ptr + T_COLOR_FEATURE::PixelSize; + + while (ptr != ptrEnd) + { + uint16_t value = *ptr; + *ptr++ = (value * _brightness) >> 8; + } + } + NeoPixelBus::SetPixelColor(indexPixel, color); + } + + typename T_COLOR_FEATURE::ColorObject GetPixelColor(uint16_t indexPixel) const + { + typename T_COLOR_FEATURE::ColorObject color = NeoPixelBus::GetPixelColor(indexPixel); + + if (_brightness) + { + uint8_t* ptr = (uint8_t*)&color; + uint8_t* ptrEnd = ptr + T_COLOR_FEATURE::PixelSize; + + while (ptr != ptrEnd) + { + uint16_t value = *ptr; + *ptr++ = (value << 8) / _brightness; + } + } + return color; + } + +protected: + uint8_t _brightness; +}; + + diff --git a/src/NeoPixelBus.h b/src/NeoPixelBus.h index dd4e1f0..d2b962a 100644 --- a/src/NeoPixelBus.h +++ b/src/NeoPixelBus.h @@ -152,7 +152,7 @@ public: _state &= ~NEO_DIRTY; }; - uint8_t* Pixels() const + uint8_t* Pixels() { return _method.getPixels(); }; @@ -307,7 +307,7 @@ public: -private: +protected: const uint16_t _countPixels; // Number of RGB LEDs in strip uint8_t _state; // internal state @@ -381,3 +381,4 @@ private: } }; + diff --git a/src/internal/NeoBrightnessBus.h b/src/internal/NeoBrightnessBus.h new file mode 100644 index 0000000..4ac2020 --- /dev/null +++ b/src/internal/NeoBrightnessBus.h @@ -0,0 +1,121 @@ +/*------------------------------------------------------------------------- +NeoPixel library helper template class that provides overall brightness control + +Written by Michael C. Miller. + +I invest time and resources providing this open source code, +please support me by dontating (see https://github.com/Makuna/NeoPixelBus) + +------------------------------------------------------------------------- +This file is part of the Makuna/NeoPixelBus library. + +NeoPixelBus is free software: you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as +published by the Free Software Foundation, either version 3 of +the License, or (at your option) any later version. + +NeoPixelBus is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with NeoPixel. If not, see +. +-------------------------------------------------------------------------*/ + +#pragma once + +template class NeoBrightnessBus : + public NeoPixelBus +{ +public: + void SetBrightness(uint8_t brightness) + { + // Stored brightness value is different than what's passed. + // This simplifies the actual scaling math later, allowing a fast + // 8x8-bit multiply and taking the MSB. 'brightness' is a uint8_t, + // adding 1 here may (intentionally) roll over...so 0 = max brightness + // (color values are interpreted literally; no scaling), 1 = min + // brightness (off), 255 = just below max brightness. + uint8_t newBrightness = brightness + 1; + // Only update if there is a change + if (newBrightness != _brightness) + { + // calculate a scale to modify from old brightness to new brightness + // + uint8_t oldBrightness = _brightness - 1; // De-wrap old brightness value + uint16_t scale; + + if (oldBrightness == 0) + { + scale = 0; // Avoid divide by 0 + } + else if (brightness == 255) + { + scale = 65535 / oldBrightness; + } + else + { + scale = (((uint16_t)newBrightness << 8) - 1) / oldBrightness; + } + + // re-scale existing data in RAM + // + uint8_t* ptr = pixels; + uint8_t* ptrEnd = pixels + PixelsSize(); + while (ptr != ptrEnd) + { + uint16_t value = *ptr; + *ptr++ = (value * scale) >> 8; + } + + _brightness = newBrightness; + Dirty(); + } + } + + uint8_t GetBrightness() const + { + return _brightness; + } + + void SetPixelColor(uint16_t indexPixel, typename T_COLOR_FEATURE::ColorObject color) + { + if (_brightness) + { + uint8_t* ptr = (uint8_t*)&color; + uint8_t* ptrEnd = ptr + T_COLOR_FEATURE::PixelSize; + + while (ptr != ptrEnd) + { + uint16_t value = *ptr; + *ptr++ = (value * _brightness) >> 8; + } + } + NeoPixelBus::SetPixelColor(indexPixel, color); + } + + typename T_COLOR_FEATURE::ColorObject GetPixelColor(uint16_t indexPixel) const + { + T_COLOR_FEATURE::ColorObject color = NeoPixelBus::GetPixelColor(indexPixel); + + if (_brightness) + { + uint8_t* ptr = (uint8_t*)&color; + uint8_t* ptrEnd = ptr + T_COLOR_FEATURE::PixelSize; + + while (ptr != ptrEnd) + { + uint16_t value = *ptr; + *ptr++ = (value << 8) / _brightness); + } + } + return color; + } + +protected: + uint8_t _brightness; +}; + +