Hilfe beim Countdown Projekt

Hallo Zusammen,

Ich habe gerade ein kleines Projekt am laufen wobei ich mit Hilfe von Programmierbaren LED Strips einen Countdown anzeigen lassen möchte.
Hier ein paar Einblicke:


4

Der Titel verrät bereits dass ich Schwierigkeiten habe. Genauer gesagt bringe ich den code nicht zum laufen.

Ich versuche mal zu erläutern wo meine Probleme liegen.

Ich habe mal einen anfänglichen Code auf die Beine gestellt welcher nur einen Countdown eines definierten wertes herunterzählen soll. Dieser funktioniert auch nicht schlecht, wobei es Probleme mit der Hundertstelle der Tage gibt. Das Format welches angezeigt werden soll ist folgendermassen: DDD:HH:MM:SS. Meiner Logik nach müsste ich jetzt einen maximalen Wert darstellen können von 999:23:59:59, dies ist aber nicht möglich. Wenn ich aber einen wert von 005:23:59:59 eingebe, funktioniert es.

Folgender Code habe dafür erstellt:

#include <Adafruit_NeoPixel.h>



//Definiere Countdown Zeit:
#define Tage      5   // Anzahl Tage in TTT
#define Stunden   20    // Anzahl Stunden in HH
#define Minuten   15    // Anzahl Minuten in MM
#define Sekunden  15    // Anzahl Sekunden in SS 



// Pin-Definitionen für die NeoPixel-Streifen
#define PIN_LED_STRIP_1 2  // Pin für Hundertstelle Tage
#define PIN_LED_STRIP_2 3  // Pin für Zehnerstelle Tage
#define PIN_LED_STRIP_3 4  // Pin für Einerstelle Tage
#define PIN_LED_STRIP_4 5  // Pin für Zehnerstelle Stunden
#define PIN_LED_STRIP_5 6  // Pin für Einerstelle Stunden
#define PIN_LED_STRIP_6 7  // Pin für Zehnerstelle Minuten
#define PIN_LED_STRIP_7 8  // Pin für Einerstelle Minuten
#define PIN_LED_STRIP_8 9  // Pin für Zehner stelle Sekunden
#define PIN_LED_STRIP_9 10  // Pin für Einerstelle Sekunden
#define PIN_LED_STRIP_10 12  // Pin für Buchstabenbeleuchtung 

#define NUM_LEDS 7 // Anzahl der LEDs Strip 1-9
#define NUM_LEDS_STRIP_10 12 // Anzahl der LEDs in Strip 10
#define NUM_STRIPS 10 

// Array für die NeoPixel-Streifen
Adafruit_NeoPixel strips[NUM_STRIPS] = {
  Adafruit_NeoPixel(NUM_LEDS, PIN_LED_STRIP_1, NEO_GRB + NEO_KHZ800),
  Adafruit_NeoPixel(NUM_LEDS, PIN_LED_STRIP_2, NEO_GRB + NEO_KHZ800),
  Adafruit_NeoPixel(NUM_LEDS, PIN_LED_STRIP_3, NEO_GRB + NEO_KHZ800),
  Adafruit_NeoPixel(NUM_LEDS, PIN_LED_STRIP_4, NEO_GRB + NEO_KHZ800),
  Adafruit_NeoPixel(NUM_LEDS, PIN_LED_STRIP_5, NEO_GRB + NEO_KHZ800),
  Adafruit_NeoPixel(NUM_LEDS, PIN_LED_STRIP_6, NEO_GRB + NEO_KHZ800),
  Adafruit_NeoPixel(NUM_LEDS, PIN_LED_STRIP_7, NEO_GRB + NEO_KHZ800),
  Adafruit_NeoPixel(NUM_LEDS, PIN_LED_STRIP_8, NEO_GRB + NEO_KHZ800),
  Adafruit_NeoPixel(NUM_LEDS, PIN_LED_STRIP_9, NEO_GRB + NEO_KHZ800), 
  Adafruit_NeoPixel(NUM_LEDS_STRIP_10, PIN_LED_STRIP_10, NEO_GRB + NEO_KHZ800)// Anpassung für 12 LEDs
};

unsigned long startTime;
unsigned long countdownDuration; 

// Definition der 7-Segment Zahlen
//      -->
//    ¦    ¦
//  ------>
//    ¦    ¦
//     <--
int segments[10][7] = {
  {0, 1, 1, 1, 1, 1, 1}, // 0
  {0, 1, 0, 0, 0, 0, 1}, // 1
  {1, 0, 1, 1, 0, 1, 1}, // 2
  {1, 1, 1, 0, 0, 1, 1}, // 3
  {1, 1, 0, 0, 1, 0, 1}, // 4
  {1, 1, 1, 0, 1, 1, 0}, // 5
  {1, 1, 1, 1, 1, 1, 0}, // 6
  {0, 1, 0, 0, 0, 1, 1}, // 7
  {1, 1, 1, 1, 1, 1, 1}, // 8
  {1, 1, 1, 0, 1, 1, 1}  // 9
};

// Definition der Zuordnung von Ziffern zu den LED-Strips
int digitStrips[10] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};




void setup() {
  Serial.begin(9600);
  startTime = millis(); // Initialisiere startTime

  // Initialisiere die Anfangszustände der Strips 1-9
  for (int i = 0; i < NUM_STRIPS; i++) {
    strips[i].begin();
    strips[i].show();  // Zeige die Anfangszustand der Strips
  }
  
  // Initialisiere den Anfangszustand von Strip 10
  for (int i = 0; i < NUM_STRIPS; i++) 
    strips[NUM_STRIPS-1].begin();
    strips[NUM_STRIPS-1].show();  // Zeige den Anfangszustand von Strip 10
  

  // Setze die Anfangszeit des Countdowns
  unsigned long initialDays = Tage;
  unsigned long initialHours = Stunden;
  unsigned long initialMinutes = Minuten;
  unsigned long initialSeconds = Sekunden;
  

countdownDuration = (initialDays * 24UL * 60UL * 60UL + initialHours * 60UL * 60UL + initialMinutes * 60UL + initialSeconds) * 1000UL;

Serial.print("Initial Countdown Time: ");
Serial.print(initialDays);
Serial.print(" days, ");
Serial.print(initialHours);
Serial.print(" hours, ");
Serial.print(initialMinutes);
Serial.print(" minutes, ");
Serial.print(initialSeconds);
Serial.println(" seconds");

}

void loop() {
  displayCountdown(); 
}

void displayCountdown() {
  unsigned long currentTime = millis();
  unsigned long elapsedTime = currentTime - startTime;
  unsigned long remainingTime = countdownDuration - elapsedTime;

    if (remainingTime < 0) {
    remainingTime = 0;
  }

  // Calculate remaining days, hours, minutes, and seconds
  unsigned long remainingDays = remainingTime / (24UL * 60UL * 60UL * 1000UL);
  remainingTime %= (24UL * 60UL * 60UL * 1000UL);
  unsigned long remainingHours = remainingTime / (60UL * 60UL * 1000UL);
  remainingTime %= (60UL * 60UL * 1000UL);
  unsigned long remainingMinutes = remainingTime / (60UL * 1000UL);
  remainingTime %= (60UL * 1000UL);
  unsigned long remainingSeconds = remainingTime / 1000UL;


  displayDigitsOnStrip(remainingDays / 100, 0); // Hundertstelle der Tage
  displayDigitsOnStrip((remainingDays / 10) % 10, 1); // Zehnerstelle der Tage
  displayDigitsOnStrip(remainingDays % 10, 2); // Einerstelle der Tage
  displayDigitsOnStrip(remainingHours / 10, 3); // Zehnerstelle der Stunden
  displayDigitsOnStrip(remainingHours % 10, 4); // Einerstelle der Stunden
  displayDigitsOnStrip(remainingMinutes / 10, 5); // Zehnerstelle der Minuten
  displayDigitsOnStrip(remainingMinutes % 10, 6); // Einerstelle der Minuten
  displayDigitsOnStrip(remainingSeconds / 10, 7); // Zehnerstelle der Sekunden
  displayDigitsOnStrip(remainingSeconds % 10, 8); // Einerstelle der Sekunden
  
  // Funktion für LED Strip 10
  displayColorOnStrip(strips[NUM_STRIPS - 1].Color(255, 0, 0)); // Rote LEDs für Strip 10
}

void displayDigitsOnStrip(int digit, int stripIndex) {
  for (int j = 0; j < 7; j++) {
    if (stripIndex >= 0 && stripIndex <= 2 && digit >= 100) {
      // Zeige nur die Hundertstelle der Tage an
      if (segments[digit / 100][j]) {
        strips[digitStrips[stripIndex]].setPixelColor(j, strips[digitStrips[stripIndex]].Color(255, 0, 0));
      } else {
        strips[digitStrips[stripIndex]].setPixelColor(j, strips[digitStrips[stripIndex]].Color(0, 0, 0));
      }
    } else {
      // Zeige die Ziffer normal an
      if (segments[digit][j]) {
        strips[digitStrips[stripIndex]].setPixelColor(j, strips[digitStrips[stripIndex]].Color(255, 0, 0));
      } else {
        strips[digitStrips[stripIndex]].setPixelColor(j, strips[digitStrips[stripIndex]].Color(0, 0, 0));
      }
    }
  }
  strips[digitStrips[stripIndex]].show();
}

// Funktion für LED Strip 10
void displayColorOnStrip(uint32_t color) {
  for (int j = 0; j < strips[NUM_STRIPS - 1].numPixels(); j++) {
    strips[NUM_STRIPS - 1].setPixelColor(j, color);
  }
  strips[NUM_STRIPS - 1].show();
}

Der finale Countdown soll über eine IR-Fernbedienung eingestellt werden können.

Ich konnte die Hex-Werte der Fernbedienung auslesen.
HEX-Wert: 45 -> 1
HEX-Wert: 46 -> 2
HEX-Wert: 47 -> 3
HEX-Wert: 44 -> 4
HEX-Wert: 40 -> 5
HEX-Wert: 43 -> 6
HEX-Wert: 7 -> 7
HEX-Wert: 15 -> 8
HEX-Wert: 9 -> 9
HEX-Wert: 19 -> 0
HEX-Wert: 18 -> up
HEX-Wert: 5A -> right
HEX-Wert: 52 -> down
HEX-Wert: 8 -> left
HEX-Wert: 1C -> ok

Mein erster versuch war einfach mal den Countdown über die Taste "OK" Starten und Stoppen zu können.
Wofür ich dieses Programm erstellt habe:

#include <Adafruit_NeoPixel.h>
#include <IRremote.h>

// Pin-Definition für den IR-Empfänger
const byte IR_RECEIVE_PIN = 11;
IRrecv irReceiver(IR_RECEIVE_PIN);
decode_results results;

bool countdownRunning = true;



// Pin-Definitionen für die NeoPixel-Streifen
#define PIN_LED_STRIP_1 2  // Pin für den ersten NeoPixel-Streifen
#define PIN_LED_STRIP_2 3  // Pin für den zweiten NeoPixel-Streifen
#define PIN_LED_STRIP_3 4  // Pin für den dritten NeoPixel-Streifen
#define PIN_LED_STRIP_4 5  // Pin für den vierten NeoPixel-Streifen
#define PIN_LED_STRIP_5 6  // Pin für den fünften NeoPixel-Streifen
#define PIN_LED_STRIP_6 7  // Pin für den sechsten NeoPixel-Streifen
#define PIN_LED_STRIP_7 8  // Pin für den siebten NeoPixel-Streifen
#define PIN_LED_STRIP_8 9  // Pin für den achten NeoPixel-Streifen
#define PIN_LED_STRIP_9 10  // Pin für den neunten NeoPixel-Streifen
#define PIN_LED_STRIP_10 12  // Pin für Buchstabenbeleuchtung 

#define NUM_LEDS 7 // Anzahl der LEDs Strip 1-9
#define NUM_LEDS_STRIP_10 12 // Anzahl der LEDs in Strip 10
#define NUM_STRIPS 10 

// Array für die NeoPixel-Streifen
Adafruit_NeoPixel strips[NUM_STRIPS] = {
  Adafruit_NeoPixel(NUM_LEDS, PIN_LED_STRIP_1, NEO_GRB + NEO_KHZ800),
  Adafruit_NeoPixel(NUM_LEDS, PIN_LED_STRIP_2, NEO_GRB + NEO_KHZ800),
  Adafruit_NeoPixel(NUM_LEDS, PIN_LED_STRIP_3, NEO_GRB + NEO_KHZ800),
  Adafruit_NeoPixel(NUM_LEDS, PIN_LED_STRIP_4, NEO_GRB + NEO_KHZ800),
  Adafruit_NeoPixel(NUM_LEDS, PIN_LED_STRIP_5, NEO_GRB + NEO_KHZ800),
  Adafruit_NeoPixel(NUM_LEDS, PIN_LED_STRIP_6, NEO_GRB + NEO_KHZ800),
  Adafruit_NeoPixel(NUM_LEDS, PIN_LED_STRIP_7, NEO_GRB + NEO_KHZ800),
  Adafruit_NeoPixel(NUM_LEDS, PIN_LED_STRIP_8, NEO_GRB + NEO_KHZ800),
  Adafruit_NeoPixel(NUM_LEDS, PIN_LED_STRIP_9, NEO_GRB + NEO_KHZ800), 
  Adafruit_NeoPixel(NUM_LEDS_STRIP_10, PIN_LED_STRIP_10, NEO_GRB + NEO_KHZ800)// Anpassung für 12 LEDs
};

unsigned long startTime;
unsigned long countdownDuration = 2UL * 365UL * 24UL * 60UL * 60UL * 1000UL; // 2 Jahre in Millisekunden

// Definition der 7-Segment Zahlen
//      -->
//    ¦    ¦
//  ------>
//    ¦    ¦
//     <--
int segments[10][7] = {
  {0, 1, 1, 1, 1, 1, 1}, // 0
  {0, 1, 0, 0, 0, 0, 1}, // 1
  {1, 0, 1, 1, 0, 1, 1}, // 2
  {1, 1, 1, 0, 0, 1, 1}, // 3
  {1, 1, 0, 0, 1, 0, 1}, // 4
  {1, 1, 1, 0, 1, 1, 0}, // 5
  {1, 1, 1, 1, 1, 1, 0}, // 6
  {0, 1, 0, 0, 0, 1, 1}, // 7
  {1, 1, 1, 1, 1, 1, 1}, // 8
  {1, 1, 1, 0, 1, 1, 1}  // 9
};

// Definition der Zuordnung von Ziffern zu den LED-Strips
int digitStrips[10] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};

void displayCountdown();

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

void setup() {
  Serial.begin(9600);
  Serial.print("Empfänger Starten");
  //irReceiver.enableIRIn();  // Starte den Infrarot-Empfänger
  IrReceiver.begin(IR_RECEIVE_PIN, ENABLE_LED_FEEDBACK);
  startTime = millis(); // Initialisiere startTime

  for (int i = 0; i < NUM_STRIPS; i++) {
    strips[i].begin();
    strips[i].show();  // Zeige die Anfangszustand der Strips
  }

  // Setze die Anfangszeit des Countdowns
  unsigned long initialDays = 0;
  unsigned long initialHours = 0;
  unsigned long initialMinutes = 0;
  unsigned long initialSeconds = 0;
  
  countdownDuration = (initialDays * 24UL * 60UL * 60UL + initialHours * 60UL * 60UL + initialMinutes * 60UL + initialSeconds) * 1000UL;

  Serial.print("Initial Countdown Time: ");
  Serial.print(initialDays);
  Serial.print(" days, ");
  Serial.print(initialHours);
  Serial.print(" hours, ");
  Serial.print(initialMinutes);
  Serial.print(" minutes, ");
  Serial.print(initialSeconds);
  Serial.println(" seconds");
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////

void loop() {
  if (irReceiver.decode()) {
    handleIRCommand(results.value);
    irReceiver.resume();  // Empfang für das nächste Signal vorbereiten
  }

  if (countdownRunning) {
    displayCountdown();
  }
}

void handleIRCommand(unsigned long irValue) {
  Serial.print("Unknown signal: 0x");
  Serial.println(results.value);
  Serial.println(IrReceiver.decodedIRData.command);

  switch (irValue) {
    case 0x1C: // "OK"-Taste
      if (countdownRunning) {
        stopCountdown();
        Serial.println("Countdown gestoppt.");
      } else {
        startCountdown();
        Serial.println("Countdown gestartet.");
      }
      break;
  }
}

void startCountdown() {
  startTime = millis();
  countdownRunning = true;
}

void stopCountdown() {
  countdownRunning = false;
}

void displayCountdown() {
  unsigned long currentTime = millis();
  unsigned long elapsedTime = currentTime - startTime;
  unsigned long remainingTime = countdownDuration - elapsedTime;

  // Calculate remaining days, hours, minutes, and seconds
  unsigned long remainingDays = remainingTime / (24UL * 60UL * 60UL * 1000UL);
  remainingTime %= (24UL * 60UL * 60UL * 1000UL);
  unsigned long remainingHours = remainingTime / (60UL * 60UL * 1000UL);
  remainingTime %= (60UL * 60UL * 1000UL);
  unsigned long remainingMinutes = remainingTime / (60UL * 1000UL);
  remainingTime %= (60UL * 1000UL);
  unsigned long remainingSeconds = remainingTime / 1000UL;

  displayDigitsOnStrip(remainingDays / 100, 0); // Hundertstelle der Tage
  displayDigitsOnStrip((remainingDays / 10) % 10, 1); // Zehnerstelle der Tage
  displayDigitsOnStrip(remainingDays % 10, 2); // Einerstelle der Tage
  displayDigitsOnStrip(remainingHours / 10, 3); // Zehnerstelle der Stunden
  displayDigitsOnStrip(remainingHours % 10, 4); // Einerstelle der Stunden
  displayDigitsOnStrip(remainingMinutes / 10, 5); // Zehnerstelle der Minuten
  displayDigitsOnStrip(remainingMinutes % 10, 6); // Einerstelle der Minuten
  displayDigitsOnStrip(remainingSeconds / 10, 7); // Zehnerstelle der Sekunden
  displayDigitsOnStrip(remainingSeconds % 10, 8); // Einerstelle der Sekunden
  
  // Neue Funktion für LED Strip 10
  displayColorOnStrip(strips[NUM_STRIPS - 1].Color(255, 0, 0)); // Rote LEDs für Strip 10
}

void displayDigitsOnStrip(int digit, int stripIndex) {
  for (int j = 0; j < 7; j++) {
    if (segments[digit][j]) {
      strips[digitStrips[stripIndex]].setPixelColor(j, strips[digitStrips[stripIndex]].Color(255, 0, 0)); // Rote LEDs für die Ziffer
    } else {
      strips[digitStrips[stripIndex]].setPixelColor(j, strips[digitStrips[stripIndex]].Color(0, 0, 0)); // Ausschalten der LEDs für inaktive Segmente
    }
  }
  strips[digitStrips[stripIndex]].show(); // Zeige die Ziffer auf dem entsprechenden LED-Streifen
}

// Seperate Funktion für LED Strip 10
void displayColorOnStrip(uint32_t color) {
  for (int j = 0; j < strips[NUM_STRIPS - 1].numPixels(); j++) {
    strips[NUM_STRIPS - 1].setPixelColor(j, color);
  }
  strips[NUM_STRIPS - 1].show();
}

In diesem Programm erkennt er aber die Signale der Fernbedienung nicht. Beziehungsweise stimmen die Tastenwerte nicht überein mit den ausgelesen Werten.

Eigentlich möchte ich es wie eine Backofenuhr einstellen können. Sprich die knöpfe rechts/links sollen zwischen den zahlen navigieren wobei die gewählte stelle Blinken soll, hoch/runter soll den Wert +1/-1 verändern und die Zahlen sollen den definierten wert direkt schreiben. Dann noch "OK für Start und Stopp.

Diese Aufgabe ist leider über meinen Kenntnissen, ich hoffe jemand kann mir weiterhelfen

Grüsse

Deine 999 Tage gehen weit über den Wertebereich von 32 Bit unsigned long hinaus.

Gruß Tommy

Der Kommentar stimmt nicht ganz mit dem Code zusammen.
wenn NUM_STRIPS = 10
dann läuft das erste for
von 0 bis 9 also die Strips von 0 bis 9 initialisiert.
und das zweite for
initialisiert zehn mal Strip 9

mit 32 Bit kommt man bis 49,7 Tage.

Grüße Uwe

Moin @fabusi ,

da die Zeitmessung mit millis() bei einem Controller auf Dauer nicht besonders präzise ist (vorsichtig ausgedrückt :wink: ), solltest Du bei diesen Zeiträumen auf entweder eine Echtzeituhr oder einen Controller mit WLAN umstellen, der die Zeit mit einem Zeitserver abgleichen kann.

Für eine Echtzeituhr habe ich Ende letzten Jahres mal für jemandem im Forum ein Beispiel erstellt, dass auf Wokwi zu finden ist:

Christmas Count Down - Wokwi ESP32, STM32, Arduino Simulator

Nicht genau das, was Du machen willst, aber vielleicht nahe genug dran.

Ansonsten müsste ein Sekundenzähler unsigned long für 1000 Tage

  • 1000 Tage * 3600 *24 = 86.400.000
  • unsigned long (32 bit)= 4.294.967.295

ausreichen. Allerdings - wie man sieht - nicht für Millisekunden :wink:

1 Like

Die braucht er wohl auch nicht. Eine millis()-Routine, die aller 1000 millis die Sekunden erhöht. Die Langzeitgenauigkeit ist das andere Problem. Da kennen wir seine Anforderungen nicht. Oft wird bei der Grobplanung ja erst mal alles auf Maximum gestellt, egal, ob ob das braucht oder nicht.

Gruß Tommy

Jo, gepostet wird in der Regel ja nicht, was das Ziel ist, sondern das Problem mit einem nicht funktionierenden Lösungsansatz...

:wink:

Ich seh da noch ein Problem: Für das Aktualisieren des WS2812 wird der Interrupt deaktiviert.
IRemote wird vermutlich den Interrupt benutzen. Auch millis() braucht den.

Vielleicht kann man das CLC Beispiel zu CCL portieren und einen Arduino Nano Every benutzen.

Dann werden die Daten nicht mehr per Bitbanging auf den Pins rausgeschoben sondern per SPI.

WS2812 und IRremote können nicht zusammen auf dem gleichen klassischen MC laufen.

Gruß Tommy

Guter Einwand!

Wenn man dem hier glauben darf, sollte die Library "IRLibAll.h" zusammen mit Neopixel funktionieren:

https://learn.adafruit.com/using-an-infrared-library/controlling-neopixels-with-ir-1

Müsste man mal testen ...

    strip.show();
    myReceiver.enableIRIn(); //Restart the receiver

Ich denke der Trick liegt darin, das man nachdem man das Timing vom IReciver gestört hat, den neu initialisiert. Das bedeutet aber auch, das man die LEDs so selten wie möglich aktualisiert.

Fehlt noch eine Lösung dafür, das dir millis() wegläuft.

Bin nicht sicher, ob das mit dem Reinitialisieren funktioniert ...

Falls nicht, findest Du im Netz dazu Folgendes:

https://github.com/Arduino-IRremote/Arduino-IRremote#problems-with-neopixels-fastled-etc

Hallo zusammen,

erst einmal vielen Dank für die schnelle Rückmeldung.

Ich sehe, mein Problem ist doch etwas umfangreicher als ich dachte.

Vielleicht kurz etwas zum Hintergrund. Wie ich sehe, wurde schon richtig vermutet, dass der Countdown auf ein bestimmtes Datum herunterzählt, genauer gesagt auf eine Veranstaltung die alle zwei Jahre stattfindet. Also ca. 730 Tage, aber das ist immer noch zu lang. Das Projekt soll am Ende in einer Bar aufgehängt werden und wir haben uns gedacht, es wäre cool, wenn man sieht, dass etwas passiert. Deswegen der Countdown bis auf die Sekunde. (Also irgendwie nicht
nicht unbedingt notwendig)

Das mit den 32Bit macht Sinn, leider habe ich da nicht dran gedacht... Offensichtlich.

Also müsste ich erst mal die Sache mit den maximalen Tagen angehen. Bevor es überhaupt Sinn macht, die IR-Fernbedienung einzubauen.

Den Vorschlag mit dem Wokwi ESP32 halte ich für eine sehr gute Lösung. Damit wäre auch das Problem der Genauigkeit gelöst. Ist ein Countdown von 2 Jahren damit möglich?

und die IR-Remote könnte ich probieren mit der IRLibAll.h zu integrieren, habe ich das richtig interpretiert?

LG

falls du noch überlegen willst.
Ohne RTC wird das mit einem Arduino UNO nichts dauerhaftes.
Ein ESP32 Board das du in das Wifi lassen kannst, hätte "immer" eine akurate Zeit über NTP.
Die Differenz von einem Zeitstempel von "Datum in zwei Jahren" auf Heute ist ein klacks
Auch kannst du am ESP32 eine Website erstellen und dann mit dem Handy das Zieldatum ändern.
Damit würde das IR-Gedöns wegfallen.

1 Like

Zu IR siehe auch meinen Post 11.

Das Beispiel aus Post 4 sollte eigentlich fast alles zur Zeitberechnung beinhalten, was gebraucht wird, um Tage, Stunden oder Sekunden zwischen zwei Daten zu errechnen.

Die sogenannte Epoch-Zeit erhält man sowohl bei einer RTC wie auch bei Abfrage eines Zeitservers im Netz. Letzteres hat den Charme, dass man die Zeit regelmäßig (einmal pro Tag oder pro Stunde) automatisch synchronisieren kann.

Das Beispiel errechnet die zeitliche Differenz zwischen "Jetztzeit" und dem nächsten Heiligabend.

Was mich stutzen lässt, ist das Zielformat

DDD:HH:MM:SS

Wenn Du einen Countdown getrennt nach Tagen, Stunden, Minuten und Sekunden darstellen willst, braucht es eigentlich

  • Anzahl der Tage bis zum letzten Tag
  • Aktuelle Uhrzeit

Man nehme die aktuelle Uhrzeit und errechnet für die Darstellung

HH = 23 - aktuelle Stunde (ergibt 23 ... 0)
MM = 59 - aktuelle Minute (ergibt 59 ... 0)
SS = 59 - aktuelle Sekunde (ergibt 59 ... 0)

Mit

anzahlTage = 2*365 (+ ggf. Schalttag)-1

ergibt sich

DDD = anzahlTage

Dann bei jedem Übergang von 23 Uhr auf 0 Uhr genau einmal anzahlTage--

Das sollte es im Wesentlichen sein.

Ich hatte gestern abend nur die aufgabe mitgenommen.
Das ist dabei rausgekommen.

// Forensketch Countdown
// https://forum.arduino.cc/t/hilfe-beim-countdown-projekt/1214019/15

#include <Streaming.h>     // https://github.com/janelia-arduino/Streaming


#include <IRremote.h>
constexpr byte IR_RECEIVE_PIN {11};
IRrecv irReceiver(IR_RECEIVE_PIN);

constexpr uint8_t irOne   {0x45};
constexpr uint8_t irTwo   {0x46};
constexpr uint8_t irThree {0x47};
constexpr uint8_t irFor   {0x44};
constexpr uint8_t irFive  {0x40};
constexpr uint8_t irSix   {0x43};
constexpr uint8_t irSeven {0x07};
constexpr uint8_t irEight {0x15};
constexpr uint8_t irNine  {0x09};
constexpr uint8_t irNull  {0x19};
constexpr uint8_t irUp    {0x18};
constexpr uint8_t irDown  {0x52};
constexpr uint8_t irLeft  {0x08};
constexpr uint8_t irRight {0x5A};
constexpr uint8_t irOk    {0x1C};

#include <Adafruit_NeoPixel.h>

constexpr uint8_t stripPin[] {2, 3, 4, 5, 6, 7, 8, 9, 10,};
// Anzahl Positionen im Array
constexpr uint8_t digitPos {sizeof(stripPin) / sizeof(stripPin[0])};

constexpr byte NUM_LEDS {7};
Adafruit_NeoPixel stripe[digitPos] =
{
  Adafruit_NeoPixel(NUM_LEDS, stripPin[0], NEO_GRB + NEO_KHZ800),
  Adafruit_NeoPixel(NUM_LEDS, stripPin[1], NEO_GRB + NEO_KHZ800),
  Adafruit_NeoPixel(NUM_LEDS, stripPin[2], NEO_GRB + NEO_KHZ800),
  Adafruit_NeoPixel(NUM_LEDS, stripPin[3], NEO_GRB + NEO_KHZ800),
  Adafruit_NeoPixel(NUM_LEDS, stripPin[4], NEO_GRB + NEO_KHZ800),
  Adafruit_NeoPixel(NUM_LEDS, stripPin[5], NEO_GRB + NEO_KHZ800),
  Adafruit_NeoPixel(NUM_LEDS, stripPin[6], NEO_GRB + NEO_KHZ800),
  Adafruit_NeoPixel(NUM_LEDS, stripPin[7], NEO_GRB + NEO_KHZ800),
  Adafruit_NeoPixel(NUM_LEDS, stripPin[8], NEO_GRB + NEO_KHZ800),
};
constexpr uint32_t colourRed {0xFF0000};

constexpr byte ledNumbers {10};
constexpr bool segments[ledNumbers][NUM_LEDS]
{
  {0, 1, 1, 1, 1, 1, 1}, // 0
  {0, 1, 0, 0, 0, 0, 1}, // 1
  {1, 0, 1, 1, 0, 1, 1}, // 2
  {1, 1, 1, 0, 0, 1, 1}, // 3
  {1, 1, 0, 0, 1, 0, 1}, // 4
  {1, 1, 1, 0, 1, 1, 0}, // 5
  {1, 1, 1, 1, 1, 1, 0}, // 6
  {0, 1, 0, 0, 0, 1, 1}, // 7
  {1, 1, 1, 1, 1, 1, 1}, // 8
  {1, 1, 1, 0, 1, 1, 1}  // 9
};

uint8_t anzeige[digitPos] = {0};
uint8_t lastAnzeige[digitPos] = {0};

// Positionen im Array
constexpr uint8_t second_Digit_One {0};
constexpr uint8_t second_Digit_Two {second_Digit_One + 1};
constexpr uint8_t minute_Digit_One {second_Digit_Two + 1};
constexpr uint8_t minute_Digit_Two {minute_Digit_One + 1};
constexpr uint8_t hour_Digit_One   {minute_Digit_Two + 1};
constexpr uint8_t hour_Digit_Two   {hour_Digit_One   + 1};
constexpr uint8_t day_Digit_One    {hour_Digit_Two   + 1};
constexpr uint8_t day_Digit_Two    {day_Digit_One    + 1};
constexpr uint8_t day_Digit_Three  {day_Digit_Two    + 1};

constexpr uint32_t oneSecond {1000}; // ms

uint32_t lastMillis;
uint32_t myMillis;

bool isCountDown = false;


void setup()
{
  Serial.begin(115200);
#if (defined(ARDUINO_AVR_MEGA) || defined(ARDUINO_AVR_MEGA2650)) // https://github.com/arduino/Arduino/issues/10764
  delay(300);
#endif
  Serial << (F("\r\nStart...\r\n")) << endl;
  IrReceiver.begin(IR_RECEIVE_PIN, ENABLE_LED_FEEDBACK);
  for (byte b = 0; b < digitPos; b++)
  {
    stripe[b].begin();
    stripe[b].fill(colourRed);
    stripe[b].show();
  }
  delay(1000);
  for (byte b = 0; b < digitPos; b++)
  {
    stripe[b].clear();
    stripe[b].show();
  }
}

void  loop()
{
  myMillis = millis();
  checkIr();
  newTime();
  checkTime();
}

//
void checkIr()
{
  static byte myDigit = 0;
  if (IrReceiver.decode())
  {
    if (isCountDown)                   // CountDown aktiv?
    {
      if (IrReceiver.decodedIRData.command == irOk)
      { isCountDown = false; }         // CountDown: STOP!
    }
    else                               // CountDown nicht aktiv
      switch (IrReceiver.decodedIRData.command)
      {
        case irOk:                     // Countdown: START!
          isCountDown = true;
          myDigit = 0;
          lastMillis = myMillis;
          break;
        case irUp:
          anzeige[myDigit]++;
          if (anzeige[myDigit] > 9)
          { anzeige[myDigit] = 0; }
          break;
        case irDown:
          anzeige[myDigit]--;
          if (anzeige[myDigit] > 9)
          { anzeige[myDigit] = 9; }
          break;
        case irLeft:
          myDigit++;
          if (myDigit > digitPos)
          { myDigit = 0; }
          break;
        case irRight:
          myDigit--;
          if (myDigit > digitPos)
          { myDigit = 9; }
          break;
        // *INDENT-OFF*
        case irOne:    anzeige[myDigit] = 1;  break;
        case irTwo:    anzeige[myDigit] = 2;  break;
        case irThree:  anzeige[myDigit] = 3;  break;
        case irFor:    anzeige[myDigit] = 4;  break;
        case irFive:   anzeige[myDigit] = 5;  break;
        case irSix:    anzeige[myDigit] = 6;  break;
        case irSeven:  anzeige[myDigit] = 7;  break;
        case irEight:  anzeige[myDigit] = 8;  break;
        case irNine:   anzeige[myDigit] = 9;  break;
        case irNull:   anzeige[myDigit] = 0;  break;
       // *INDENT-ON*
      }
    IrReceiver.resume();
  }
}
//
void checkCountDown()
{
  if (isCountDown)                           // Prüfung nur wenn countDown aktiv
  {
    isCountDown = false;                     // Merker löschen
    for (byte b = 0; b < digitPos; b++)      // zählt durch alle Ziffern
    {
      if (anzeige[b])                        // aktuelle Ziffer ist gesetzt?
      { isCountDown = true; }                // Merker setzen
    }
  }
}
//
void printControl()
{
  Serial<<anzeige[8]<<anzeige[7]<<anzeige[6]<<" - "<<anzeige[5]<<anzeige[4]<<":"<<anzeige[3]<<anzeige[2]<<":"<<anzeige[1]<<anzeige[0]<<endl;
}
//
void sendDigit(const byte &number, const byte &digit)
{
  stripe[digit].clear();
  for (byte b = 0; b < NUM_LEDS; b++)
  {
    if (segments[number][b])
    { stripe[digit].setPixelColor(b, stripe[digit].Color(255, 0, 0)); }
  }
  stripe[digit].show();
  printControl();                             // Ausgabe auf dem SerMon
}
//
void checkTime()
{
  for (byte b = 0; b < digitPos; b++)         // zählt durch alle Ziffern
  {
    if (anzeige[b] != lastAnzeige[b])         // Ziffer ist geändert?
    {
      sendDigit(anzeige[b], b);               // Anzeige ändern
      lastAnzeige[b] = anzeige[b];            // Ziffer merken
    }
  }
  checkCountDown();                           
}
//
void newTime()
{
  if (myMillis - lastMillis >= oneSecond)
  {
    if (isCountDown)
    { anzeige[second_Digit_One]--; }
    lastMillis += oneSecond;
  }
  else
  { return; }
  // *INDENT-OFF*
  if (anzeige[second_Digit_One] > 9) { anzeige[second_Digit_One] = 9;   anzeige[second_Digit_Two]--; }
  if (anzeige[second_Digit_Two] > 5) { anzeige[second_Digit_Two] = 5;   anzeige[minute_Digit_One]--; }
  if (anzeige[minute_Digit_One] > 9) { anzeige[minute_Digit_One] = 9;   anzeige[minute_Digit_Two]--; }
  if (anzeige[minute_Digit_Two] > 5) { anzeige[minute_Digit_Two] = 5;   anzeige[hour_Digit_One]--;   }
  if (anzeige[hour_Digit_One]   > 3) { anzeige[hour_Digit_One]   = 3;   anzeige[hour_Digit_Two]--;   }
  if (anzeige[hour_Digit_Two]   > 2) { anzeige[hour_Digit_Two]   = 2;   anzeige[day_Digit_One]--;    }
  if (anzeige[day_Digit_One]    > 9) { anzeige[day_Digit_One]    = 9;   anzeige[day_Digit_Two]--;    }
  if (anzeige[day_Digit_Two]    > 9) { anzeige[day_Digit_Two]    = 9;   anzeige[day_Digit_Three]--;  }
  if (anzeige[day_Digit_Three]  > 9) { anzeige[day_Digit_Three]  = 9; }
  // *INDENT-ON*
}

Hinweis: Ich verzichte aus Gründen der Einfachheit auf eine, irgendwie geartetet, große Zahl aus der irgendwas errechnet werden muss.

Stellst Du isCountDown auf true und oneSecond auf 10, dann kannst Du das schnell ablaufend auch auf dem SerMon verfolgen :slight_smile:

@my_xy_projekt das isch schon eindrücklich, dein Programm hat auf anhib besser funktioniert als meine 312,75 Versuche zuvor :wink: Mit den Stellen ist etwas noch nicht ganz korrekt. Einstellen lässt sich nur die Hundertstelle für die Tage und die Zehnerstelle für Stunden, Minuten und Sekunden. Wen der Countdown startet und die Hunderstelle die 0-Schwelle unterschreitet erscheinen dazu die Zehner und Einerstellen.

Du hast mir auf jedenfall ein Licht am Ende des Tunnels gezeigt. Eigentlich müsste es ja möglich sein auf Basis deines Codes auch mit einer RTC zu arbeiten. Vielleicht kommt mir da auch nur ein Zug entgegen.

Ich kann blöderweise nicht mit sicherheit sagen ob in Zukunft immer eine WLan verbindung zur Verfügung steht weshalb die Kontrolle über die IR-Remote noch nicht komplett vom Tisch ist.

Ich versuche auf jedenfall deinen Code zu verstehen und darauf aufzubauen.

Weiter habe ich ein ESP32 Modul bestellt und werde auch diesen Weg noch weiter Verfolgen. Dank @ec2021 ist ja auch dafür ein funktionierender Code als Basis zur Verfügung.

Wenn Du nicht alle Stellen ändern kannst, dann muss ich nochmal drüber schauen. Eigentlich sollte das funktionieren.
Vielleicht hängt es auch an der FB, dass die mehrfach den right/left Code sendet und damit eine Stelle überspringt.

Eigentlich müsste die Anzeige ständig an sein... Hm.
Na mal sehen, was mir noch einfällt.
Schön, wenn es Dir gefallen hat. :slight_smile:

Hier mal was geändertes.
In der IR-Funktion las ich jetz den HEX-Code ausgeben und ich las den Überlauf vorher prüfen.

// Forensketch Countdown
// https://forum.arduino.cc/t/hilfe-beim-countdown-projekt/1214019/17

#include <Streaming.h>     // https://github.com/janelia-arduino/Streaming


#include <IRremote.h>
constexpr byte IR_RECEIVE_PIN {11};
IRrecv irReceiver(IR_RECEIVE_PIN);

constexpr uint8_t irOne   {0x45};
constexpr uint8_t irTwo   {0x46};
constexpr uint8_t irThree {0x47};
constexpr uint8_t irFor   {0x44};
constexpr uint8_t irFive  {0x40};
constexpr uint8_t irSix   {0x43};
constexpr uint8_t irSeven {0x07};
constexpr uint8_t irEight {0x15};
constexpr uint8_t irNine  {0x09};
constexpr uint8_t irNull  {0x19};
constexpr uint8_t irUp    {0x18};
constexpr uint8_t irDown  {0x52};
constexpr uint8_t irLeft  {0x08};
constexpr uint8_t irRight {0x5A};
constexpr uint8_t irOk    {0x1C};

#include <Adafruit_NeoPixel.h>

constexpr uint8_t stripPin[] {2, 3, 4, 5, 6, 7, 8, 9, 10,};
// Anzahl Positionen im Array
constexpr uint8_t digitPos {sizeof(stripPin) / sizeof(stripPin[0])};

constexpr byte NUM_LEDS {7};
Adafruit_NeoPixel stripe[digitPos] =
{
  Adafruit_NeoPixel(NUM_LEDS, stripPin[0], NEO_GRB + NEO_KHZ800),
  Adafruit_NeoPixel(NUM_LEDS, stripPin[1], NEO_GRB + NEO_KHZ800),
  Adafruit_NeoPixel(NUM_LEDS, stripPin[2], NEO_GRB + NEO_KHZ800),
  Adafruit_NeoPixel(NUM_LEDS, stripPin[3], NEO_GRB + NEO_KHZ800),
  Adafruit_NeoPixel(NUM_LEDS, stripPin[4], NEO_GRB + NEO_KHZ800),
  Adafruit_NeoPixel(NUM_LEDS, stripPin[5], NEO_GRB + NEO_KHZ800),
  Adafruit_NeoPixel(NUM_LEDS, stripPin[6], NEO_GRB + NEO_KHZ800),
  Adafruit_NeoPixel(NUM_LEDS, stripPin[7], NEO_GRB + NEO_KHZ800),
  Adafruit_NeoPixel(NUM_LEDS, stripPin[8], NEO_GRB + NEO_KHZ800),
};
constexpr uint32_t colourRed {0xFF0000};

constexpr byte ledNumbers {10};
constexpr bool segments[ledNumbers][NUM_LEDS]
{
  {0, 1, 1, 1, 1, 1, 1}, // 0
  {0, 1, 0, 0, 0, 0, 1}, // 1
  {1, 0, 1, 1, 0, 1, 1}, // 2
  {1, 1, 1, 0, 0, 1, 1}, // 3
  {1, 1, 0, 0, 1, 0, 1}, // 4
  {1, 1, 1, 0, 1, 1, 0}, // 5
  {1, 1, 1, 1, 1, 1, 0}, // 6
  {0, 1, 0, 0, 0, 1, 1}, // 7
  {1, 1, 1, 1, 1, 1, 1}, // 8
  {1, 1, 1, 0, 1, 1, 1}  // 9
};

uint8_t anzeige[digitPos] = {0};
uint8_t lastAnzeige[digitPos] = {0};

// Positionen im Array
constexpr uint8_t second_Digit_One {0};
constexpr uint8_t second_Digit_Two {second_Digit_One + 1};
constexpr uint8_t minute_Digit_One {second_Digit_Two + 1};
constexpr uint8_t minute_Digit_Two {minute_Digit_One + 1};
constexpr uint8_t hour_Digit_One   {minute_Digit_Two + 1};
constexpr uint8_t hour_Digit_Two   {hour_Digit_One   + 1};
constexpr uint8_t day_Digit_One    {hour_Digit_Two   + 1};
constexpr uint8_t day_Digit_Two    {day_Digit_One    + 1};
constexpr uint8_t day_Digit_Three  {day_Digit_Two    + 1};

constexpr uint32_t oneSecond {1000}; // ms

uint32_t lastMillis;
uint32_t myMillis;

bool isCountDown = false;


void setup()
{
  Serial.begin(115200);
#if (defined(ARDUINO_AVR_MEGA) || defined(ARDUINO_AVR_MEGA2650)) // https://github.com/arduino/Arduino/issues/10764
  delay(300);
#endif
  Serial << (F("\r\nStart...\r\n")) << endl;
  IrReceiver.begin(IR_RECEIVE_PIN, ENABLE_LED_FEEDBACK);
  for (byte b = 0; b < digitPos; b++)
  {
    stripe[b].begin();
    stripe[b].fill(colourRed);
    stripe[b].show();
  }
  delay(1000);
  for (byte b = 0; b < digitPos; b++)
  {
    stripe[b].clear();
    stripe[b].show();
  }
}

void  loop()
{
  myMillis = millis();
  checkIr();
  newTime();
  checkTime();
}

//
void checkIr()
{
  static byte myDigit = 0;
  if (IrReceiver.decode())
  {
    Serial << (F("IR-CODE: ")) << _HEX(IrReceiver.decodedIRData.command) << (F(" erkannt")) << endl;
    if (isCountDown)                   // CountDown aktiv?
    {
      if (IrReceiver.decodedIRData.command == irOk)
      { isCountDown = false; }         // CountDown: STOP!
    }
    else                               // CountDown nicht aktiv
      switch (IrReceiver.decodedIRData.command)
      {
        case irOk:                     // Countdown: START!
          isCountDown = true;
          myDigit = 0;
          lastMillis = myMillis;
          break;
        case irUp:
          anzeige[myDigit]++;
          if (anzeige[myDigit] > 9)
          { anzeige[myDigit] = 0; }
          break;
        case irDown:
          anzeige[myDigit]--;
          if (anzeige[myDigit] > 9)
          { anzeige[myDigit] = 9; }
          break;
        case irLeft:
          myDigit++;
          if (myDigit > digitPos)
          { myDigit = 0; }
          break;
        case irRight:
          myDigit--;
          if (myDigit > digitPos)
          { myDigit = 9; }
          break;
        // *INDENT-OFF*
        case irOne:    anzeige[myDigit] = 1;  break;
        case irTwo:    anzeige[myDigit] = 2;  break;
        case irThree:  anzeige[myDigit] = 3;  break;
        case irFor:    anzeige[myDigit] = 4;  break;
        case irFive:   anzeige[myDigit] = 5;  break;
        case irSix:    anzeige[myDigit] = 6;  break;
        case irSeven:  anzeige[myDigit] = 7;  break;
        case irEight:  anzeige[myDigit] = 8;  break;
        case irNine:   anzeige[myDigit] = 9;  break;
        case irNull:   anzeige[myDigit] = 0;  break;
       // *INDENT-ON*
      }
    IrReceiver.resume();
    checkCount();
  }
}
//
void checkCountDown()
{
  if (isCountDown)                           // Prüfung nur wenn countDown aktiv
  {
    isCountDown = false;                     // Merker löschen
    for (byte b = 0; b < digitPos; b++)      // zählt durch alle Ziffern
    {
      if (anzeige[b])                        // aktuelle Ziffer ist gesetzt?
      { isCountDown = true; }                // Merker setzen
    }
  }
}
//
void printControl()
{
  Serial << anzeige[8] << anzeige[7] << anzeige[6] << " - " << anzeige[5] << anzeige[4] << ":" << anzeige[3] << anzeige[2] << ":" << anzeige[1] << anzeige[0] << endl;
}
//
void sendDigit(const byte &number, const byte &digit)
{
  stripe[digit].clear();
  for (byte b = 0; b < NUM_LEDS; b++)
  {
    if (segments[number][b])
    { stripe[digit].setPixelColor(b, stripe[digit].Color(255, 0, 0)); }
  }
  stripe[digit].show();
  printControl();                             // Ausgabe auf dem SerMon
}
//
void checkTime()
{
  for (byte b = 0; b < digitPos; b++)         // zählt durch alle Ziffern
  {
    if (anzeige[b] != lastAnzeige[b])         // Ziffer ist geändert?
    {
      sendDigit(anzeige[b], b);               // Anzeige ändern
      lastAnzeige[b] = anzeige[b];            // Ziffer merken
    }
  }
  checkCountDown();
}
//
void newTime()
{
  if (myMillis - lastMillis >= oneSecond)
  {
    if (isCountDown)
    { anzeige[second_Digit_One]--; }
    lastMillis += oneSecond;
  }
  else
  { return; }
  checkCount();
}
//
void checkCount()
{
    // *INDENT-OFF*
  if (anzeige[second_Digit_One] > 9) { anzeige[second_Digit_One] = 9;   anzeige[second_Digit_Two]--; }
  if (anzeige[second_Digit_Two] > 5) { anzeige[second_Digit_Two] = 5;   anzeige[minute_Digit_One]--; }
  if (anzeige[minute_Digit_One] > 9) { anzeige[minute_Digit_One] = 9;   anzeige[minute_Digit_Two]--; }
  if (anzeige[minute_Digit_Two] > 5) { anzeige[minute_Digit_Two] = 5;   anzeige[hour_Digit_One]--;   }
  if (anzeige[hour_Digit_One]   > 3) { anzeige[hour_Digit_One]   = 3;   anzeige[hour_Digit_Two]--;   }
  if (anzeige[hour_Digit_Two]   > 2) { anzeige[hour_Digit_Two]   = 2;   anzeige[day_Digit_One]--;    }
  if (anzeige[day_Digit_One]    > 9) { anzeige[day_Digit_One]    = 9;   anzeige[day_Digit_Two]--;    }
  if (anzeige[day_Digit_Two]    > 9) { anzeige[day_Digit_Two]    = 9;   anzeige[day_Digit_Three]--;  }
  if (anzeige[day_Digit_Three]  > 9) { anzeige[day_Digit_Three]  = 9; }
  // *INDENT-ON*
}

Kleine Korrektur meinerseits. In meinem Kommentar klingt das als wäre der Fehler bestimmt im Code. Ich hatte aber nicht so viel Zeit alles durchzugehen um zu kontrollieren das auch alles mit meinem Setup überrein stimmt dazu kommt das ich auf die schnelle nicht alles verstanden habe. Wenn ich mir also das Niveau deines Codes bewusst mache sehe ich die Wahrscheinlichkeit höher das der Fehler von mir aus gekommen ist :sweat_smile:

1 Like

ist ganz unten.
Das ist nix, was irgendwo zeigbar ist. Ich entwickle Code aus einem Logikplan heraus.

Eigentlich hätte man das mit Deiner Uhr auch machen können und die Tage einfach nur durchrechnen können.
Sowas hab ich auch mal gemacht.
z.B. hier nur für Tage an einem beliebigen Datum https://forum.arduino.cc/t/abstand-zwischen-zwei-tagen-berechnen-nach-dem-19-01-2038/1023692/20 ( Bitte das Post #23 dann beachten)
Oder z.B. hier: https://forum.arduino.cc/t/datediff-differenz-zwischen-zwei-daten/962095/62
Du siehst also, ich versuch immer erst um die Ecke zu denken :slight_smile:

1 Like

Das kann sehr gut sein. Beim Auslesen der Fernbedienung wurde der Wert im Serial Monitor immer doppelt geschrieben. Erst bei einem Programm mit einem Delay von 200 bekam ich die einzelnen Werte