Jeden Tag ein neues Fenster leuchten lassen

Mein Plan ist eine Adventhaus Beleuchtung (Modellbau) wo sich jeden Tag vom 1. Dezember bis zum 24. Dezember um 9 Uhr ein Fenster einschalten soll und um 17 Uhr alle bis zu den aktuellen Tag aktiven Fenster dazu einschalten und um 22 Uhr sich alle ausschalten und dann am nächsten Tag um 9 Uhr mit dem aktuellen Fenster wieder alles beginnt. Das alles ist echt Neuland für mich ich habe schon einiges verstanden oder versucht zu verstehen und versuche auch immer mit Beispielen zu arbeiten. Da ich am besten durch probieren lerne.
Der zusammengeflickte Sketch funktioniert teilweise ja schon. Habe aber jetzt ein Problem gefunden und versuche verzweifelt es zu lösen.

Ich habe einen WS2812 Strip und ein DS3231RTC und einen Arduino Uno R4 verbaut und die einzelnen Pixel in die Fenster eingebaut. Mein Problem ist mir erst jetzt aufgefallen: Wie kann ich an einen bestimmten Tag ein bestimmtes Pixel leuchten lassen. im Versuch hat es geklappt da hatte ich nur 24 Pixel am Strip. und da habe ich einfach den Tag "now.day()" auch gleich als Pixelnummer genommen. Jetzt sind mehrere verbaut. Im Sketch hab ich jetzt nur 5.
Zum testen hab ich immer die Variablen geändert.
Wie schaffe ich das, das ich z.B. am Tag 12 die Pixel 40 leuchten lasse.
Für mein zweites Problem das die bereits aktivierten Pixel, also am Tag 12 alle Pixel von 1-12 von 17 - 22 Uhr leuchten, bin ich für Hilfe und Tips dankbar. Werde da aber auch selber weitertüfteln.
Vielen Dank im voraus.
Der Sketch ist für euch sicher nur Salat. Sorry

/*
Versuch für eine Adventhaus Beleuchtung (Modellbau) wo sich jeden Tag vom 1. Dezember bis zum 24. Dezember um 9 Uhr
ein Fenster einschalten soll und um 17 Uhr alle bis zu den aktuellen Tag aktiven Fenster dazu einschalten
und um 22 Uhr sich alle ausschalten und dann am nächsten Tag um 9 Uhr mit dem aktuellen Fenster wieder alles
beginnt.
Im Oktober läuft das Halloween Programm und in der restlichen Zeit das Standart Programm.
Möchte später das ganze mit Musik zu jeden Fenster um 9 Uhr erweitern.
*/

#include <Wire.h>
#include "RTClib.h"
RTC_DS3231 rtc;
#include <Arduino.h>
#include <Adafruit_NeoPixel.h>
#define PIN 6                        // DatenPIN für den LED Strip
#define PIXELCOUNT 126               // Anzahl der LEDs auf dem Strip
Adafruit_NeoPixel strip = Adafruit_NeoPixel(PIXELCOUNT, PIN, NEO_GRB + NEO_KHZ800);
unsigned long previousMillis = 0;
const long interval = 1000;

void setup() {
  Serial.begin(9600);

  rtc.begin();
  rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));

  strip.begin();
  strip.setBrightness(50);  // Helligkeit (1-255)
  strip.show();             // Schaltet alle LEDs am Anfang aus
  delay(1000);              // wartet 1 Sekunden
}

void loop() {

  int StartH = 10;          // Das Monat für Halloween
  int StartA = 12;          // Das Monat für den Adventkalender
  int FensterTime = 9;      // Startzeit für das aktuelle Fenster - alle anderen sind aus
  int AlleFensterE = 17;    // Alle bisherigen Fenster einschalten - 17 Uhr
  int AlleFensterA = 22;    // Alle Fenster ausschalten - 22 Uhr

  DateTime now = rtc.now();

  unsigned long currentMillis = millis();
  if (currentMillis - previousMillis >= interval) {

    if ((now.month()) == StartA && (now.hour()) == FensterTime) {
      strip.setPixelColor(now.day(), 0, 0, 255);
      Serial.println("Das aktuelle Fenster leuchtet von 9-10 Uhr");

    } else if ((now.month()) == StartA && (now.day()) <= now.day() && (now.hour()) == AlleFensterE) {
      strip.setPixelColor(1, 0, 0, 255);
      strip.setPixelColor(2, 0, 0, 255);
      strip.setPixelColor(3, 0, 0, 255);
      strip.setPixelColor(4, 0, 0, 255);
      strip.setPixelColor(5, 0, 0, 255);
      Serial.println("Alle Fenster bis zum aktuellen Tag leuchten von 17-22 Uhr");

    } else if ((now.month()) == StartH) {
      
      colorWipe(strip.Color(255, 0, 0), 50);  // Red
      colorWipe(strip.Color(0, 255, 0), 50);  // Green
      colorWipe(strip.Color(0, 0, 255), 50);  // Blue

      theaterChase(strip.Color(127, 127, 127), 50);  // White, half brightness
      theaterChase(strip.Color(127, 0, 0), 50);      // Red, half brightness
      theaterChase(strip.Color(0, 0, 127), 50);      // Blue, half brightness

      rainbow(10);              // Flowing rainbow cycle along the whole strip
      theaterChaseRainbow(50);  // Rainbow-enhanced theaterChase variant
      Serial.println(now.day());
      Serial.println("Halloween Programm");

    } else {
      Serial.println("Standart Programm");
      Serial.println("Folgt noch.");
    }
    strip.show();
    previousMillis = currentMillis;
  }
}

void colorWipe(uint32_t color, int wait) {
  for (int i = 0; i < strip.numPixels(); i++) {  // For each pixel in strip...
    strip.setPixelColor(i, color);               //  Set pixel's color (in RAM)
    strip.show();                                //  Update strip to match
    delay(wait);                                 //  Pause for a moment
  }
}

void theaterChase(uint32_t color, int wait) {
  for (int a = 0; a < 10; a++) {   // Repeat 10 times...
    for (int b = 0; b < 3; b++) {  //  'b' counts from 0 to 2...
      strip.clear();               //   Set all pixels in RAM to 0 (off)
      for (int c = b; c < strip.numPixels(); c += 3) {
        strip.setPixelColor(c, color);  // Set pixel 'c' to value 'color'
      }
      strip.show();  // Update strip with new contents
      delay(wait);   // Pause for a moment
    }
  }
}

void rainbow(int wait) {
  for (long firstPixelHue = 0; firstPixelHue < 5 * 65536; firstPixelHue += 256) {
    strip.rainbow(firstPixelHue);
    strip.show();  // Update strip with new contents
    delay(wait);   // Pause for a moment
  }
}

void theaterChaseRainbow(int wait) {
  int firstPixelHue = 0;           // First pixel starts at red (hue 0)
  for (int a = 0; a < 30; a++) {   // Repeat 30 times...
    for (int b = 0; b < 3; b++) {  //  'b' counts from 0 to 2...
      strip.clear();               //   Set all pixels in RAM to 0 (off)
      for (int c = b; c < strip.numPixels(); c += 3) {
        int hue = firstPixelHue + c * 65536L / strip.numPixels();
        uint32_t color = strip.gamma32(strip.ColorHSV(hue));  // hue -> RGB
        strip.setPixelColor(c, color);                        // Set pixel 'c' to value 'color'
      }
      strip.show();                 // Update strip with new contents
      delay(wait);                  // Pause for a moment
      firstPixelHue += 65536 / 90;  // One cycle of color wheel over 90 frames
    }
  }
}

Wenn ich es richtig verstanden habe, musst du da doch nur 28 hinzu zählen.
Für dein zweites Problem nutzt du eine Variable die du je Tag um eins hochzählst. Und dann alle Leds von 1 bis Inhalt der Variablen leuchten läßt.

Fehlt mir noch etwas Information:
Soll pro Tag genau 1 Pixel leuchten oder mehrere?

Ich würde ein (byte)Array anlegen, für jeden Tag 1 (oder Anzahl der LEDn pro Tag) Eintäge mit der Pixel-Nummer.
Dann im Programmablauf von Index 0 ... now.day()-1 alle Einträge leuchten lassen.

Erstmal Danke.
Es ist halt so das die Pixel die ein Fenster beleuchten sehr verstreut im Strip sind. Für Fenster 1 ist Pixel 23 zuständig für Fenster 15 Pixel 47 usw. Also müsste ich für jedes Fenster dann extra berechnen?

Also pro Tag soll von 9 bis 10 nur ein Pixel leuchten. Das für das aktuelle Fenster (1-24). Aber dann von 17 bis 22 Uhr sollen alle Pixel die für die schon vorherigen Fenster leuchten. Wenn immer die Pixelnummer mit der Fensternummer passen würde bekäme ich das vielleicht hin. Aber leider sind die Pixel für die Fenster im Strip verteilt. Also für Fenster 1 ist Pixel 23 zuständig usw.
Vielen Dank

Hallo
Ich würde eine Array Tabelle anlegen. Der Index ist der Tag und der Array wert der zugehörigen Pixel

Besser Salat als nix :smiley:

Dann hilft Dir eine Tabelle, die den Tag als Index verwendet und den Inhalt als Pixelnummer. Dazu ein kleines

Testprogramm
#include <Adafruit_NeoPixel.h>
#define PIN 6                        // DatenPIN für den LED Strip
#define PIXELCOUNT 126               // Anzahl der LEDs auf dem Strip
Adafruit_NeoPixel strip = Adafruit_NeoPixel(PIXELCOUNT, PIN, NEO_GRB + NEO_KHZ800);
unsigned long previousMillis = 0;
const long intervall = 1000;
const byte pixel[] = {5, 0, 4, 1, 3, 2};
byte index = 0;

void setup()
{
  Serial.begin(9600);
  strip.begin();
  strip.setBrightness(50);  // Helligkeit (1-255)
  strip.show();             // Schaltet alle LEDs am Anfang aus
  delay(1000);              // wartet 1 Sekunden
}

void loop()
{
  unsigned long currentMillis = millis();
  if ( currentMillis - previousMillis >= intervall )
  {
    strip.setPixelColor(pixel[index], 0, 0, 255);
    strip.show();
    previousMillis = currentMillis;
    if ( index < (sizeof(pixel) - 1) )
    {
      index++;
    }
  }
}

Die Tabelle kannst Du auf 24 Elemente erweitern und die Pixelnummern frei verteilen.

EDIT: 20240524 10:48 Fehler beseitigt, - 1 ergänzt.

Hallo, danke damit kann ich wieder etwas weiterarbeiten und meinen Horizont erweitern.
Am besten ist testen :wink:
Vielen Dank für die schnelle Hilfe. Werde morgen gleich daran arbeiten.
MfG

wie schon angesprochen, leg dir in ein Array ein Mapping von TagZuPixel an

und dann je nach Uhrzeit

  • wenn Stunde >= 9 und Stunde <=10 schalte das Pixel aus dem Array TagZuPixel ein
  • wenn Stunde >= 17 und Stunde <=22 schalte alle Pixel aus dem Array TagZuPixel ein, die <= Tag sind

Vielen Dank.
Hab wieder was zum abarbeiten. Werde berichten.
MfG

aua.

Nimm einen UNO R3

Grüße Uwe

Okay. Hab ich auch. Hab den R4 geschenkt bekommen und dachte den nehme ich.
MfG

Naja, das hättest du gleich mitschreiben können.
Hier ist das mehrfach zitierte Array die Lösung.

Hallo herbert-v

Schaue dir mal eine adressierbare RGB LED Lichterkette für dein Modell an.

grafik

Bei der Menge an initialisierten LEDs (126) vermute ich mal, daß du die nicht benötigten Pixel aus/dunkel lässt und sie nur als Verlängerung von Fenster zu Fenster nutzt?
Vielleicht möchtest du das ja für die Zukunft oder zur übernächsten Adventszeit ja noch einmal überdenken und etwas ressourcenschonender betreiben :innocent:
Mit dem von @paulpaulson vorgeschlagenen LED-String oder einzelnen LED-Pixeln auf Platine könntest du dir die Verbindungen von Fenster zu Fenster selbst konfektionieren und auf die benötigte Länge bringen.

kannst Du mir mal den rohen halloween-sketch geben?
danke.

Zum Thema LED-Typ: Es gibt auch 5 mm rund als APA106 F5, die verwende ich in meinem Avatarbildchen.

Für andere Projekte mit mehr Pixeln könntest Du Dir WS2815 ansehen, die funktionieren mit 12 V und weniger Strom. Leider sind sie etwas teurer und seltener.

Damit könntest Du die aktuelle Zeit von Deinem Router per WLAN holen. Mit einem reinen ESP32 mache ich das für eine LED-Uhr. Aber ich ahne, warum Du ihn geschenkt bekommen hast und schließe mich daher Uwes Rat an, hebe ihn Dir für später auf! Die Zeit von DS3231 ist für ein Jahr genau genug und viel einfacher zu verwenden.

Solltest Du auf die Idee kommen, die Zimmer mit unterschiedlichen Farben zu beleuchten, so kannst Du zusätzlich zur Pixelnummer auch noch die Farbe speichern. In C hätte man das mit zwei eindimensionalen Felder unterschiedlichen Typs gemacht, in C++ geht das auch mit einem Feld einer Struktur zweier Konstanten unterschiedlichen Typs:

Programm mit Struktur
#include <Adafruit_NeoPixel.h>
#define PIN 6                        // DatenPIN für den LED Strip
#define PIXELCOUNT 126               // Anzahl der LEDs auf dem Strip
Adafruit_NeoPixel strip = Adafruit_NeoPixel(PIXELCOUNT, PIN, NEO_GRB + NEO_KHZ800);
struct Zimmer
{
  const byte pixel;
  const uint32_t farbe;
};

Zimmer zimmer[]
{ // pixel, farbe
  {5, 0x0000FF},  // Blau
  {0, 0x0000FF},  // Blau
  {4, 0x00FF00},  // Grün
  {1, 0x00FF00},  // Grün
  {3, 0xFF0000},  // Rot
  {2, 0xFF0000},  // Rot
};

unsigned long previousMillis = 0;
const long intervall = 1000;
byte index = 0;

void setup()
{
  Serial.begin(9600);
  strip.begin();
  strip.setBrightness(50);  // Helligkeit (1-255)
  strip.show();             // Schaltet alle LEDs am Anfang aus
  delay(1000);              // wartet 1 Sekunden
}

void loop()
{
  unsigned long currentMillis = millis();
  if ( currentMillis - previousMillis >= intervall )
  {
    strip.setPixelColor(zimmer[index].pixel, zimmer[index].farbe);
    previousMillis = currentMillis;
    if ( index < (sizeof(zimmer) / sizeof(zimmer[0]) - 1) )
    {
      index++;
    }
    strip.show();
  }
}

Du kannst auch eine Funktion ergänzen, wird dann gerne Methode genannt:

Programm mit Methode
#include <Adafruit_NeoPixel.h>
#define PIN 6                        // DatenPIN für den LED Strip
#define PIXELCOUNT 126               // Anzahl der LEDs auf dem Strip
Adafruit_NeoPixel strip = Adafruit_NeoPixel(PIXELCOUNT, PIN, NEO_GRB + NEO_KHZ800);
class Zimmer
{
    byte pixel;
    uint32_t farbe;
  public:
    Zimmer (const byte pixel, const uint32_t farbe)
      : pixel(pixel), farbe(farbe)
    {}
    void beleuchten()
    {
      strip.setPixelColor(pixel, farbe);
      strip.show();
    }
};

Zimmer zimmer[]
{ // pixel, farbe
  {5, 0x0000FF},  // Blau
  {0, 0x0000FF},  // Blau
  {4, 0x00FF00},  // Grün
  {1, 0x00FF00},  // Grün
  {3, 0xFF0000},  // Rot
  {2, 0xFF0000},  // Rot
};
const byte anzahlZimmer = sizeof(zimmer) / sizeof(zimmer[0]);
unsigned long previousMillis = 0;
const long intervall = 1000;
byte index = 0;

void setup()
{
  Serial.begin(9600);
  strip.begin();
  strip.setBrightness(50);  // Helligkeit (1-255)
  strip.show();             // Schaltet alle LEDs am Anfang aus
  delay(1000);              // wartet 1 Sekunden
}

void loop()
{
  unsigned long currentMillis = millis();
  if ( currentMillis - previousMillis >= intervall )
  {
    zimmer[index].beleuchten();
    previousMillis = currentMillis;
    if ( index < (anzahlZimmer - 1) )
    {
      index++;
    }
    strip.show();
  }
}

struct ist am Anfang public, während class mit privat startet, sonst sind die gleich.

Dann viel Spaß hinter dem neuen Horizont :slightly_smiling_face:

Sieht stark nach dem Beispiel strandtest_nodelay.ino aus :wink:

Ist es auch. :wink:

Hatte das auch vor aber die, die ich gefunden hatte waren teilweise kaputt.

Die werde ich mal probieren.

Danke und MfG

Ich hoffe, Du schenkst auch meinen drei Programmen etwas Aufmerksamkeit, würde mich freuen :innocent:

Habe alle drei schon mal kurz angesehen und ausprobiert. Habe das Wochenende Dienst und dann beschäftige ich mich wieder damit. Sind für mich echt toll und freu mich schon darauf.
MfG