#include <FastLED.h>
#include <SoftwareSerial.h>
// #include <letters.h>
// Einstellungen für die LED-Matrix
#define LED_PIN 6 // Pin, an dem der LED-Streifen angeschlossen ist
#define WIDTH 16 // Breite der Matrix
#define HEIGHT 16 // Höhe der Matrix
#define NUM_LEDS WIDTH * HEIGHT // Anzahl der LEDs
#define BRIGHTNESS 150 // Helligkeit der LEDs
CRGB leds[NUM_LEDS]; // Array zur Speicherung der LED-Farben
// Einstellungen für Bluetooth
SoftwareSerial BTSerial(10, 11); // RX, TX für Bluetooth-Modul
// Globale Variablen
uint8_t hue = 0; // Farbton für den Regenbogeneffekt
int textSpeed = 70; // Standardgeschwindigkeit des laufenden Textes (ms)
uint8_t heat[NUM_LEDS]; // Wärme-Array für den Feuereffekt
// Variablen für die automatische Umschaltung
unsigned long effectStartTime;
const unsigned long effectDuration = 20000; // Dauer eines Effekts in Millisekunden (20 Sekunden)
// Modi der LED-Matrix
enum Mode { RAINBOW, FIRE, SCROLL_TEXT };
Mode currentMode = RAINBOW; // Startmodus
// Variablen für den Scroll-Text
String scrollText = "Willkommen bei der Digital Development Division, der IT-Schule";
int scrollPos = 0; // Position für die Lauftextanzeige
// Vereinfachte 5x8-Schriftart für Großbuchstaben, Kleinbuchstaben und Zahlen
const byte font5x8[62][5] PROGMEM = {
// Großbuchstaben A-Z
{0x7E, 0x11, 0x11, 0x11, 0x7E}, // A
{0x7F, 0x49, 0x49, 0x49, 0x36}, // B
{0x3E, 0x41, 0x41, 0x41, 0x22}, // C
{0x7F, 0x41, 0x41, 0x41, 0x3E}, // D
{0x7F, 0x49, 0x49, 0x49, 0x41}, // E
{0x7F, 0x09, 0x09, 0x09, 0x01}, // F
{0x3E, 0x41, 0x49, 0x49, 0x7A}, // G
{0x7F, 0x08, 0x08, 0x08, 0x7F}, // H
{0x00, 0x41, 0x7F, 0x41, 0x00}, // I
{0x20, 0x40, 0x41, 0x3F, 0x01}, // J
{0x7F, 0x08, 0x14, 0x22, 0x41}, // K
{0x7F, 0x40, 0x40, 0x40, 0x40}, // L
{0x7F, 0x02, 0x0C, 0x02, 0x7F}, // M
{0x7F, 0x04, 0x08, 0x10, 0x7F}, // N
{0x3E, 0x41, 0x41, 0x41, 0x3E}, // O
{0x7F, 0x09, 0x09, 0x09, 0x06}, // P
{0x3E, 0x41, 0x51, 0x21, 0x5E}, // Q
{0x7F, 0x09, 0x19, 0x29, 0x46}, // R
{0x46, 0x49, 0x49, 0x49, 0x31}, // S
{0x01, 0x01, 0x7F, 0x01, 0x01}, // T
{0x3F, 0x40, 0x40, 0x40, 0x3F}, // U
{0x1F, 0x20, 0x40, 0x20, 0x1F}, // V
{0x3F, 0x40, 0x38, 0x40, 0x3F}, // W
{0x63, 0x14, 0x08, 0x14, 0x63}, // X
{0x07, 0x08, 0x70, 0x08, 0x07}, // Y
{0x61, 0x51, 0x49, 0x45, 0x43}, // Z
// Kleinbuchstaben a-z
{0x20, 0x54, 0x54, 0x54, 0x78}, // a
{0x7F, 0x48, 0x44, 0x44, 0x38}, // b
{0x38, 0x44, 0x44, 0x44, 0x20}, // c
{0x38, 0x44, 0x44, 0x48, 0x7F}, // d
{0x38, 0x54, 0x54, 0x54, 0x18}, // e
{0x08, 0x7E, 0x09, 0x01, 0x02}, // f
{0x08, 0x14, 0x54, 0x54, 0x3C}, // g
{0x7F, 0x08, 0x04, 0x04, 0x78}, // h
{0x00, 0x44, 0x7D, 0x40, 0x00}, // i
{0x20, 0x40, 0x44, 0x3D, 0x00}, // j
{0x00, 0x7F, 0x10, 0x28, 0x44}, // k
{0x00, 0x41, 0x7F, 0x40, 0x00}, // l
{0x7C, 0x04, 0x18, 0x04, 0x78}, // m
{0x7C, 0x08, 0x04, 0x04, 0x78}, // n
{0x38, 0x44, 0x44, 0x44, 0x38}, // o
{0x7C, 0x14, 0x14, 0x14, 0x08}, // p
{0x08, 0x14, 0x14, 0x18, 0x7C}, // q
{0x7C, 0x08, 0x04, 0x04, 0x08}, // r
{0x48, 0x54, 0x54, 0x54, 0x20}, // s
{0x04, 0x3F, 0x44, 0x40, 0x20}, // t
{0x3C, 0x40, 0x40, 0x20, 0x7C}, // u
{0x1C, 0x20, 0x40, 0x20, 0x1C}, // v
{0x3C, 0x40, 0x30, 0x40, 0x3C}, // w
{0x44, 0x28, 0x10, 0x28, 0x44}, // x
{0x0C, 0x50, 0x50, 0x50, 0x3C}, // y
{0x44, 0x64, 0x54, 0x4C, 0x44}, // z
// Zahlen 0-9
{0x3E, 0x51, 0x49, 0x45, 0x3E}, // 0
{0x00, 0x42, 0x7F, 0x40, 0x00}, // 1
{0x42, 0x61, 0x51, 0x49, 0x46}, // 2
{0x21, 0x41, 0x45, 0x4B, 0x31}, // 3
{0x18, 0x14, 0x12, 0x7F, 0x10}, // 4
{0x27, 0x45, 0x45, 0x45, 0x39}, // 5
{0x3C, 0x4A, 0x49, 0x49, 0x30}, // 6
{0x01, 0x71, 0x09, 0x05, 0x03}, // 7
{0x36, 0x49, 0x49, 0x49, 0x36}, // 8
{0x06, 0x49, 0x49, 0x29, 0x1E} // 9
};
void setup() {
// Initialisierung der LEDs
FastLED.addLeds<WS2812, LED_PIN, GRB>(leds, NUM_LEDS);
FastLED.setBrightness(BRIGHTNESS);
// Initialisierung der seriellen Verbindung und des Bluetooth-Moduls
Serial.begin(9600); // Serielle Verbindung für Debugging
BTSerial.begin(9600); // Serielle Verbindung für Bluetooth-Modul
// Setze den Anfangsmodus auf Regenbogen
currentMode = RAINBOW;
setupRainbow();
effectStartTime = millis(); // Starte die Zeitmessung für den Effekt
}
void loop() {
// Überprüfen, ob Daten vom Bluetooth-Modul empfangen wurden
if (BTSerial.available() > 0) {
String command = BTSerial.readStringUntil('\n'); // Lese die empfangene Nachricht
command.trim(); // Entferne unnötige Leerzeichen
handleCommand(command); // Verarbeite den Befehl
}
// Führe den aktuellen Modus aus
switch (currentMode) {
case RAINBOW:
loopRainbow();
break;
case FIRE:
loopFire();
break;
case SCROLL_TEXT:
loopScrollText();
break;
}
// Überprüfen, ob die Zeit für den aktuellen Effekt abgelaufen ist
if (millis() - effectStartTime >= effectDuration) {
switchToNextEffect();
}
}
// Diese Funktion verarbeitet die empfangenen Befehle und schaltet die Modi um
void handleCommand(String command) {
if (command == "RAINBOW") {
currentMode = RAINBOW;
setupRainbow();
} else if (command == "FIRE") {
currentMode = FIRE;
setupFire();
} else if (command == "SCROLL_TEXT") {
currentMode = SCROLL_TEXT;
setupScrollText();
} else if (command.startsWith("TEXT")) {
scrollText = command.substring(5); // Setze den Text für die Lauftextanzeige
setupScrollText();
} else if (command.startsWith("DELAY")) {
textSpeed = command.substring(6).toInt(); // Setze die Verzögerungszeit
}
effectStartTime = millis(); // Setze die Zeitmessung für den neuen Effekt zurück
}
// Diese Funktion schaltet zum nächsten Effekt um
void switchToNextEffect() {
switch (currentMode) {
case RAINBOW:
currentMode = FIRE;
setupFire();
break;
case FIRE:
currentMode = SCROLL_TEXT;
setupScrollText();
break;
case SCROLL_TEXT:
currentMode = RAINBOW;
setupRainbow();
break;
default:
currentMode = RAINBOW;
setupRainbow();
break;
}
effectStartTime = millis(); // Setze die Zeitmessung für den neuen Effekt zurück
}
// Diese Funktion bereitet den Regenbogeneffekt vor
void setupRainbow() {
hue = 0; // Setze den Anfangsfarbton auf 0
}
// Diese Funktion führt den Regenbogeneffekt aus
void loopRainbow() {
for (int x = 0; x < WIDTH; x++) {
for (int y = 0; y < HEIGHT; y++) {
leds[XY(x, y)] = CHSV((hue + x * 8 + y * 8), 255, 255); // Setze die Farbe für jede LED
}
}
hue++; // Erhöhe den Farbton
hue = hue % 256; // Setze den Farbton zurück auf 0, wenn er 255 erreicht
FastLED.show(); // Zeige die LEDs an
delay(textSpeed); // Warte für die eingestellte Zeit
}
// Diese Funktion bereitet den Feuereffekt vor
void setupFire() {
// Initialisiere das Array für die Wärme
for (int i = 0; i < NUM_LEDS; i++) {
heat[i] = 0;
}
}
// Diese Funktion führt den Feuereffekt aus
void loopFire() {
// Schritt 1: Kühle jede Zelle ein wenig ab
for (int i = 0; i < NUM_LEDS; i++) {
heat[i] = qsub8(heat[i], random8(0, ((55 * 10) / NUM_LEDS) + 2));
}
// Schritt 2: Wärme steigt auf und verteilt sich ein wenig
for (int k = NUM_LEDS - 1; k >= WIDTH; k--) {
heat[k] = (heat[k - WIDTH] + heat[k - WIDTH + 1] + heat[k - WIDTH - 1]) / 3;
}
// Schritt 3: Zünde neue Funken in der unteren Reihe an
if (random8() < 120) {
int y = random8(WIDTH);
heat[y] = qadd8(heat[y], random8(160, 255));
}
// Schritt 4: Wandle Wärme in Farbe um
for (int j = 0; j < NUM_LEDS; j++) {
leds[j] = HeatColor(heat[j]);
}
FastLED.show();
delay(textSpeed);
}
// Diese Funktion bereitet die Lauftextanzeige vor
void setupScrollText() {
scrollPos = WIDTH; // Startposition des Textes am rechten Rand der Matrix
}
// Diese Funktion führt die Lauftextanzeige aus
void loopScrollText() {
FastLED.clear(); // Lösche die LEDs
int len = scrollText.length();
for (int i = 0; i < len; i++) {
int charWidth = 5; // Breite eines Buchstabens (in Pixeln)
int charPos = scrollPos + i * charWidth;
if (charPos >= 0 && charPos < WIDTH) {
// Zeichne den Buchstaben auf die Matrix
drawChar(scrollText[i], charPos, 0);
}
}
scrollPos--; // Bewege den Text nach links
if (scrollPos < -len * 5) { // Wenn der gesamte Text aus dem Bild ist
scrollPos = WIDTH; // Starte von neuem
}
FastLED.show();
delay(textSpeed);
}
// Zeichnet einen Buchstaben auf die Matrix
void drawChar(char c, int x, int y) {
byte font[5] = {0}; // Platzhalter für den Buchstaben
// ASCII-Zeichen zu 5x8-Matrix umwandeln
if (c >= 'A' && c <= 'Z') {
memcpy_P(font, font5x8[c - 'A'], 5);
} else if (c >= 'a' && c <= 'z') {
memcpy_P(font, font5x8[c - 'a' + 26], 5);
} else if (c >= '0' && c <= '9') {
memcpy_P(font, font5x8[c - '0' + 52], 5);
}
for (int i = 0; i < 5; i++) {
for (int j = 0; j < 8; j++) {
if (font[i] & (1 << j)) {
leds[XY(x + i, y + (7 - j))] = CRGB::Blue; // Zeichne Pixel in Weiß
//leds[XY(x + i, y + j)] = CRGB::White; // Zeichne Pixel in Weiß
}
}
}
}
uint16_t XY(uint8_t x, uint8_t y) {
uint16_t i;
if (y % 2 == 0) {
// Gerade Zeile
i = (y * WIDTH) + x;
} else {
// Ungerade Zeile (Zickzack-Muster)
i = (y * WIDTH) + (WIDTH - 1 - x);
}
return i;
}