DIY Arduino-Schneeflocke: 30-LED-Display-Projekt
Komponenten und Materialien
| Komponente | Anzahl |
|---|---|
| Arduino Nano R3 | 1 |
Zusätzlich: 30 SMD-LEDs, 0,8 mm Messingdraht (~2 m), 220 Ω Widerstände (17 Stück), Lötzinn, Lötkolben, Zange, Karton & doppelseitiges Klebeband für Löt-Jig.
Projektbeschreibung
Die Schneeflocke besteht aus 30 LEDs, gruppiert in 17 unabhängig ansteuerbare Segmente. Jede Gruppe kann per PWM gedimmt werden – für wunderschöne Animationen.
Werkzeug
Alles was Sie brauchen: Lötkolben, Lötzinn, Zange.
Konstruktion
- Muster wählen: Einfaches Schneeflocken-Kristall-Muster, ausgedruckt in passender Größe (Arduino Nano passt in das zentrale Sechseck).
- Trägerstruktur = Verkabelung: 0,8 mm Messingdrähte werden verlötet – sie tragen die LEDs und leiten den Strom. Gesamt ca. 2 m Draht. „Freeform“-Aufbau als Gedulds- und Geschicklichkeitsprobe.


Zuerst das zentrale Sechseck aus einem Draht biegen, Enden verlöten. 6 weitere Drähte an die Ecken → Masse-Verdrahtung (Kathoden) fertig. Alle LED-Kathoden werden daran gelötet.
SMD-LEDs waren knifflig – geholfen hat ein Jig aus Karton und doppelseitigem Klebeband.

Arduino Nano wird unter der Kernstruktur platziert, mit Platz für 3 Lagen Messingdraht-Verdrahtung (Anoden → Arduino-Pins). Erfordert extrem viel Geduld: Keine Kurzschlüsse, Strombegrenzungswiderstände einbauen, optisch sauber.

Pin-Belegung (17 Segmente, 18 Pins nötig, aber A6/A7 sind Input-only → 17 nutzbare Pins):
- Blatt-LEDs (Spitzen): Je 1 LED pro Pin → 6 Pins
- Zweig-LEDs: Je 2 LEDs pro PWM-Pin gruppiert → 6 Pins
- Kern-LEDs: Je 2 LEDs pro Pin, aber 2 Paare zusammengelegt → 4 LEDs auf 2 Pins (Gruppe à 4)
- Touch-Sensor: 1 Pin
220 Ω Widerstände begrenzen Strom auf ~8 mA/Pin → gesamt ~240 mA (etwas über ATmega328-Spezifikation von 200 mA, aber funktionsfähig).
Kapazitiver Touch-Sensor
Zusätzlicher Messingdraht als kapazitiver Tastsensor. Bibliothek & Tutorial von Paul Stoffregen (ADCTouch). Funktionen: Animation wechseln, Ein/Aus, Funkeln bei Berührung.

Abschließender Hinweis
Alle Dioden VOR dem Einlöten testen! Nachträglicher Austausch ist extrem schwierig (Verpolung/Defekt).

Software & Animationen
Ursprünglich nur Hardware-PWM-Pins dimmbar. Die SoftPWM-Bibliothek (GitHub) ermöglicht Software-PWM auf allen Pins – endlose Animationsmöglichkeiten! Der beigefügte Code enthält erste Animationen.
Code
snowflake.ino (Arduino)
#include "SoftPWM.h"
#include
byte edgeLedPins[] = {13, A4, A5, 2, 8, 12}; // 6 Spitzen
byte middleLedPins[] = {10, 6, 3, 5, 9, 11}; // 6 Zweige
byte innerLedPins[] = {A2, A3, A1, 4, 7, A1}; // 6 Kern (A1 doppelt → 4er-Gruppe)
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; // Alle an (100%)
case 1: shinyAnimation(); break; // Glitzern
case 2: circleAnimation(); break; // Pulsierende Ringe
case 3: loopAnimation(); break; // Lauflicht
case 4: fireworkAnimation(); fireworkAnimation(); fireworkAnimation(); fireworkAnimation(); fireworkAnimation(); fireworkAnimation(); animation++; break;
case 5: smileAnimation(); break; // Smiley
default: animation = 0; break;
}
int touchValue = touchSensor.read();
if (touchAt + 2000 < millis() && touchValue > 1000) {
touchAt = millis();
animation++;
_fill(0); // Kurz ausblenden beim Wechsel
}
}
// --- Animationen ---
void _fill(byte value) {
for (int i = 0; i < 6; i++) {
SoftPWMSet(edgeLedPins[i], value);
SoftPWMSet(middleLedPins[i], value);
SoftPWMSet(innerLedPins[i], value);
}
}
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); // Augen
SoftPWMSet(middleLedPins[0], 255); SoftPWMSet(middleLedPins[5], 255); // Mundwinkel
SoftPWMSet(edgeLedPins[2], 255); SoftPWMSet(edgeLedPins[3], 255); // Mund
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[3] = {100, 55, 10};
byte circleDir[3] = {1, 1, 1};
void circleAnimation() {
for (int i = 0; i < 3; i++) {
if (circleState[i] >= 100) circleDir[i] = -1;
else if (circleState[i] <= 10) circleDir[i] = 1;
circleState[i] += circleDir[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[6] = {100, 55, 10, 10, 55, 100};
byte waveDir[6] = {1, 1, 1, -1, -1, -1};
void waveAnimation() {
for (int i = 0; i < 6; i++) {
if (waveState[i] >= 100) waveDir[i] = -1;
else if (waveState[i] <= 10) waveDir[i] = 1;
waveState[i] += waveDir[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, loopState = 150;
void loopAnimation() {
SoftPWMSet(innerLedPins[loopCounter], loopState);
SoftPWMSet(middleLedPins[loopCounter], loopState);
SoftPWMSet(edgeLedPins[loopCounter], loopState);
loopCounter = (loopCounter + 1) % 6;
if (loopCounter == 0) loopState = (loopState == 150 ? 0 : 150);
delay(100);
}
byte slowOnCounter = 0, 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);
if (++slowOnCounter >= 50) { slowOnCounter = 0; slowOnState = (slowOnState == 150 ? 0 : 150); }
delay(50);
}
byte shinyState[6] = {0, 100, 0, 100, 0, 100};
byte shinyDir[6] = {1, 1, 1, 1, 1, 1};
byte shinyCounter = 0;
void shinyAnimation() {
for (int i = 0; i < 6; i++) {
if (shinyState[i] >= 100) shinyDir[i] = -1;
else if (shinyState[i] <= 0) shinyDir[i] = 1;
shinyState[i] += shinyDir[i];
SoftPWMSet(edgeLedPins[i], shinyState[i]);
}
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[6] = {0, 100, 0, 100, 0, 100};
byte fadingDir[6] = {1, 1, 1, 1, 1, 1};
void fadingAnimation() {
for (int i = 0; i < 6; i++) {
if (fadingState[i] >= 100) fadingDir[i] = -1;
else if (fadingState[i] <= 0) fadingDir[i] = 1;
fadingState[i] += fadingDir[i];
SoftPWMSet(edgeLedPins[i], fadingState[i]);
SoftPWMSet(middleLedPins[(i+1)%6], fadingState[i]);
SoftPWMSet(innerLedPins[i], 50);
}
delay(20);
}
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;
}
Schaltpläne
Herstellungsprozess
- Wie Dübelstifte Ihre Projekte präzise halten: Einsatz in Möbeln, Regalen und Maschinen
- Materialien für Dübelstifte: Holz, Metall und Kunststoff im Vergleich
- 5 Schlüsselfaktoren für die Auswahl der richtigen Dübelstifte
- Das Nudelholz: Von etruskischen Ursprüngen bis zur modernen Handwerkskunst
- Die Entwicklung und Handwerkskunst moderner Bowling-Pins
- Sicherheitsnadel: Von antiken Fibeln zur modernen Fertigung
- TinyML: Ingenieure vereinen sich zur Standardisierung von KI für Ultra-Low-Power-Systeme
- Raspberry Pi I/O Breakout-Kabel & Plugboard-Adapter selbst bauen – Schritt für Schritt
- Dynamische LED-Dreieckskunst: 45 RGB-LEDs (APA106) mit Arduino UNO steuern
- Ball Grid Array (BGA): Was es ist und warum es wichtig ist