forked from Makuna/NeoPixelBus
96
examples/NeoPixelRotateLoop/NeoPixelRotateLoop.ino
Normal file
96
examples/NeoPixelRotateLoop/NeoPixelRotateLoop.ino
Normal file
@@ -0,0 +1,96 @@
|
|||||||
|
// NeoPixelFunLoop
|
||||||
|
// This example will move a trail of light around a series of pixels.
|
||||||
|
// A ring formation of pixels looks best.
|
||||||
|
// The trail will have a slowly fading tail.
|
||||||
|
//
|
||||||
|
// This will demonstrate the use of the RotateRight method.
|
||||||
|
//
|
||||||
|
|
||||||
|
#include <NeoPixelBus.h>
|
||||||
|
#include <NeoPixelAnimator.h>
|
||||||
|
|
||||||
|
|
||||||
|
const uint16_t PixelCount = 16; // make sure to set this to the number of pixels in your strip
|
||||||
|
const uint16_t PixelPin = 2; // make sure to set this to the correct pin, ignored for Esp8266
|
||||||
|
const uint16_t AnimCount = 1; // we only need one
|
||||||
|
const uint16_t TailLength = 6; // length of the tail, must be shorter than PixelCount
|
||||||
|
const float MaxLightness = 0.4f; // max lightness at the head of the tail (0.5f is full bright)
|
||||||
|
|
||||||
|
NeoGamma<NeoGammaTableMethod> colorGamma; // for any fade animations, best to correct gamma
|
||||||
|
|
||||||
|
NeoPixelBus<NeoGrbFeature, Neo800KbpsMethod> strip(PixelCount, PixelPin);
|
||||||
|
//NeoPixelBus<NeoGrbwFeature, Neo800KbpsMethod> strip(PixelCount, PixelPin);
|
||||||
|
|
||||||
|
NeoPixelAnimator animations(AnimCount); // NeoPixel animation management object
|
||||||
|
|
||||||
|
void SetRandomSeed()
|
||||||
|
{
|
||||||
|
uint32_t seed;
|
||||||
|
|
||||||
|
// random works best with a seed that can use 31 bits
|
||||||
|
// analogRead on a unconnected pin tends toward less than four bits
|
||||||
|
seed = analogRead(0);
|
||||||
|
delay(1);
|
||||||
|
|
||||||
|
for (int shifts = 3; shifts < 31; shifts += 3)
|
||||||
|
{
|
||||||
|
seed ^= analogRead(0) << shifts;
|
||||||
|
delay(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Serial.println(seed);
|
||||||
|
randomSeed(seed);
|
||||||
|
}
|
||||||
|
|
||||||
|
void LoopAnimUpdate(const AnimationParam& param)
|
||||||
|
{
|
||||||
|
// wait for this animation to complete,
|
||||||
|
// we are using it as a timer of sorts
|
||||||
|
if (param.state == AnimationState_Completed)
|
||||||
|
{
|
||||||
|
// done, time to restart this position tracking animation/timer
|
||||||
|
animations.RestartAnimation(param.index);
|
||||||
|
|
||||||
|
// rotate the complete strip one pixel to the right on every update
|
||||||
|
strip.RotateRight(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void DrawTailPixels()
|
||||||
|
{
|
||||||
|
// using Hsl as it makes it easy to pick from similiar saturated colors
|
||||||
|
float hue = random(360) / 360.0f;
|
||||||
|
for (uint16_t index = 0; index < strip.PixelCount() && index <= TailLength; index++)
|
||||||
|
{
|
||||||
|
float lightness = index * MaxLightness / TailLength;
|
||||||
|
RgbColor color = HslColor(hue, 1.0f, lightness);
|
||||||
|
|
||||||
|
strip.SetPixelColor(index, colorGamma.Correct(color));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void setup()
|
||||||
|
{
|
||||||
|
strip.Begin();
|
||||||
|
strip.Show();
|
||||||
|
|
||||||
|
SetRandomSeed();
|
||||||
|
|
||||||
|
// Draw the tail that will be rotated through all the rest of the pixels
|
||||||
|
DrawTailPixels();
|
||||||
|
|
||||||
|
// we use the index 0 animation to time how often we rotate all the pixels
|
||||||
|
animations.StartAnimation(0, 66, LoopAnimUpdate);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void loop()
|
||||||
|
{
|
||||||
|
// this is all that is needed to keep it running
|
||||||
|
// and avoiding using delay() is always a good thing for
|
||||||
|
// any timing related routines
|
||||||
|
animations.UpdateAnimations();
|
||||||
|
strip.Show();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
@@ -13,9 +13,11 @@ HslColor KEYWORD1
|
|||||||
HsbColor KEYWORD1
|
HsbColor KEYWORD1
|
||||||
HtmlColor KEYWORD1
|
HtmlColor KEYWORD1
|
||||||
NeoGrbFeature KEYWORD1
|
NeoGrbFeature KEYWORD1
|
||||||
|
NeoGrbwFeature KEYWORD1
|
||||||
NeoRgbwFeature KEYWORD1
|
NeoRgbwFeature KEYWORD1
|
||||||
NeoRgbFeature KEYWORD1
|
NeoRgbFeature KEYWORD1
|
||||||
NeoBrgFeature KEYWORD1
|
NeoBrgFeature KEYWORD1
|
||||||
|
NeoRbgFeature KEYWORD1
|
||||||
Neo800KbpsMethod KEYWORD1
|
Neo800KbpsMethod KEYWORD1
|
||||||
Neo400KbpsMethod KEYWORD1
|
Neo400KbpsMethod KEYWORD1
|
||||||
NeoAvr800KbpsMethod KEYWORD1
|
NeoAvr800KbpsMethod KEYWORD1
|
||||||
@@ -66,6 +68,10 @@ Begin KEYWORD2
|
|||||||
Show KEYWORD2
|
Show KEYWORD2
|
||||||
CanShow KEYWORD2
|
CanShow KEYWORD2
|
||||||
ClearTo KEYWORD2
|
ClearTo KEYWORD2
|
||||||
|
RotateLeft KEYWORD2
|
||||||
|
ShiftLeft KEYWORD2
|
||||||
|
RotateRight KEYWORD2
|
||||||
|
ShiftRight KEYWORD2
|
||||||
IsDirty KEYWORD2
|
IsDirty KEYWORD2
|
||||||
Dirty KEYWORD2
|
Dirty KEYWORD2
|
||||||
ResetDirty KEYWORD2
|
ResetDirty KEYWORD2
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
name=NeoPixelBus by Makuna
|
name=NeoPixelBus by Makuna
|
||||||
version=2.0.8
|
version=2.0.9
|
||||||
author=Michael C. Miller (makuna@live.com)
|
author=Michael C. Miller (makuna@live.com)
|
||||||
maintainer=Michael C. Miller (makuna@live.com)
|
maintainer=Michael C. Miller (makuna@live.com)
|
||||||
sentence=A library that makes controlling NeoPixels (WS2811, WS2812 & SK6812) easy.
|
sentence=A library that makes controlling NeoPixels (WS2811, WS2812 & SK6812) easy.
|
||||||
|
@@ -160,14 +160,150 @@ public:
|
|||||||
|
|
||||||
void ClearTo(typename T_COLOR_FEATURE::ColorObject color)
|
void ClearTo(typename T_COLOR_FEATURE::ColorObject color)
|
||||||
{
|
{
|
||||||
|
uint8_t temp[T_COLOR_FEATURE::PixelSize];
|
||||||
|
|
||||||
|
T_COLOR_FEATURE::applyPixelColor(temp, 0, color);
|
||||||
|
|
||||||
uint8_t* pixels = _method.getPixels();
|
uint8_t* pixels = _method.getPixels();
|
||||||
for (uint16_t n = 0; n < _countPixels; n++)
|
uint8_t* pFirst = T_COLOR_FEATURE::getPixelAddress(pixels, 0);
|
||||||
|
uint8_t* pLast = T_COLOR_FEATURE::getPixelAddress(pixels, _countPixels);
|
||||||
|
uint8_t* pFront = temp;
|
||||||
|
while (pFirst < pLast)
|
||||||
{
|
{
|
||||||
T_COLOR_FEATURE::applyPixelColor(pixels, n, color);
|
T_COLOR_FEATURE::copyIncPixel(pFirst, pFront);
|
||||||
}
|
}
|
||||||
|
|
||||||
Dirty();
|
Dirty();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
void RotateLeft(uint16_t rotationCount, uint16_t first = 0, uint16_t last = 0xffff)
|
||||||
|
{
|
||||||
|
if (last >= _countPixels)
|
||||||
|
{
|
||||||
|
last = _countPixels - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (first < _countPixels &&
|
||||||
|
last < _countPixels &&
|
||||||
|
first < last &&
|
||||||
|
(last - first) >= rotationCount)
|
||||||
|
{
|
||||||
|
|
||||||
|
// store in temp
|
||||||
|
uint8_t temp[rotationCount * T_COLOR_FEATURE::PixelSize];
|
||||||
|
uint8_t* pixels = _method.getPixels();
|
||||||
|
uint8_t* pFirst = T_COLOR_FEATURE::getPixelAddress(temp, 0);
|
||||||
|
uint8_t* pLast = T_COLOR_FEATURE::getPixelAddress(temp, rotationCount - 1);
|
||||||
|
uint8_t* pFront = T_COLOR_FEATURE::getPixelAddress(pixels, first);
|
||||||
|
while (pFirst <= pLast)
|
||||||
|
{
|
||||||
|
T_COLOR_FEATURE::moveIncPixel(pFirst, pFront);
|
||||||
|
}
|
||||||
|
|
||||||
|
// shift data
|
||||||
|
ShiftLeft(rotationCount, first, last);
|
||||||
|
|
||||||
|
// move temp back
|
||||||
|
pFirst = T_COLOR_FEATURE::getPixelAddress(temp, 0);
|
||||||
|
pFront = T_COLOR_FEATURE::getPixelAddress(pixels, last - (rotationCount - 1));
|
||||||
|
while (pFirst <= pLast)
|
||||||
|
{
|
||||||
|
T_COLOR_FEATURE::moveIncPixel(pFront, pFirst);
|
||||||
|
}
|
||||||
|
|
||||||
|
Dirty();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ShiftLeft(uint16_t shiftCount, uint16_t first = 0, uint16_t last = 0xffff)
|
||||||
|
{
|
||||||
|
if (last >= _countPixels)
|
||||||
|
{
|
||||||
|
last = _countPixels - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (first < _countPixels &&
|
||||||
|
last < _countPixels &&
|
||||||
|
first < last &&
|
||||||
|
(last - first) >= shiftCount)
|
||||||
|
{
|
||||||
|
uint8_t* pixels = _method.getPixels();
|
||||||
|
uint8_t* pFirst = T_COLOR_FEATURE::getPixelAddress(pixels, first);
|
||||||
|
uint8_t* pLast = T_COLOR_FEATURE::getPixelAddress(pixels, last);
|
||||||
|
uint8_t* pFront = T_COLOR_FEATURE::getPixelAddress(pixels, first + shiftCount);
|
||||||
|
while (pFront <= pLast)
|
||||||
|
{
|
||||||
|
T_COLOR_FEATURE::moveIncPixel(pFirst, pFront);
|
||||||
|
}
|
||||||
|
|
||||||
|
Dirty();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void RotateRight(uint16_t rotationCount, uint16_t first = 0, uint16_t last = 0xffff)
|
||||||
|
{
|
||||||
|
if (last >= _countPixels)
|
||||||
|
{
|
||||||
|
last = _countPixels - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (first < _countPixels &&
|
||||||
|
last < _countPixels &&
|
||||||
|
first < last &&
|
||||||
|
(last - first) >= rotationCount)
|
||||||
|
{
|
||||||
|
|
||||||
|
// store in temp
|
||||||
|
uint8_t temp[rotationCount * T_COLOR_FEATURE::PixelSize];
|
||||||
|
uint8_t* pixels = _method.getPixels();
|
||||||
|
uint8_t* pFirst = T_COLOR_FEATURE::getPixelAddress(temp, 0);
|
||||||
|
uint8_t* pLast = T_COLOR_FEATURE::getPixelAddress(temp, rotationCount - 1);
|
||||||
|
uint8_t* pBack = T_COLOR_FEATURE::getPixelAddress(pixels, last);
|
||||||
|
while (pLast >= pFirst)
|
||||||
|
{
|
||||||
|
T_COLOR_FEATURE::moveDecPixel(pLast, pBack);
|
||||||
|
}
|
||||||
|
|
||||||
|
// shift data
|
||||||
|
ShiftRight(rotationCount, first, last);
|
||||||
|
|
||||||
|
// move temp back
|
||||||
|
pLast = T_COLOR_FEATURE::getPixelAddress(temp, rotationCount - 1);
|
||||||
|
pBack = T_COLOR_FEATURE::getPixelAddress(pixels, first + rotationCount - 1);
|
||||||
|
while (pLast >= pFirst)
|
||||||
|
{
|
||||||
|
T_COLOR_FEATURE::moveDecPixel(pBack, pLast);
|
||||||
|
}
|
||||||
|
|
||||||
|
Dirty();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ShiftRight(uint16_t shiftCount, uint16_t first = 0, uint16_t last = 0xffff)
|
||||||
|
{
|
||||||
|
if (last >= _countPixels)
|
||||||
|
{
|
||||||
|
last = _countPixels - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (first < _countPixels &&
|
||||||
|
last < _countPixels &&
|
||||||
|
first < last &&
|
||||||
|
(last - first) >= shiftCount)
|
||||||
|
{
|
||||||
|
uint8_t* pixels = _method.getPixels();
|
||||||
|
uint8_t* pFirst = T_COLOR_FEATURE::getPixelAddress(pixels, first);
|
||||||
|
uint8_t* pLast = T_COLOR_FEATURE::getPixelAddress(pixels, last);
|
||||||
|
uint8_t* pBack = T_COLOR_FEATURE::getPixelAddress(pixels, last - shiftCount);
|
||||||
|
while (pBack >= pFirst)
|
||||||
|
{
|
||||||
|
T_COLOR_FEATURE::moveDecPixel(pLast, pBack);
|
||||||
|
}
|
||||||
|
|
||||||
|
Dirty();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const uint16_t _countPixels; // Number of RGB LEDs in strip
|
const uint16_t _countPixels; // Number of RGB LEDs in strip
|
||||||
|
|
||||||
|
@@ -36,6 +36,27 @@ public:
|
|||||||
return pPixels + indexPixel * PixelSize;
|
return pPixels + indexPixel * PixelSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void copyIncPixel(uint8_t*& pPixelDest, uint8_t* pPixelSrc)
|
||||||
|
{
|
||||||
|
*pPixelDest++ = *pPixelSrc++;
|
||||||
|
*pPixelDest++ = *pPixelSrc++;
|
||||||
|
*pPixelDest++ = *pPixelSrc;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void moveIncPixel(uint8_t*& pPixelDest, uint8_t*& pPixelSrc)
|
||||||
|
{
|
||||||
|
*pPixelDest++ = *pPixelSrc++;
|
||||||
|
*pPixelDest++ = *pPixelSrc++;
|
||||||
|
*pPixelDest++ = *pPixelSrc++;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void moveDecPixel(uint8_t*& pPixelDest, uint8_t*& pPixelSrc)
|
||||||
|
{
|
||||||
|
*pPixelDest-- = *pPixelSrc--;
|
||||||
|
*pPixelDest-- = *pPixelSrc--;
|
||||||
|
*pPixelDest-- = *pPixelSrc--;
|
||||||
|
}
|
||||||
|
|
||||||
typedef RgbColor ColorObject;
|
typedef RgbColor ColorObject;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -49,6 +70,32 @@ public:
|
|||||||
return pPixels + indexPixel * PixelSize;
|
return pPixels + indexPixel * PixelSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void copyIncPixel(uint8_t*& pPixelDest, uint8_t* pPixelSrc)
|
||||||
|
{
|
||||||
|
uint32_t* pDest = (uint32_t*)pPixelDest;
|
||||||
|
uint32_t* pSrc = (uint32_t*)pPixelSrc;
|
||||||
|
*pDest++ = *pSrc;
|
||||||
|
pPixelDest = (uint8_t*)pDest;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void moveIncPixel(uint8_t*& pPixelDest, uint8_t*& pPixelSrc)
|
||||||
|
{
|
||||||
|
uint32_t* pDest = (uint32_t*)pPixelDest;
|
||||||
|
uint32_t* pSrc = (uint32_t*)pPixelSrc;
|
||||||
|
*pDest++ = *pSrc++;
|
||||||
|
pPixelDest = (uint8_t*)pDest;
|
||||||
|
pPixelSrc = (uint8_t*)pSrc;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void moveDecPixel(uint8_t*& pPixelDest, uint8_t*& pPixelSrc)
|
||||||
|
{
|
||||||
|
uint32_t* pDest = (uint32_t*)pPixelDest;
|
||||||
|
uint32_t* pSrc = (uint32_t*)pPixelSrc;
|
||||||
|
*pDest-- = *pSrc--;
|
||||||
|
pPixelDest = (uint8_t*)pDest;
|
||||||
|
pPixelSrc = (uint8_t*)pSrc;
|
||||||
|
}
|
||||||
|
|
||||||
typedef RgbwColor ColorObject;
|
typedef RgbwColor ColorObject;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user