Hardware components | ||||||
| × | 91 | ||||
![]() |
| × | 1 | |||
Software apps and online services | ||||||
![]() |
| |||||
Hand tools and fabrication machines | ||||||
![]() |
|
I saw the design for this on Thingiverse (https://www.thingiverse.com/thing:1966885) but it was too big for my 3D printer so I decided to scale it down to fit 5mm LEDs instead of 12mm LEDs the LEDs I used were APA106-F5 which I got 100 of from eBay.
To fit the LEDs I printed the snowflake at 42% scale. You can either print it yourself or order it from a service such as 3D Hubs or Shapeways.
Once this was all printed I started on the electronics, you will need at least 91 APA106-F5 LEDs to put in the frame the pinout for one of these is as below.
To wire these connect all the VCC lines together, all the GND lines together and the Data Out of each LED to the Data In on the next I wired them around the flake in this order.
This should be carried out for all 91 LEDs around the flake.
Next stage is to program it, as a controller I used the Arduino Uno.
To wire, connect the VCC and GND lines to a 5 volts supply to power the LEDs. Now connect the GND line to the GND on the Arduino whilst connecting the Data In line from the first LED to an Arduino Pin (I used 6 but it doesn't matter which).
I also connected a button on pin 5 to switch between different animations.
Before uploading the code make sure you have the Arduino NeoPixel library to check this, go to Sketch --> Include Library --> Manage Libraries --> Then search NeoPixel and check the list for "Adafruit NeoPixel by Adafruit". It will say if this is installed, if it isn't then install it before uploading code to the Arduino.
CodeThere is some code attached below, with some different effects for the snowflake. Or, there is some more code here: https://github.com/Equinaut19/RGBLEDSnowflake
#include <Adafruit_NeoPixel.h>
#ifdef __AVR__
#include <avr/power.h>
#endif
int numberOfModes=11;
int PIN = 6;
int NUMPIXELS = 91;
float brightness = 0.05;
int mode = 1;
Adafruit_NeoPixel pixels = Adafruit_NeoPixel(NUMPIXELS, PIN, NEO_RGB + NEO_KHZ400);
/*There are 7 wings including the middle*/int wings[] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,3,3,3,3,3,3,3,3,3,3,3,3,3,3,4,4,4,4,4,4,4,4,4,4,4,4,4,4,5,5,5,5,5,5,5,5,5,5,5,5,5,5,6,6,6,6,6,6,6};
/*There are 8 rings*/int rings[] = {5, 4, 3, 1, 0, 1, 0, 1, 0, 1, 0, 0, 1, 2, 5, 4, 3, 1, 0, 1, 0, 1, 0, 1, 0, 0, 1, 2, 5, 4, 3, 1, 0, 1, 0, 1, 0, 1, 0, 0, 1, 2, 5, 4, 3, 1, 0, 1, 0, 1, 0, 1, 0, 0, 1, 2, 5, 4, 3, 1, 0, 1, 0, 1, 0, 1, 0, 0, 1, 2, 5, 4, 3, 1, 0, 1, 0, 1, 0, 1, 0, 0, 1, 2, 6, 6, 6, 6, 6, 6, 7};
/*There are 27 rows*/int rows[] = {18, 19, 21, 22, 21, 24, 25, 25, 26, 24, 25, 21, 22, 23, 15, 16, 17, 16, 15, 17, 16, 19, 20, 20, 21, 20, 19, 18, 11, 10, 9, 7, 6, 6, 4, 7, 6, 9, 10, 11, 10, 8, 8, 6, 5, 4, 5, 2, 1, 1, 0, 2, 1, 5, 4, 3, 11, 10, 9, 7, 6, 6, 4, 7, 6, 9, 10, 11, 10, 8, 15, 16, 17, 19, 20, 20, 21, 19, 20, 17, 16, 15, 16, 18, 14, 15, 14, 12, 11, 12, 13};
/*There are 17 columns*/int cols[] = {8, 8, 8, 9, 10, 9, 10, 8, 8, 7, 6, 6, 7, 8, 11, 12, 13, 14, 14, 15, 16, 15, 16, 14, 14, 12, 13, 14, 11, 12, 13, 13, 12, 14, 14, 15, 16, 15, 16, 14, 14, 14, 8, 8, 8, 7, 6, 7, 6, 8, 8, 9, 10, 10, 9, 8, 5, 4, 3, 3, 4, 2, 2, 1, 0, 1, 0, 2, 2, 2, 5, 4, 3, 3, 4, 2, 2, 1, 0, 1, 0, 2, 2, 2, 7, 8, 9, 9, 8, 7, 8};
void setup() {
pinMode(5,INPUT);
pixels.begin();
Serial.begin(9600);
}
void loop() {
if (Serial.available() > 0) {mode = Serial.parseInt();clearLeds();}
if (digitalRead(5)==HIGH) {changeMode();}
if (mode == 0) {mode0();}
else if (mode == 1) {mode1();}
else if (mode == 2) {mode2();}
else if (mode == 3) {mode3();}
else if (mode == 4) {mode4();}
else if (mode == 5) {mode5();}
else if (mode == 6) {mode6();}
else if (mode == 7) {mode7();}
else if (mode == 8) {mode8();}
else if (mode == 9) {mode9();}
else if (mode == 10) {mode10();}
else if (mode == 11) {mode11();}
pixels.show();
}
void clearLeds() {
for (int i=0;i<91;i++) {
pixels.setPixelColor(i,pixels.Color(0,0,0));
}
pixels.show();
}
void changeMode() {
mode+=1;
if(mode>numberOfModes) {mode=0;}
clearLeds();
for (int i=0; i<=mode;i++) {pixels.setPixelColor(i,pixels.Color(255,255,255));}
pixels.show();
delay(2000);
clearLeds();}
void wipe(int r,int g,int b,int dist = 100,int dir=0) {
if (dir==0) {for (int row=0; row<8; row++) {for (int i=0;i<91;i++) {if (rings[i]==row) {pixels.setPixelColor(i,pixels.Color(r,g,b));}} delay(dist); pixels.show();}} //Wipes from outside to inside
else if (dir==1) {for (int row=7; row>=0; row--) {for (int i=0;i<91;i++) {if (rings[i]==row) {pixels.setPixelColor(i,pixels.Color(r,g,b));}} delay(dist); pixels.show();}}//Wipes from inside to outside
else if (dir==2) {for (int row=0; row<27; row++) {for (int i=0;i<91;i++) {if (rows[i]==row) {pixels.setPixelColor(i,pixels.Color(r,g,b));}} delay(dist); pixels.show();}}//Wipes from top to bottom
else if (dir==3) {for (int row=26; row>=0; row--) {for (int i=0;i<91;i++) {if (rows[i]==row) {pixels.setPixelColor(i,pixels.Color(r,g,b));}} delay(dist); pixels.show();}}//Wipes from bottom to top
else if (dir==4) {for (int row=0; row<17; row++) {for (int i=0;i<91;i++) {if (cols[i]==row) {pixels.setPixelColor(i,pixels.Color(r,g,b));}} delay(dist); pixels.show();}}//Wipes from left to right
else if (dir==5) {for (int row=16; row>=0; row--) {for (int i=0;i<91;i++) {if (cols[i]==row) {pixels.setPixelColor(i,pixels.Color(r,g,b));}} delay(dist); pixels.show();}}//Wipes from right to left
else if (dir==6) {for (int row=5; row>=0; row--) {for (int i=0;i<91;i++) {if (wings[i]==row) {pixels.setPixelColor(i,pixels.Color(r,g,b));}} delay(dist); pixels.show();}}//Wipes through each wing clockwise
else if (dir==7) {for (int row=0; row<6; row++) {for (int i=0;i<91;i++) {if (wings[i]==row) {pixels.setPixelColor(i,pixels.Color(r,g,b));}} delay(dist); pixels.show();}}//Wipes through each wing counter-clockwise
}
void split(int r,int g,int b,int dist = 100, int dir=0) {
if (dir==0) {for (int row=0; row<=13;row++) {for (int i=0;i<91;i++) {if (rows[i]==row || rows[i]==26-row) {pixels.setPixelColor(i,pixels.Color(r,g,b));}} delay(dist);pixels.show();}} //Wipes inwards
else if (dir==1) {for (int row=13; row>=0;row--) {for (int i=0;i<91;i++) {if (rows[i]==row || rows[i]==26-row) {pixels.setPixelColor(i,pixels.Color(r,g,b));}} delay(dist);pixels.show();}} //Wipes outwards
else if (dir==2) {for (int col=0; col<=8;col++) {for (int i=0;i<91;i++) {if (cols[i]==col || cols[i]==16-col) {pixels.setPixelColor(i,pixels.Color(r,g,b));}} delay(dist);pixels.show();}} //Wipes inwards
else if (dir==3) {for (int col=8; col>=0;col--) {for (int i=0;i<91;i++) {if (cols[i]==col || cols[i]==16-col) {pixels.setPixelColor(i,pixels.Color(r,g,b));}} delay(dist);pixels.show();}} //Wipes outwards
}
void mode0() {
for (int i=0; i<91; i++) {
pixels.setPixelColor(i,pixels.Color((100*i/91)*brightness,(100-100*i/91)*brightness,0));
pixels.show();
delay(10);
}
for (int i=90; i>=0; i--) {
pixels.setPixelColor(i,pixels.Color(0,0,0));
pixels.show();
delay(10);
}
}
void mode1() {
for (int i=0; i<91; i++) {
pixels.setPixelColor(i,pixels.Color((100*i/91)*brightness,0,(100-100*i/91)*brightness));
pixels.show();
delay(15);
}
delay(1000);
for (int i=90; i>=0; i--) {
pixels.setPixelColor(i,pixels.Color((100*i/91)*brightness,(100-100*i/91)*brightness,0));
pixels.show();
delay(15);
}
delay(1000);
}
void mode2() {
int dist = 100;
wipe(255*brightness,0,0,dist,0);
wipe(0,255*brightness,0,dist,1);
wipe(0,0,255*brightness,dist,0);
wipe(255*brightness,0,0,dist,1);
wipe(0,255*brightness,0,dist,0);
wipe(0,0,255*brightness,dist,1);
}
void mode3() {
int dist = 20;
wipe(255*brightness,0,0,dist,2);
wipe(0,255*brightness,0,dist,3);
wipe(0,0,255*brightness,dist,2);
wipe(255*brightness,0,0,dist,3);
wipe(0,255*brightness,0,dist,2);
wipe(0,0,255*brightness,dist,3);
}
void mode4() {
int dist = 30;
wipe(255*brightness,0,0,dist,4);
wipe(0,255*brightness,0,dist,5);
wipe(0,0,255*brightness,dist,4);
wipe(255*brightness,0,0,dist,5);
wipe(0,255*brightness,0,dist,4);
wipe(0,0,255*brightness,dist,5);
}
void mode5() {
int dist = 30;
wipe(255*brightness,0,0,dist,2);
wipe(0,255*brightness,0,dist,4);
wipe(0,0,255*brightness,dist,3);
wipe(255*brightness,0,0,dist,5);
wipe(0,255*brightness,0,dist,0);
wipe(0,0,255*brightness,dist,1);
}
void mode6() {
int dist = 150;
wipe(255*brightness,0,0,dist,6);
wipe(0,255*brightness,0,dist,6);
wipe(0,0,255*brightness,dist,6);
wipe(255*brightness,0,0,dist,6);
wipe(0,255*brightness,0,dist,6);
wipe(0,0,255*brightness,dist,6);
}
void mode7() {
int r = 255*brightness;int g=0;int b=0;int dist = 50;
int r2 = 0;int g2 = 255*brightness; int b2 = 0;
for (int row=0; row<27; row++) {
int invrow = 26-row;
for (int i=0;i<91;i++) {
if (rows[i]==row && (wings[i]==0 || wings[i]==3 || wings[i]==6)) {pixels.setPixelColor(i,pixels.Color(r,g,b));}
if (rows[i]==invrow && !(wings[i]==0 || wings[i]==3 || wings[i]==6)) {pixels.setPixelColor(i,pixels.Color(r2,g2,b2));}
}
delay(dist); pixels.show();
}
clearLeds();
//else if (dir==3) {for (int row=26; row>=0; row--) {for (int i=0;i<91;i++) {if (rows[i]==row) {pixels.setPixelColor(i,pixels.Color(r,g,b));}} delay(dist); pixels.show();}}
}
void mode8() {
int dist = 100;
split(255*brightness,0,0,dist,2);
split(0,255*brightness,0,dist,3);
}
void mode9() {
int r = 255;
int g = 0;
int b = 0;
int stage = 0;
int diff=5;
while (stage<=5) {
if (stage==0) {g+=diff; if (g>=255) {g=255; stage+=1;}}
else if (stage==1) {r-=diff; if (r<=0) {r=0; stage+=1;}}
else if (stage==2) {b+=diff; if (b>=255) {b=255; stage+=1;}}
else if (stage==3) {g-=diff; if (g<=0) {g=0; stage+=1;}}
else if (stage==4) {r+=diff; if (r>=255) {r=255; stage+=1;}}
else if (stage==5) {b-=diff; if (b<=0) {b=0; stage+=1;}}
for (int i=0; i<91; i++) {pixels.setPixelColor(i,pixels.Color(r*brightness,g*brightness,b*brightness));}
pixels.show();
}
}
void mode10() {
int r[] = {255,223,191,159,127,95,63,31};
int g[] = {0,0,0,0,0,0,0,0};
int b[] = {0,0,0,0,0,0,0,0};
int stage[] = {0,0,0,0,0,0,0,0};
int diff=20;
while (stage[7]<=5) {
for (int j=0; j<8; j++) {
if (stage[j]==0) {g[j]+=diff; if (g[j]>=255) {g[j]=255; stage[j]+=1;}}
else if (stage[j]==1) {r[j]-=diff; if (r[j]<=0) {r[j]=0; stage[j]+=1;}}
else if (stage[j]==2) {b[j]+=diff; if (b[j]>=255) {b[j]=255; stage[j]+=1;}}
else if (stage[j]==3) {g[j]-=diff; if (g[j]<=0) {g[j]=0; stage[j]+=1;}}
else if (stage[j]==4) {r[j]+=diff; if (r[j]>=255) {r[j]=255; stage[j]+=1;}}
else if (stage[j]==5) {b[j]-=diff; if (b[j]<=0) {r[j]=255;g[j]=0;b[j]=0; stage[j]+=1;}}
for (int i=0; i<91; i++) {if (rings[i]==j) {pixels.setPixelColor(i,pixels.Color(r[j]*brightness,g[j]*brightness,b[j]*brightness));}}
pixels.show();
}
}
}
void mode11() {
int r[] = {255,246,237,228,219,210,201,192,183,174,165,156,147,138,129,120,111,102,93,84,75,66,57,48,39,30,21};
int g[] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
int b[] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
int stage[] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
int diff=40;
while (stage[26]<=5) {
for (int j=0; j<27; j++) {
if (stage[j]==0) {g[j]+=diff; if (g[j]>=255) {g[j]=255; stage[j]+=1;}}
else if (stage[j]==1) {r[j]-=diff; if (r[j]<=0) {r[j]=0; stage[j]+=1;}}
else if (stage[j]==2) {b[j]+=diff; if (b[j]>=255) {b[j]=255; stage[j]+=1;}}
else if (stage[j]==3) {g[j]-=diff; if (g[j]<=0) {g[j]=0; stage[j]+=1;}}
else if (stage[j]==4) {r[j]+=diff; if (r[j]>=255) {r[j]=255; stage[j]+=1;}}
else if (stage[j]==5) {b[j]-=diff; if (b[j]<=0) {r[j]=255;g[j]=0;b[j]=0; stage[j]+=1;}}
for (int i=0; i<91; i++) {if (rows[i]==j) {pixels.setPixelColor(i,pixels.Color(r[j]*brightness,g[j]*brightness,b[j]*brightness));}}
pixels.show();
}
}
}
/* Written by James Cameron December 2018
* For use with APA106-F5 LEDs on
* https://www.thingiverse.com/thing:1966885 by hoangnam
* Requires Adafruit NeoPixel Library
*/
#include <Adafruit_NeoPixel.h>
#ifdef __AVR__
#include <avr/power.h>
#endif
int PIN = 6;
int NUMPIXELS = 91;
Adafruit_NeoPixel pixels = Adafruit_NeoPixel(NUMPIXELS, PIN, NEO_RGB + NEO_KHZ400);
int mode = 0;
int wings[][14] = {{0,1,2,3,4,5,6,7,8,9,10,11,12,13},{14,15,16,17,18,19,20,21,22,23,24,25,26,27},{28,29,30,31,32,33,34,35,36,37,38,39,40,41},{42,43,44,45,46,47,48,49,50,51,52,53,54,55},{56,57,58,59,60,61,62,63,64,65,66,67,68,69},{70,71,72,73,74,75,76,77,78,79,80,81,82,83}};
int oLayers[][30] = {{4,6,8,10,11, 18,20,22,24,25, 32,34,36,38,39, 46,48,50,52,53, 60,62,64,66,67, 74,76,78,80,81}, //Outer Layer 1
{3,5,7,9,12, 17,19,21,23,26, 31,33,35,37,40, 45,47,49,51,54, 59,61,63,65,68, 73,75,77,79,82}, //Outer Layer 2
{13,27,41,55,69,83}, //Outer Layer 3
{2,16,30,44,58,72}, //Outer Layer 4
{1,15,29,43,57,71}, //Outer Layer 5
{0,14,28,42,56,70}, //Outer Layer 6
{84,85,86,87,88,89}, //Outer Layer 7
{90}}; //Outer Layer 8
int oLayersLengths[] = {30,30,6,6,6,6,6,1};
int vLayers[][7] = {{50},//Vertical Layer 1
{48,49,52},//Vertical Layer 2
{47,51},//Vertical Layer 3
{55},//Vertical Layer 4
{62,45,54,34},//Vertical Layer 5
{46,53,44},//Vertical Layer 6
{43,60,61,32,33,36,64},//Vertical Layer 7
{63,59,31,35},//Vertical Layer 8
{69,42,41},//Vertical Layer 9
{65,58,30,37},//Vertical Layer 10
{66,68,57,29,40,38},//Vertical Layer 11
{67,56,88,28,39},//Vertical Layer 12
{89,87},//Vertical Layer 13
{90},//Vertical Layer 14
{84,86},//Vertical Layer 15
{70,85,14,81,18},//Vertical Layer 16
{80,82,71,15,17,20},//Vertical Layer 17
{79,72,16,19},//Vertical Layer 18
{83,0,27},//Vertical Layer 19
{77,73,1,26,21},//Vertical Layer 20
{78,74,25,22,23,75},//Vertical Layer 21
{76,11,2,4,24},//Vertical Layer 22
{12,3},//Vertical Layer 23
{13},//Vertical Layer 24
{9,5},//Vertical Layer 25
{10,7,6},//Vertical Layer 26
{8}};//Vertical Layer 27
int vLayersLengths[] = {1,3,2,1,4,3,7,4,3,4,6,5,2,1,2,5,6,4,3,5,6,5,2,1,2,3,1};
float brightness = 0.1;
void setup() {
pinMode(5,INPUT);
pixels.begin();
Serial.begin(9600);
}
void loop() {
if (Serial.available() > 0) {mode = Serial.parseInt();clearLeds();}
if (digitalRead(5)==HIGH) {changeMode();}
if (mode == 0) {mode0();}
else if (mode == 1) {mode1();}
else if (mode == 2) {mode2();}
else if (mode == 3) {mode3();}
pixels.show();
}
void clearLeds() {
for (int i=0;i<91;i++) {
pixels.setPixelColor(i,pixels.Color(0,0,0));
}
pixels.show();
}
void changeMode() {
mode+=1;
if(mode>3) {mode=0;}
clearLeds();
for (int i=0; i<=mode;i++) {
pixels.setPixelColor(i,pixels.Color(255,255,255));
}
pixels.show();
delay(2000);
clearLeds();
}
void mode0() {
for (int i=0; i<91; i++) {
pixels.setPixelColor(i,pixels.Color((100*i/91)*brightness,(100-100*i/91)*brightness,0));
pixels.show();
delay(10);
}
for (int i=90; i>=0; i--) {
pixels.setPixelColor(i,pixels.Color(0,0,0));
pixels.show();
delay(10);
}
}
void mode1() {
for (int i=0; i<91; i++) {
pixels.setPixelColor(i,pixels.Color((100*i/91)*brightness,0,(100-100*i/91)*brightness));
pixels.show();
delay(15);
}
delay(1000);
for (int i=90; i>=0; i--) {
pixels.setPixelColor(i,pixels.Color((100*i/91)*brightness,(100-100*i/91)*brightness,0));
pixels.show();
delay(15);
}
delay(1000);
}
void owipe(int r,int g,int b,int dist = 100,bool dir=true) { //Function to wipe a particular colour from inside to outside or outside to inside
if (dir) {for (int row=0;row<7;row++) {for (int i=0;i<oLayersLengths[row];i++) {pixels.setPixelColor(oLayers[row][i],pixels.Color(r,g,b));} delay(dist); pixels.show();}}
else {for (int row=6;row>0;row--) {for (int i=0;i<oLayersLengths[row];i++) {pixels.setPixelColor(oLayers[row][i],pixels.Color(r,g,b));} delay(dist); pixels.show();}}
}
void vwipe(int r,int g,int b,int dist = 100,bool dir=true) {
if (dir) {for (int row=0;row<27;row++) {for (int i=0;i<vLayersLengths[row];i++) {pixels.setPixelColor(vLayers[row][i],pixels.Color(r,g,b));} delay(dist); pixels.show();}}
else {for (int row=26;row>0;row--) {for (int i=0;i<vLayersLengths[row];i++) {pixels.setPixelColor(vLayers[row][i],pixels.Color(r,g,b));} delay(dist); pixels.show();}}
}
void mode2() {
int dist = 100;
owipe(255*brightness,0,0,dist);
owipe(0,255*brightness,0,dist,false);
owipe(0,0,255*brightness,dist);
owipe(255*brightness,0,0,dist,false);
owipe(0,255*brightness,0,dist);
owipe(0,0,255*brightness,dist,false);
}
void mode3() {
int dist = 20;
vwipe(255*brightness,0,0,dist);
vwipe(0,255*brightness,0,dist,false);
vwipe(0,0,255*brightness,dist);
vwipe(255*brightness,0,0,dist,false);
vwipe(0,255*brightness,0,dist);
vwipe(0,0,255*brightness,dist,false);
}
Comments
Please log in or sign up to comment.