Jiří Praus
Published © CC BY-NC-SA

Arduinoflake!

A freeform interactive snowflake animated by Arduino Nano. Using 17 independent PWM channels and touch sensor it can create awesome effects!

AdvancedFull instructions provided8 hours8,976

Things used in this project

Story

Read more

Schematics

Schematics with parts list

Schematic arduinoflake sheet 1 20181130203444 ilmzgkak97

Code

snowflake.ino

Arduino
Source code
#include "SoftPWM.h"
#include <ADCTouchSensor.h>

byte edgeLedPins[] = {13, A4, A5, 2, 8, 12};
byte middleLedPins[] = {10, 6, 3, 5, 9, 11};
byte innerLedPins[] = {A2, A3, A1, 4, 7, A1};

ADCTouchSensor touchSensor = ADCTouchSensor(A0, 1); 

void setup() {
  Serial.begin(115200);
  SoftPWMBegin();
}

byte animation = 0;
long touchAt = 0;

void loop() {
  switch (animation) {
    case 0:
      _fill(100);
      break;
    case 1:
      shinyAnimation();
      //fadingAnimation();
      break;
    case 2:
      circleAnimation();
      break;
    case 3:
      loopAnimation();
      break;
    case 4:
      fireworkAnimation();
      fireworkAnimation();
      fireworkAnimation();
      fireworkAnimation();
      fireworkAnimation();
      fireworkAnimation();
      animation ++;
      break;
    case 5:
      smileAnimation();
      break;
    default:
      animation = 0;
      break;
  }
  int touchValue = touchSensor.read();
  if (touchAt + 2000 < millis() && touchValue > 1000) {
    touchAt = millis(); // touch down, cold down timeout is 2s
    animation ++;
    _fill(0);
  }
}

void fireworkAnimation() {
  for (int i = 0; i < 4; i++) {
    SoftPWMSet(innerLedPins[i], 100);
    delay(100);
  }
  SoftPWMSet(innerLedPins[4], 100);
  for (int i = 0; i < 6; i++) {
    SoftPWMSet(middleLedPins[i], 255);
  }
  delay(50);
  for (int i = 0; i < 6; i++) {
    SoftPWMSet(innerLedPins[i], 0);
    SoftPWMSet(edgeLedPins[i], 255);
  }
  delay(50);
  for (int i = 0; i < 6; i++) {
    SoftPWMSet(middleLedPins[i], 0);
  }
  delay(50);
  _fill(0);
}

void smileAnimation() {
  SoftPWMSet(innerLedPins[1], 100);
  SoftPWMSet(innerLedPins[3], 100);
  SoftPWMSet(middleLedPins[0], 255);
  SoftPWMSet(middleLedPins[5], 255);
  SoftPWMSet(edgeLedPins[2], 255);
  SoftPWMSet(edgeLedPins[3], 255);
  delay(2000);
  SoftPWMSet(innerLedPins[1], 0);
  SoftPWMSet(innerLedPins[3], 0);
  delay(100);
  SoftPWMSet(innerLedPins[1], 100);
  SoftPWMSet(innerLedPins[3], 100);
  delay(100);
  SoftPWMSet(innerLedPins[1], 0);
  SoftPWMSet(innerLedPins[3], 0);
  delay(100);
}

byte circleState[] = {100, 55, 10};
byte circleStateAnimation[] = {1, 1, 1};

void circleAnimation() {
  for (int i = 0; i < 3; i++) {
    if (circleState[i] >= 100) {
      circleStateAnimation[i] = -1; // dim
    }
    else if (circleState[i] <= 10) {
      circleStateAnimation[i] = 1; // bright
    }
    circleState[i] += circleStateAnimation[i];
  }
  for (int i = 0; i < 6; i++) {
    SoftPWMSet(innerLedPins[i], circleState[0]);
    SoftPWMSet(middleLedPins[i], circleState[1]);
    SoftPWMSet(edgeLedPins[i], circleState[2]);
  }
  delay(5);
}

byte waveState[] = {100, 55, 10, 10, 55, 100};
byte waveStateAnimation[] = {1, 1, 1, -1, -1, -1};

void waveAnimation() {
  for (int i = 0; i < 6; i++) {
    if (waveState[i] >= 100) {
      waveStateAnimation[i] = -1; // dim
    }
    else if (waveState[i] <= 10) {
      waveStateAnimation[i] = 1; // bright
    }
    waveState[i] += waveStateAnimation[i];
  }
  for (int i = 0; i < 6; i+=2) {
    SoftPWMSet(innerLedPins[i], waveState[0]);
    SoftPWMSet(middleLedPins[i], waveState[1]);
    SoftPWMSet(edgeLedPins[i], waveState[2]);
    SoftPWMSet(innerLedPins[i + 1], waveState[3]);
    SoftPWMSet(middleLedPins[i + 1], waveState[4]);
    SoftPWMSet(edgeLedPins[i + 1], waveState[5]);
  }
  delay(10);
}

byte loopCounter = 0;
byte loopState = 150;

void loopAnimation() {
  SoftPWMSet(innerLedPins[loopCounter], loopState);
  SoftPWMSet(middleLedPins[loopCounter], loopState);
  SoftPWMSet(edgeLedPins[loopCounter], loopState);

  loopCounter = _nextIndex(loopCounter, 1);
  if (loopCounter == 0) {
    loopState = (loopState == 150 ? 0 : 150);
  }
  delay(100);
}

byte slowOnCounter = 0;
byte slowOnState = 150;

void slowOnAnimation() {
  byte randomLed = random(0, 18);
  if (randomLed < 6) {
    SoftPWMSet(innerLedPins[randomLed], slowOnState);
  }
  else if (randomLed < 12) {
    SoftPWMSet(middleLedPins[randomLed - 6], slowOnState);
  }
  else {
    SoftPWMSet(edgeLedPins[randomLed - 12], slowOnState);
  }
  slowOnCounter ++;
  if (slowOnCounter >= 50) {
    slowOnCounter = 0;
    slowOnState = (slowOnState == 150 ? 0 : 150);
  }
  delay(50);
}

byte shinyState[] = {0, 100, 0, 100, 0, 100};
byte shinyStateAnimation[] = {1, 1, 1, 1, 1, 1};
byte shinyCounter = 0;

void shinyAnimation() {
  for (int i = 0; i < 6; i++) {
    if (shinyState[i] >= 100) {
      shinyStateAnimation[i] = -1; // dim
    }
    else if (shinyState[i] <= 0) {
      shinyStateAnimation[i] = 1; // bright
    }
    shinyState[i] += shinyStateAnimation[i];
    SoftPWMSet(edgeLedPins[i], shinyState[i]);
  }
  shinyCounter ++;
  if (shinyCounter > 10) {
    shinyCounter = 0;
    for (byte r = random(1, 3); r > 0; r--) {
      byte randomLed = random(0, 12);
      if (randomLed < 6) {
        SoftPWMSet(innerLedPins[random(0, 6)], 255);
      }
      else {
        SoftPWMSet(middleLedPins[random(0, 6)], 255);
      }
    }
  }
  else {
    for (int i = 0; i < 6; i++) {
      SoftPWMSet(innerLedPins[i], 20);
      SoftPWMSet(middleLedPins[i], 20);
    }
  }
  delay(30);
}

byte fadingState[] = {0, 100, 0, 100, 0, 100};
byte fadingStateAnimation[] = {1, 1, 1, 1, 1, 1};

void fadingAnimation() {
  for (int i = 0; i < 6; i++) {
    if (fadingState[i] >= 100) {
      fadingStateAnimation[i] = -1; // dim
    }
    else if (fadingState[i] <= 0) {
      fadingStateAnimation[i] = 1; // bright
    }
    fadingState[i] += fadingStateAnimation[i];
    SoftPWMSet(edgeLedPins[i], fadingState[i]);
    SoftPWMSet(middleLedPins[_nextIndex(i, 1)], fadingState[i]);
    SoftPWMSet(innerLedPins[i], 50);
  }
  delay(20);
}

void _fill(byte value) {
  for (int i = 0; i < 6; i++) {
    SoftPWMSet(edgeLedPins[i], value);
    SoftPWMSet(middleLedPins[i], value);
    SoftPWMSet(innerLedPins[i], value);
  }
}

byte _prevIndex(short index, byte step) {
  index -= step;
  while (index < 0) {
    index += 6;
  }
  return index;
}

byte _nextIndex(short index, byte step) {
  index += step;
  while (index > 5) {
    index -= 6;
  }
  return index;
}

Credits

Jiří Praus

Jiří Praus

7 projects • 66 followers
Developer for Samepage.io and hardware maker. I started with a simple Arduino kit two years ago and I fell in love with the platform.

Comments