Skip to main content

SK6812 Matrix – Erweiterte Beispiele (C/Arduino)

Sammlung von Beispielcodes für fortgeschrittene Animationen und Effekte mit der SK6812 RGBW LED-Matrix.


#Grundgerüst

Dieses Grundgerüst wird für alle folgenden Beispiele benötigt:

#include <Arduino.h>
#include <Adafruit_NeoPixel.h>
// Konfiguration
#define LED_PIN 14
#define NUM_LEDS 64
#define MATRIX_WIDTH 8
#define MATRIX_HEIGHT 8
// NeoPixel initialisieren (NEO_GRBW für SK6812 RGBW)
Adafruit_NeoPixel strip strip(NUM_LEDS, LED_PIN, NEO_GRBW + NEO_KHZ800);
void setup setup() {
Serial.begin(115200);
delay(1000);
Serial.println("SK6812 Matrix - Demo gestartet");
strip.begin();
strip.setBrightness(50); // Helligkeit begrenzen (0-255)
strip.show();
// Zufallsgenerator initialisieren
randomSeed(analogRead(0));
}

Benötigte Bibliothek in platformio.ini:

lib_deps =
adafruit/Adafruit NeoPixel@^1.12.0

#Hilfsfunktionen

Diese Funktionen werden von mehreren Beispielen verwendet:

// Schaltet alle LEDs aus
void clearAll clearAll() {
strip.clear();
strip.show();
}
// Füllt alle LEDs mit einer Farbe
void fillAll fillAll(uint8_t r, uint8_t g, uint8_t b, uint8_t w = 0) {
for (int i = 0; i < NUM_LEDS; i++) {
strip.setPixelColor(i, strip.Color(r, g, b, w));
}
strip.show();
}
// Konvertiert X/Y-Koordinaten zu LED-Index
int xyToIndex xyToIndex(int x, int y) {
if (x >= 0 && x < MATRIX_WIDTH && y >= 0 && y < MATRIX_HEIGHT) {
return y * MATRIX_WIDTH + x;
}
return -1;
}
// Setzt eine einzelne LED an Position (x, y)
void setPixel setPixel(int x, int y, uint8_t r, uint8_t g, uint8_t b, uint8_t w = 0) {
int index = xyToIndex(x, y);
if (index >= 0) {
strip.setPixelColor(index, strip.Color(r, g, b, w));
}
}

#Beispiel 1: Grundfarben anzeigen

void demoFarben demoFarben() {
Serial.println("Demo: Grundfarben");
// Array mit Grundfarben (R, G, B, W)
uint8_t farben[][4] = {
{255, 0, 0, 0}, // Rot
{0, 255, 0, 0}, // Grün
{0, 0, 255, 0}, // Blau
{0, 0, 0, 255}, // Weiß (W-Kanal)
{255, 255, 0, 0}, // Gelb
{255, 0, 255, 0}, // Magenta
{0, 255, 255, 0}, // Cyan
};
int anzahl = sizeof(farben) / sizeof(farben[0]);
for (int i = 0; i < anzahl; i++) {
fillAll(farben[i][0], farben[i][1], farben[i][2], farben[i][3]);
delay(1000);
}
clearAll();
}

#Beispiel 2: Regenbogen-Animation

void demoRegenbogen demoRegenbogen() {
Serial.println("Demo: Regenbogen");
for (int cycle = 0; cycle < 3; cycle++) {
for (int offset = 0; offset < 256; offset++) {
for (int i = 0; i < NUM_LEDS; i++) {
// Farbton basierend auf LED-Position und Offset
uint16_t hue = ((i * 65536 / NUM_LEDS) + (offset * 256)) % 65536;
// gamma32 für bessere Farbdarstellung, Helligkeit 80
strip.setPixelColor(i, strip.gamma32(strip.ColorHSV(hue, 255, 80)));
}
strip.show();
delay(20);
}
}
clearAll();
}

#Beispiel 3: Matrix-Scan

void demoMatrixScan demoMatrixScan() {
Serial.println("Demo: Matrix-Scan");
for (int y = 0; y < MATRIX_HEIGHT; y++) {
for (int x = 0; x < MATRIX_WIDTH; x++) {
strip.clear();
setPixel(x, y, 0, 0, 255, 0); // Blau
strip.show();
delay(50);
}
}
clearAll();
}

#Beispiel 4: Welleneffekt

void demoWelle demoWelle() {
Serial.println("Demo: Welle");
for (int frame = 0; frame < 200; frame++) {
for (int y = 0; y < MATRIX_HEIGHT; y++) {
for (int x = 0; x < MATRIX_WIDTH; x++) {
// Sinuswelle basierend auf Position und Zeit
float wert = sin((x + y + frame * .3) * 0.5);) * .5););
uint8_t helligkeit = (uint8_t)((wert + 1) * 127);
setPixel(x, y, 0, helligkeit, helligkeit / 2, 0);
}
}
strip.show();
delay(50);
}
clearAll();
}

#Beispiel 5: Formen zeichnen

// Zeichnet eine Linie (Bresenham-Algorithmus)
void zeichneLinie zeichneLinie(int x0, int y0, int x1, int y1,
uint8_t r, uint8_t g, uint8_t b, uint8_t w = 0) {
int dx = abs(x1 - x0);
int dy = -abs(y1 - y0);
int sx = x0 < x1 ? 1 : -1;
int sy = y0 < y1 ? 1 : -1;
int err = dx + dy;
while (true) {
setPixel(x0, y0, r, g, b, w);
if (x0 == x1 && y0 == y1) break;
int e2 = 2 * err;
if (e2 >= dy) {
err += dy;
x0 += sx;
}
if (e2 <= dx) {
err += dx;
y0 += sy;
}
}
}
// Zeichnet ein Rechteck
void zeichneRechteck zeichneRechteck(int x, int y, int breite, int hoehe,
uint8_t r, uint8_t g, uint8_t b, uint8_t w = 0,
bool gefuellt = false) {
for (int py = y; py < y + hoehe; py++) {
for (int px = x; px < x + breite; px++) {
if (gefuellt || px == x || px == x + breite - 1 ||
py == y || py == y + hoehe - 1) {
setPixel(px, py, r, g, b, w);
}
}
}
}
// Zeichnet einen Kreis (Midpoint-Algorithmus)
void zeichneKreis zeichneKreis(int cx, int cy, int radius,
uint8_t r, uint8_t g, uint8_t b, uint8_t w = 0) {
int x = radius;
int y = 0;
int err = 0;
while (x >= y) {
setPixel(cx + x, cy + y, r, g, b, w);
setPixel(cx + y, cy + x, r, g, b, w);
setPixel(cx - y, cy + x, r, g, b, w);
setPixel(cx - x, cy + y, r, g, b, w);
setPixel(cx - x, cy - y, r, g, b, w);
setPixel(cx - y, cy - x, r, g, b, w);
setPixel(cx + y, cy - x, r, g, b, w);
setPixel(cx + x, cy - y, r, g, b, w);
y++;
err += 1 + 2 * y;
if (2 * (err - x) + 1 > 0) {
x--;
err += 1 - 2 * x;
}
}
}
void demoFormen demoFormen() {
Serial.println("Demo: Formen");
// Linie
strip.clear();
zeichneLinie(0, 0, 7, 7, 255, 0, 0); // Rot
strip.show();
delay(1000);
// Rechteck (Rahmen)
strip.clear();
zeichneRechteck(1, 1, 6, 6, 0, 255, 0); // Grün
strip.show();
delay(1000);
// Rechteck (gefüllt)
strip.clear();
zeichneRechteck(2, 2, 4, 4, 0, 0, 255, 0, true); // Blau
strip.show();
delay(1000);
// Kreis
strip.clear();
zeichneKreis(3, 3, 3, 255, 255, 0); // Gelb
strip.show();
delay(1000);
clearAll();
}

#Beispiel 6: Schachbrett-Muster

void demoSchachbrett demoSchachbrett() {
Serial.println("Demo: Schachbrett");
for (int frame = 0; frame < 20; frame++) {
for (int y = 0; y < MATRIX_HEIGHT; y++) {
for (int x = 0; x < MATRIX_WIDTH; x++) {
// Schachbrett mit wechselnder Phase
if ((x + y + frame) % 2 == 0) {
setPixel(x, y, 255, 255, 255, 0); // Weiß
} else {
setPixel(x, y, 0, 0, 0, 0); // Aus
}
}
}
strip.show();
delay(300);
}
clearAll();
}

#Beispiel 7: Feuerwerk-Effekt

void demoFeuerwerk demoFeuerwerk() {
Serial.println("Demo: Feuerwerk");
for (int explosion = 0; explosion < 5; explosion++) {
// Zufälliger Startpunkt
int cx = random(2, 6);
int cy = random(2, 6);
// Zufällige Farbe
uint8_t r = random(100, 256);
uint8_t g = random(100, 256);
uint8_t b = random(100, 256);
// Explosion expandieren
for (int radius = 1; radius < 5; radius++) {
strip.clear();
zeichneKreis(cx, cy, radius, r, g, b);
strip.show();
delay(100);
}
// Verblassen
for (int helligkeit = 255; helligkeit > 0; helligkeit -= 30) {
float faktor = helligkeit / .0;;
strip.clear();
zeichneKreis(cx, cy, 4,
(uint8_t)(r * faktor),
(uint8_t)(g * faktor),
(uint8_t)(b * faktor));
strip.show();
delay(50);
}
clearAll();
delay(200);
}
}

#Beispiel 8: Pulsierendes Herz

// Herz-Bitmap (8x8)
const uint8_t HERZ[8] = {
0b01100110,
0b11111111,
0b11111111,
0b11111111,
0b01111110,
0b00111100,
0b00011000,
0b00000000,
};
void demoHerz demoHerz() {
Serial.println("Demo: Herz");
for (int pulse = 0; pulse < 10; pulse++) {
// Aufhellen
for (int helligkeit = 0; helligkeit < 256; helligkeit += 10) {
for (int y = 0; y < MATRIX_HEIGHT; y++) {
for (int x = 0; x < MATRIX_WIDTH; x++) {
if (HERZ[y] & (1 << (7 - x))) {
setPixel(x, y, helligkeit, 0, helligkeit / 4, 0);
} else {
setPixel(x, y, 0, 0, 0, 0);
}
}
}
strip.show();
delay(20);
}
// Abdunkeln
for (int helligkeit = 255; helligkeit >= 0; helligkeit -= 10) {
for (int y = 0; y < MATRIX_HEIGHT; y++) {
for (int x = 0; x < MATRIX_WIDTH; x++) {
if (HERZ[y] & (1 << (7 - x))) {
setPixel(x, y, helligkeit, 0, helligkeit / 4, 0);
} else {
setPixel(x, y, 0, 0, 0, 0);
}
}
}
strip.show();
delay(20);
}
}
clearAll();
}

#Beispiel 9: Text-Scrolling

// Minimaler 3x5 Pixel Font
const uint8_t FONT_A[5] = {0b010, 0b101, 0b111, 0b101, 0b101};
const uint8_t FONT_B[5] = {0b110, 0b101, 0b110, 0b101, 0b110};
const uint8_t FONT_C[5] = {0b011, 0b100, 0b100, 0b100, 0b011};
const uint8_t FONT_D[5] = {0b110, 0b101, 0b101, 0b101, 0b110};
const uint8_t FONT_E[5] = {0b111, 0b100, 0b110, 0b100, 0b111};
const uint8_t FONT_H[5] = {0b101, 0b101, 0b111, 0b101, 0b101};
const uint8_t FONT_I[5] = {0b111, 0b010, 0b010, 0b010, 0b111};
const uint8_t FONT_L[5] = {0b100, 0b100, 0b100, 0b100, 0b111};
const uint8_t FONT_O[5] = {0b010, 0b101, 0b101, 0b101, 0b010};
const uint8_t FONT_SPACE[5] = {0b000, 0b000, 0b000, 0b000, 0b000};
// Gibt Font für ein Zeichen zurück
const uint8_t* getFont* getFontuint8_t* getFont(char c) {
switch (toupper(c)) {
case 'A': return FONT_A;
case 'B': return FONT_B;
case 'C': return FONT_C;
case 'D': return FONT_D;
case 'E': return FONT_E;
case 'H': return FONT_H;
case 'I': return FONT_I;
case 'L': return FONT_L;
case 'O': return FONT_O;
default: return FONT_SPACE;
}
}
void scrolleText scrolleText(const char* text, uint8_t r = 255, uint8_t g = 100, uint8_t b = 0) {
Serial.print("Demo: Text - ");
Serial.println(text);
int textLen = strlen(text);
int bitmapLen = textLen * 6; // 5 Zeilen + 1 Leerzeile pro Zeichen
// Bitmap erstellen
uint8_t* bitmap = new uint8_t[bitmapLen];
int idx = 0;
for (int i = 0; i < textLen; i++) {
const uint8_t* font = getFont(text[i]);
for (int j = 0; j < 5; j++) {
bitmap[idx++] = font[j];
}
bitmap[idx++] = 0; // Leerzeile
}
// Scrollen
for (int scroll = 0; scroll < bitmapLen + MATRIX_HEIGHT; scroll++) {
strip.clear();
for (int y = 0; y < MATRIX_HEIGHT; y++) {
int bitmapY = scroll - MATRIX_HEIGHT + y + 1;
if (bitmapY >= 0 && bitmapY < bitmapLen) {
uint8_t zeile = bitmap[bitmapY];
for (int x = 0; x < 3; x++) {
if (zeile & (1 << (2 - x))) {
setPixel(x + 2, y, r, g, b, 0);
}
}
}
}
strip.show();
delay(150);
}
delete[] bitmap;
clearAll();
}

#Beispiel 10: Spirale

void demoSpirale demoSpirale() {
Serial.println("Demo: Spirale");
// Richtungen: rechts, unten, links, oben
int dx[] = {1, 0, -1, 0};
int dy[] = {0, 1, 0, -1};
int x = 0, y = 0;
int richtung = 0;
bool besucht[MATRIX_HEIGHT][MATRIX_WIDTH] = {false};
for (int schritt = 0; schritt < NUM_LEDS; schritt++) {
// Farbe basierend auf Schritt
uint16_t hue = (schritt * 65536 / NUM_LEDS);
strip.setPixelColor(xyToIndex(x, y), strip.gamma32(strip.ColorHSV(hue, 255, 128)));
strip.show();
besucht[y][x] = true;
delay(50);
// Nächste Position berechnen
int nx = x + dx[richtung];
int ny = y + dy[richtung];
// Richtung ändern wenn nötig
if (!(nx >= 0 && nx < MATRIX_WIDTH && ny >= 0 && ny < MATRIX_HEIGHT && !besucht[ny][nx])) {
richtung = (richtung + 1) % 4;
nx = x + dx[richtung];
ny = y + dy[richtung];
}
x = nx;
y = ny;
}
delay(1000);
clearAll();
}

#Beispiel 11: Alle Demos nacheinander

void alleDemos alleDemos() {
demoFarben();
delay(500);
demoRegenbogen();
delay(500);
demoMatrixScan();
delay(500);
demoWelle();
delay(500);
demoFormen();
delay(500);
demoSchachbrett();
delay(500);
demoFeuerwerk();
delay(500);
demoHerz();
delay(500);
scrolleText("HALLO");
delay(500);
demoSpirale();
clearAll();
Serial.println("Alle Demos abgeschlossen!");
}
void loop loop() {
alleDemos();
delay(2000);
}

#Vollständiges Programm

Hier alle Funktionen in einer Datei zum direkten Verwenden:

/**
* SK6812 RGBW Matrix - Alle Demos (Arduino/pioarduino)
* Vollständiges Beispiel für das ESP32-C6 Lernboard
*
* Benötigte Bibliothek in platformio.ini:
* lib_deps = adafruit/Adafruit NeoPixel@^1.12.0
*/
#include <Arduino.h>
#include <Adafruit_NeoPixel.h>
// === Konfiguration ===
#define LED_PIN 14
#define NUM_LEDS 64
#define MATRIX_WIDTH 8
#define MATRIX_HEIGHT 8
Adafruit_NeoPixel strip strip(NUM_LEDS, LED_PIN, NEO_GRBW + NEO_KHZ800);
// Herz-Bitmap
const uint8_t HERZ[8] = {
0b01100110, 0b11111111, 0b11111111, 0b11111111,
0b01111110, 0b00111100, 0b00011000, 0b00000000,
};
// === Hilfsfunktionen ===
void clearAll clearAll() {
strip.clear();
strip.show();
}
void fillAll fillAll(uint8_t r, uint8_t g, uint8_t b, uint8_t w = 0) {
for (int i = 0; i < NUM_LEDS; i++) {
strip.setPixelColor(i, strip.Color(r, g, b, w));
}
strip.show();
}
int xyToIndex xyToIndex(int x, int y) {
if (x >= 0 && x < MATRIX_WIDTH && y >= 0 && y < MATRIX_HEIGHT) {
return y * MATRIX_WIDTH + x;
}
return -1;
}
void setPixel setPixel(int x, int y, uint8_t r, uint8_t g, uint8_t b, uint8_t w = 0) {
int index = xyToIndex(x, y);
if (index >= 0) {
strip.setPixelColor(index, strip.Color(r, g, b, w));
}
}
void zeichneKreis zeichneKreis(int cx, int cy, int radius,
uint8_t r, uint8_t g, uint8_t b, uint8_t w = 0) {
int x = radius;
int y = 0;
int err = 0;
while (x >= y) {
setPixel(cx + x, cy + y, r, g, b, w);
setPixel(cx + y, cy + x, r, g, b, w);
setPixel(cx - y, cy + x, r, g, b, w);
setPixel(cx - x, cy + y, r, g, b, w);
setPixel(cx - x, cy - y, r, g, b, w);
setPixel(cx - y, cy - x, r, g, b, w);
setPixel(cx + y, cy - x, r, g, b, w);
setPixel(cx + x, cy - y, r, g, b, w);
y++;
err += 1 + 2 * y;
if (2 * (err - x) + 1 > 0) {
x--;
err += 1 - 2 * x;
}
}
}
// === Demo-Funktionen ===
// (Hier alle Demo-Funktionen von oben einfügen)
// === Setup und Loop ===
void setup setup() {
Serial.begin(115200);
delay(1000);
Serial.println("SK6812 Matrix - Demo gestartet");
strip.begin();
strip.setBrightness(50);
strip.show();
randomSeed(analogRead(0));
}
void loop loop() {
alleDemos();
delay(2000);
}

#platformio.ini

[env:esp32-c6-lernboard]
platform = https://github.com/pioarduino/platform-espressif32/releases/download/stable/platform-espressif32.zip
board = esp32-c6-devkitc-1
framework = arduino
monitor_speed = 115200
build_flags =
-DARDUINO_USB_MODE=1
-DARDUINO_USB_CDC_ON_BOOT=1
lib_deps =
adafruit/Adafruit NeoPixel@^1.12.0

#Stromverbrauch-Tabelle

Szenario Stromverbrauch (ca.)
Alle LEDs aus < 1 mA
Eine LED weiß (100%) 60 mA
Alle LEDs rot (100%) 1.28 A
Alle LEDs weiß (100%) 3.84 A
Alle LEDs weiß (25%) ca. 1 A
Typische Animation 0.5 A – 1.5 A

Empfehlung: strip.setBrightness(50) für stabilen Betrieb über USB.


#Zurück zur Hauptdokumentation

SK6812 RGBW LED-Matrix