James Cameron
Published © GPL3+

RGB LED Snowflake with Arduino Uno

A 3D-printed snowflake made with Arduino Uno. Has 91 addressable RGB LEDs.

IntermediateWork in progress20,903
RGB LED Snowflake with Arduino Uno

Things used in this project

Hardware components

APA106-F5
×91
Arduino UNO
Arduino UNO
×1

Software apps and online services

Arduino IDE
Arduino IDE

Hand tools and fabrication machines

Soldering iron (generic)
Soldering iron (generic)

Story

Read more

Custom parts and enclosures

Snowflake

Files to print the snowflake

Code

Arduino Code Version2

C/C++
New effects from the first code
#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();
        }
      }
}

Arduino Code

C/C++
Upload to Arduino to run with Snowflake
/* 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);  
}

RGB LED Snowflake

Some code with more effects

Credits

James Cameron

James Cameron

3 projects • 7 followers
Thanks to Hoangnam.

Comments