Hardware components | ||||||
| × | 1 | ||||
| × | 1 | ||||
Software apps and online services | ||||||
|
A simple project, trying out a few animations on a NeoPixel matrix from AliExpress consisting of 5 LED rings and 1 LED in the center (93 LEDs in total).
Preparing the LED ringsThe 6 components are fixed to each other but not electronically connected, you need to solder all 5V connections together, as well as all ground connections.
You also have to solder the DO (digital out) connection of a ring to the DI (digital in) of the next. Make sure the flow continues (from DO to DI) or else the rings won't function correctly.
It is not the tidiest soldering job but it works fine.
The setup is easy: connect the power input and ground of the NeoPixels to the 5V output and ground of the Arduino and connect the DIN to pin 3 (best practice to add a 470 Ohm in between).
Note: if you set the brightness too high or add more LEDs, you might need to use an external power supply. I had no problems using the USB input of the Nano to power the LEDs.
/*
**********************************************************************
* Neopixel Multiple Ring animation by ericBcreator
* Designed to be used with an Arduino UNO, Nano or compatible device.
**********************************************************************
* version 1.0 - Last update 20200118 by ericBcreator
*
* This code is free for personal use, not for commercial purposes.
* Please leave this header intact.
*
* contact: ericBcreator@gmail.com
**********************************************************************
* Components:
* - Arduino Nano
* - Multi Neopixel Ring, 6 rings with 1+2+8+12+16+32 leds
**********************************************************************
*/
//
// debug settings
//
//#define DEBUG // print debug messages
//#define DEBUGCHECKPIXEL0 // visual check which pixel is at 0 (after MAIN_PIXEL_OFFSET), sets it off after the startup fade in (also the 0 pixel of a 2nd ring)
#ifdef DEBUG
#define DEBUGPRINT(x) Serial.print(x)
#define DEBUGPRINTLN(x) Serial.println(x)
#else
#define DEBUGPRINT(x)
#define DEBUGPRINTLN(x)
#endif
//
// definitions
//
#define SIGNAL_PIN 6 // @EB-setup the digital output pin
#define NUM_OF_PIXELS 93 // the number of pixels
#define MAIN_PIXEL_OFFSET 1 // offset for pixel 0
byte ledNumOfRings = 6; // number of rings
int ledPos[][2] = { // positions of the leds for each ring. note: start with 0
{ 0, 31},
{32, 55},
{56, 71},
{72, 83},
{84, 91},
{92, 92}
};
//
// includes
//
#include <Adafruit_NeoPixel.h>
//
// settings
//
int maxBrightness = 30;
int ledBrightness = maxBrightness;
int flowDelay = 60;
int circleDelay = 20;
int fadeStep = 2;
int sparkleDelay = 40;
int sparkleCount = 350;
int sparkleRandomMax = 100;
int sparkleRandomLimit = 40;
int ringsDelay = 40;
int ringsCycleDelay = 475;
int ringsCount = 350;
int circleFadeDelay = 40;
int circleFadeCycleDelay = 60;
int circleFadeCount = NUM_OF_PIXELS * 5;
//
// setup variables
//
int pixelOffset = 0;
int colorRange = 0;
uint32_t stripColor[NUM_OF_PIXELS + 6];
Adafruit_NeoPixel pixels = Adafruit_NeoPixel(NUM_OF_PIXELS, SIGNAL_PIN, NEO_GRB + NEO_KHZ800); // grb
//
// setup
//
void setup() {
#ifdef DEBUGPRINT
Serial.begin(115200);
DEBUGPRINTLN("Setup");
#endif
randomSeed(analogRead(0));
pixels.begin();
setPixelColors(true, 0, false);
#ifdef DEBUGCHECKPIXEL0
DEBUGPRINTLN("Check pixel 0");
setOneLedRing(1, 0, pixels.Color(20, 20, 20));
pixels.show();
checkAndDelay(7500);
#endif
}
//
// main loop
//
void loop() {
DEBUGPRINTLN("Main loop");
setStripColorsRainbow();
circleIn();
circleOut();
flow();
rainbow();
circleFade();
ringsFade();
sparkleFade();
} // loop
//
// functions
//
unsigned long checkAndDelay(int delayTime) {
unsigned long startTime = millis();
unsigned long result = 0;
while ((millis() - startTime) < delayTime) {
delay(1);
}
return 0;
} // checkAndDelay
//
// functions for animations
//
void flow() {
DEBUGPRINTLN(" Anim: Walk");
// blue circle in and out
setStripColors(true, 0, "B"); inToOut(true); outToIn(false);
setStripColors(true, 0, "RG"); inToOut(true); outToIn(false);
// multiple colors circle in and out
setStripColors(true, 0, "R"); inToOut(true);
setStripColors(true, 0, "G"); inToOut(true);
setStripColors(true, 0, "B"); inToOut(true);
setStripColors(true, 0, "RB"); inToOut(true);
setStripColors(true, 0, "GB"); inToOut(true);
setStripColors(true, 0, "RG"); inToOut(true);
setStripColors(true, 0, "RGB"); inToOut(true);
outToIn(false);
// RGB circle in and out
setStripColors(false, 0, "R"); setStripColors(false, 1, "G"); setStripColors(false, 2, "B");
setStripColors(false, 3, "R"); setStripColors(false, 4, "G"); setStripColors(false, 5, "B");
inToOut(true); inToOut(false);
inToOut(true); inToOut(false);
outToIn(true); outToIn(false);
inToOut(true); outToIn(false);
inToOut(true); outToIn(false);
} // flow()
void inToOut(bool onOff) {
for (int i = ledNumOfRings - 1; i >= 0; i--) {
setPixelColors(false, i, onOff);
checkAndDelay(flowDelay);
}
} // inToOut
void outToIn(bool onOff) {
for (int i = 0; i <= ledNumOfRings; i++) {
setPixelColors(false, i, onOff);
checkAndDelay(flowDelay);
}
} // outToIn
void circleIn() {
DEBUGPRINTLN(" Anim: Circle in");
for (int i = 0; i < NUM_OF_PIXELS; i++) {
setOneLed(i - MAIN_PIXEL_OFFSET, stripColor[(i + pixelOffset) % NUM_OF_PIXELS]);
pixels.show();
checkAndDelay(circleDelay);
}
} // circleIn
void circleOut() {
DEBUGPRINTLN(" Anim: Circle out");
for (int i = 0; i < NUM_OF_PIXELS; i++) {
setOneLed(i - MAIN_PIXEL_OFFSET, 0);
pixels.show();
checkAndDelay(circleDelay);
}
} // circleOut
void rainbow() {
DEBUGPRINTLN(" Anim: Rainbow");
for (int j = 0; j < 4 * 256; j++) {
for (int h = ledNumOfRings - 1; h >= 0; h--) {
for (int i = ledPos[h][0]; i <= ledPos[h][1]; i++) {
stripColor[i] = wheel((i+j) & 255);
}
setPixelColors(false, h, true);
}
}
} // rainbow
void sparkleFade() {
DEBUGPRINTLN(" Anim: Fading sparkles");
int j, i, maxLoop, pixel;
int fadePos[NUM_OF_PIXELS] = {};
int fadeDir[NUM_OF_PIXELS] = {};
maxLoop = sparkleCount + (maxBrightness / fadeStep);
for (j = 0; j < maxLoop; j++) {
if (j < sparkleCount) { // stop adding sparkles after reaching the max...
setStripColorsRainbowCycle();
if (random(sparkleRandomMax) < sparkleRandomLimit) {
pixel = random(NUM_OF_PIXELS);
if (fadeDir[pixel] == 0)
fadeDir[pixel] = 1;
}
} else if (j == sparkleCount) { // ...then fade out the sparkles
for (i = 0; i < NUM_OF_PIXELS; i++) {
if (fadeDir[i] == 1)
fadeDir[i] = 2;
}
}
plotFadingPixels(fadePos, fadeDir);
checkAndDelay(sparkleDelay);
}
} // sparkleFade
void ringsFade() {
DEBUGPRINTLN(" Anim: Fading rings");
static long int startCycleTime;
int j, i, maxLoop;
int ringNum = ledNumOfRings - 1, ringDir = -1;
int fadePos[NUM_OF_PIXELS] = {};
int fadeDir[NUM_OF_PIXELS] = {};
maxLoop = ringsCount + (maxBrightness / fadeStep);
for (j = 0; j < maxLoop; j++) {
if (j < ringsCount) {
setStripColorsRainbowCycle();
if ((millis() - startCycleTime) > ringsCycleDelay) {
startCycleTime = millis();
for (int i = ledPos[ringNum][0]; i <= ledPos[ringNum][1]; i++)
fadeDir[i] = 1;
ringNum += ringDir;
if (ringNum < 0) { ringNum = 0; ringDir = -ringDir; }
if (ringNum >= ledNumOfRings) { ringNum = ledNumOfRings - 1; ringDir = -ringDir; }
}
} else if (j == ringsCount) {
for (i = 0; i < NUM_OF_PIXELS; i++) {
if (fadeDir[i] == 1)
fadeDir[i] = 2;
}
}
plotFadingPixels(fadePos, fadeDir);
checkAndDelay(ringsDelay);
}
} // ringsFade
void circleFade() {
DEBUGPRINTLN(" Anim: Fading circle");
static long int startCycleTime;
int j, i, maxLoop;
int pixelNum = 0, pixelDir = -1;
int fadePos[NUM_OF_PIXELS] = {};
int fadeDir[NUM_OF_PIXELS] = {};
maxLoop = circleFadeCount + (maxBrightness / fadeStep);
for (j = 0; j < maxLoop; j++) {
if (j < circleFadeCount) {
setStripColorsRainbowCycle();
if ((millis() - startCycleTime) > circleFadeCycleDelay) {
startCycleTime = millis();
fadeDir[pixelNum] = 1;
pixelNum += pixelDir;
if (pixelNum < 0) { pixelNum = 0; pixelDir = -pixelDir; }
if (pixelNum >= NUM_OF_PIXELS) { pixelNum = NUM_OF_PIXELS - 1; pixelDir = -pixelDir; }
}
} else if (j == circleFadeCount) {
for (i = 0; i < NUM_OF_PIXELS; i++) {
if (fadeDir[i] == 1)
fadeDir[i] = 2;
}
}
plotFadingPixels(fadePos, fadeDir);
checkAndDelay(circleFadeDelay);
}
} // ringsFade
void plotFadingPixels(int fadePos[], int fadeDir[]) {
int r, g, b, i;
uint32_t pixelColor;
for (i = 0; i < NUM_OF_PIXELS; i++) {
if (fadeDir[i] == 0)
pixels.setPixelColor(i, 0);
else {
if (fadeDir[i] == 1) {
fadePos[i] += fadeStep;
if (fadePos[i] >= maxBrightness) {
fadeDir[i] = 2;
fadePos[i] = maxBrightness;
}
} else {
fadePos[i] -= fadeStep;
if (fadePos[i] <= 0) {
fadeDir[i] = 0;
fadePos[i] = 0;
}
}
pixelColor = stripColor[i];
r = (pixelColor >> 16) * fadePos[i] / maxBrightness;
g = ((pixelColor >> 8) & 0xFF) * fadePos[i] / maxBrightness;
b = (pixelColor & 0xFF) * fadePos[i] / maxBrightness;
pixelColor = pixels.Color(r, g, b);
pixels.setPixelColor(i, pixelColor);
}
}
pixels.show();
} // plotFadingPixels
//
// functions for settings colors
//
void setStripColors(bool allRings, byte ringNum, String colorType) {
int r = 0, g = 0, b = 0;
int startRingNum = ringNum, endRingNum = ringNum;
if (colorType.indexOf("R") >= 0) r = ledBrightness;
if (colorType.indexOf("G") >= 0) g = ledBrightness;
if (colorType.indexOf("B") >= 0) b = ledBrightness;
if (allRings) { startRingNum = 0; endRingNum = ledNumOfRings - 1; }
for (int h = startRingNum; h <= endRingNum; h++) {
for (int i = ledPos[h][0]; i <= ledPos[h][1]; i++) {
stripColor[i] = pixels.Color(r, g, b);
}
}
}
void setStripColorsRGB() {
int r, g, b;
colorRange = 2;
r = ledBrightness;
g = ledBrightness;
b = ledBrightness;
for (int i = 0; i < NUM_OF_PIXELS ; i += 3) {
stripColor[i] = pixels.Color(r, 0, 0);
stripColor[i+1] = pixels.Color(0, g, 0);
stripColor[i+2] = pixels.Color(0, 0, b);
}
}
void setStripColorsRainbow() {
for (int i = 0; i < NUM_OF_PIXELS; i++)
stripColor[i] = wheel((i * 255 / NUM_OF_PIXELS));
}
void setStripColorsRainbowCycle() {
static byte startPos;
for (int i = 0; i < NUM_OF_PIXELS; i++)
stripColor[i] = wheel((startPos + i) & 255);
startPos += 2;
startPos = startPos & 255;
}
void setPixelColors(bool allRings, byte ringNum, bool onOff) {
int pixelCol;
int startRingNum = ringNum, endRingNum = ringNum;
if (allRings) { startRingNum = 0; endRingNum = ledNumOfRings - 1; }
for (int h = startRingNum; h <= endRingNum; h++) {
for (int i = ledPos[h][0]; i <= ledPos[h][1]; i++) {
pixelCol = i + pixelOffset;
if (pixelCol > ledPos[h][1]) pixelCol = ledPos[h][0];
if (pixelCol < ledPos[h][0]) pixelCol = ledPos[h][1];
if (onOff)
setOneLedRing(h, i, stripColor[pixelCol]);
else
setOneLedRing(h, i, 0);
}
}
pixels.show();
} // setPixelColors
void setOneLedRing(int ringNum, int pixel, uint32_t color) {
int targetPixel;
targetPixel = pixel + MAIN_PIXEL_OFFSET;
if (targetPixel > ledPos[ringNum][1])
targetPixel = ledPos[ringNum][0];
pixels.setPixelColor(targetPixel, color);
} // setOneLedRing
void setOneLed(int pixel, uint32_t color) {
int targetPixel;
targetPixel = pixel + MAIN_PIXEL_OFFSET;
if (targetPixel > NUM_OF_PIXELS)
targetPixel = NUM_OF_PIXELS;
pixels.setPixelColor(targetPixel, color);
} // setOneLedRing
// Input a value 0 to 255 to get a color value.
// The colours are a transition r - g - b - back to r.
uint32_t wheel(byte wheelPos) {
int r, g, b;
wheelPos = 255 - wheelPos;
if (wheelPos < 85) {
r = 255 - wheelPos * 3;
g = 0;
b = wheelPos * 3;
} else if (wheelPos < 170) {
wheelPos -= 85;
r = 0;
g = wheelPos * 3;
b = 255 - wheelPos * 3;
} else {
wheelPos -= 170;
r = wheelPos * 3;
g = 255 - wheelPos * 3;
b = 0;
}
r = (float) (r * ledBrightness / 255);
g = (float) (g * ledBrightness / 255);
b = (float) (b * ledBrightness / 255);
return pixels.Color(r, g, b);
} // wheel
Comments