Wordclock mit ESP8266 und WS2812B - unterschiedliches Verhalten nach Flashen

Hi zusammen,

ich habe hier seit ca. 7 Jahren eine WordClock problemlos laufen, Programmcode habe ich immer mal wieder optimiert, die letzte laufende war von 2022.
Jetzt hatte ich wieder eine Änderung, habe dafür eine neuere Arduino IDE installiert und ein paar Bibliotheken aktualisiert. Wieder bin-file erstellt und über OTA (ESP8266HTTPUpdateServer) geflasht und natürlich :stuck_out_tongue: läuft die Uhr nicht mehr richtig (LEDs gehen alle 2 Sekunden nacheinander aus; fastLED library).
Noch spannender: nehme ich jetzt wieder das alte bin-File von 2022, bleibt der Fehler.

Daher, bevor wir in die Details gehen: wie kann es sein, dass ein Fehler bleibt, wenn ich ein altes bin-File wieder draufflashe? Kann das ein Softwarefehler sein?

Ich habe einen zweiten, baugleichen Arduino (nodemcu ESP8266) hier (direkt an USB, keine separate Spannungsversorgung, mit nur 5 LEDs statt ca 140), bei dem trat der Fehler auch auf, allerdings konnte ich ihn identifizieren und beheben. blankscreen habe ich durch FastLED.clear ersetzt.

//void blankscreen(bool commit) {
//  for (int led = 0; led < NUM_LEDS; led++) {
//    leds[led] = CRGB(0, 0, 0);
//    if (commit) {
//      FastLED.show();
//    }
//  }
//}

Flashe ich dasselbe aber auf die Uhr, tritt der Fehler weiter auf - siehe oben.

Bin gerade etwas ratlos bzgl. strategischer Fehlersuche, vielleicht habt ihr eine Idee. :slight_smile:

Viele Grüße

Zeige den Fehler. Ich vermute, dass sich der „Kern“ (Board-Unterstützung) geändert hat. Vielleicht kannst du das wieder in den funktionierenden Kern verschieben?

Ich habs mir jetzt nochmal angeschaut und es ist wirklich keinerlei Systematik drin. Manchmal blinkt es nach einer Kompilierung, manchmal dann mit dem selben File nicht. Unabhängig von der Boardversion in der Boardverwaltung (alte/neue Version und mehrere dazwischen probiert) und unabhängig davon ob per USB oder OTA geflasht.

Interessant ist, dass die Fehlermeldung für fehlende Wlan-Verbindung am Anfang ("kein Funk") nur kommt, wenn die Anzeige dann blinkt. Bleiben die Leds am Anfang weiß, so tritt kein Blinken auf.

Fehler sieht so aus, wiederholt sich alle 2 s:
VID_20250108_212414.mp4
Alle 2 Sekunden, da ich definiert habe, dass die Leds nur alle 2 Sekunden aktualisiert werden.

#define FASTLED_ESP8266_RAW_PIN_ORDER
#include <FastLED.h>
#include <ESP8266WiFi.h>
#include <time.h>      // time() ctime()
#include <sys/time.h>  // struct timeval
#include "wordclock_words.c"
#include "wordclock_eeprom.h"
#include <Dusk2Dawn.h>
#include <WiFiClient.h>
#include <ESP8266WebServer.h>
#include <ESP8266mDNS.h>
#include <ESP8266HTTPUpdateServer.h>

#define NUM_LEDS 140
#define NUM_LINES 11
#define DATA_PIN 2
#define SSID "hasi"
#define KEY "mausi"

#define TZ 1      // (utc+) TZ in hours
#define DST_MN 0  // use 60mn for summer time in some countries
#define TZ_SEC ((TZ)*3600)
#define DST_SEC ((DST_MN)*60)

CRGB leds[NUM_LEDS];
CRGB color_line[NUM_LINES];
CRGB color_line1[NUM_LINES];
CRGB color_line2[NUM_LINES];
CRGB color_ambient;

void word2stripe(const int[], int, CRGB color = CRGB::Orange);
void blankscreen(bool commit = false);
const char* host = "esp8266-webupdate";
bool beforeSunrise = false;
bool afterSunset = false;
bool Ambient_on = false;

int laSunrise = 0;
int laSunset = 0;

uint32_t millis_start = 0;
uint32_t millis_delay = 0;
uint8_t hourx;
uint8_t minx;
uint8_t sekx;
uint8_t wdayx;
uint8_t mdayx;
uint8_t monx;
uint8_t yearx;
int timeinmin;

timeval tv;
time_t now;

ESP8266WebServer httpServer(80);
ESP8266HTTPUpdateServer httpUpdater;

void setup() {
  FastLED.addLeds<WS2812B, DATA_PIN, GRB>(leds, NUM_LEDS);
  blankscreen(true);

  // config time
  configTime(TZ_SEC, DST_SEC, "pool.ntp.org");

  //connect to WiFi
  WiFi.mode(WIFI_STA);
  WiFi.hostname("WordClock");
  WiFi.begin(SSID, KEY);
  while (WiFi.status() != WL_CONNECTED) {  // show "KEIN FUNK"
    word2stripe(word_KEIN, sizeof(word_KEIN) / sizeof(int), CRGB::Red);
    word2stripe(word_FUNK, sizeof(word_FUNK) / sizeof(int), CRGB::Red);
    FastLED.show();
    delay(5000);
  }

  //Farben definieren
  color_line1[1] = CRGB(102, 255, 255);  //kalt
  color_line1[2] = CRGB(122, 255, 214);
  color_line1[3] = CRGB(143, 255, 173);
  color_line1[4] = CRGB(163, 255, 133);
  color_line1[5] = CRGB(184, 255, 92);
  color_line1[6] = CRGB(204, 255, 51);
  color_line1[7] = CRGB(153, 217, 38);
  color_line1[8] = CRGB(102, 179, 26);
  color_line1[9] = CRGB(51, 140, 13);
  color_line1[10] = CRGB(0, 102, 0);
  color_line2[1] = CRGB(102, 255, 255);  //warm
  color_line2[2] = CRGB(122, 255, 214);
  color_line2[3] = CRGB(143, 255, 173);
  color_line2[4] = CRGB(163, 255, 133);
  color_line2[5] = CRGB(184, 255, 92);
  color_line2[6] = CRGB(204, 255, 51);
  color_line2[7] = CRGB(217, 204, 38);
  color_line2[8] = CRGB(230, 153, 26);
  color_line2[9] = CRGB(242, 101, 13);
  color_line2[10] = CRGB(255, 50, 0);

  gettimeofday(&tv, nullptr);  //erstes mal Zeit holen
  now = time(nullptr);

  MDNS.begin(host);
  httpUpdater.setup(&httpServer);
  httpServer.begin();
  MDNS.addService("http", "tcp", 80);
}

void loop() {
  httpServer.handleClient();                    //Client für Updateprozedur
  if (millis() - millis_delay > (2000 - 709)) {  //Anti-delay-Abfrage, Programmlaufzeit berücksichtigt, sonst wird Uhr ungenau
    if (millis() - millis_start > 900000) {     //15 min vergangen, Zeit neu holen
      gettimeofday(&tv, nullptr);
      now = time(nullptr);
      millis_start = millis();  //Zeit in ms seit Arduinostart
    } else {
      now = now + 2;  // 2 s draufaddieren
    }
    blankscreen(true);  // all pixels to black, "Aufräumen" der LEDs, sonst würden iwann alle leuchten
    Ambient_on = false;
    hourx = localtime(&now)->tm_hour;
    minx = localtime(&now)->tm_min;
    sekx = localtime(&now)->tm_sec;
    wdayx = localtime(&now)->tm_wday;
    mdayx = localtime(&now)->tm_mday;
    monx = localtime(&now)->tm_mon;
    timeinmin = hourx * 60 + minx;
    if (LEDs_on()) {
      timeToStripe(hourx, minx, sekx);  // calculate time and fill leds array
      FastLED.setBrightness(brightness());
      FastLED.setDither(0);
      FastLED.show();
      FastLED.delay(5);
    }
    if (millis() < 600000) {
      printdiagnosis();
    }
    millis_delay = millis();
  }
}


// push word to leds array
void word2stripe(const int word[], int len, CRGB color) {
  for (int letter = 0; letter < len; letter++) {
    leds[word[letter]] = color;
  }
}

// blank screen (to specific color if given, and put it on the matrix if set)
void blankscreen(bool commit) {
  for (int led = 0; led < NUM_LEDS; led++) {
    leds[led] = CRGB(0, 0, 0);
    if (commit) {
      FastLED.show();
    }
  }
}


//sollen LEDs leuchten?
boolean LEDs_on() {
  if (((hourx == 6) && (wdayx > 0 && wdayx < 6)) ||                 // früh unter der Woche, 0= So, 1 = Mo, 5 = Fr, 6 = Sa,  -  6-7 Uhr
      ((hourx > 15 && hourx < 23) && (wdayx > 0 && wdayx < 6)) ||   // Mo-Fr abend 16-23 Uhr
      ((hourx > 6 && hourx < 23) && (wdayx == 6 || wdayx == 0)) ||  //tagsüber Samstag, Sonntag 7-23 Uhr
      //(hourx > 6 && hourx < 23) ||                                                               //nur während Homeoffice
      (((mdayx > 19 && monx == 11) || (mdayx < 7 && monx == 0)) && (hourx > 6 && hourx < 23))) {  //Weihnachten bis heilig drei Könige
    return true;
  } else {
    return false;
  }
}


//Mappingfunktion - Dreisatz
float mapfloat(float x, float in_min, float in_max, float out_min, float out_max) {
  return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
}


//Helligkeit LEDs festlegen
byte brightness() {
  int high = 200;
  int low = 10;
  int atsun = 60;                     //Helligkeit bei Sonnenauf/untergang
  int set_startdim = laSunset - 120;  // 3h vor Sonnenuntergang
  int set_enddim = laSunset + 180;
  int rise_startdim = laSunrise - 60;
  int rise_enddim = laSunrise + 180;
  if (timeinmin <= set_startdim && timeinmin >= rise_enddim) {  //tagsüber
    return high;
  }
  if (timeinmin >= set_enddim || timeinmin <= rise_startdim) {  //nachts
    return low;
  }
  if (timeinmin > set_startdim && timeinmin < set_enddim) {  // Zeitraum für Dimmen abends
    if (timeinmin < laSunset) {                              // Dimmen vor Sonnenuntergang
      return mapfloat(timeinmin, laSunset, set_startdim, atsun, high);
    } else {  // Dimmen nach Sonnenuntergang
      return mapfloat(timeinmin, set_enddim, laSunset, low, atsun);
    }
  }
  if (timeinmin < rise_enddim && timeinmin > rise_startdim) {  // Zeitraum für Dimmen früh
    if (timeinmin > laSunrise) {                               // Dimmen nach Sonnenaufgang
      return mapfloat(timeinmin, laSunrise, rise_enddim, atsun, high);
    } else {  // Dimmen vor Sonnenaufgang
      return mapfloat(timeinmin, rise_startdim, laSunrise, low, atsun);
    }
  }
  return atsun;  //Notfallwert, falls keine if-Bedingung greift
}


//calculate if sunset/rise
void isSun() {
 ..
}


// push the time (words) to leds array
void timeToStripe(uint8_t hours, uint8_t mins, uint8_t secs) {

  //Farbe der Buchstaben korrekt auswaehlen
  isSun();
  if (afterSunset) {
    for (int line = 0; line < NUM_LINES; line++) {
      color_line[line] = color_line2[line];
    }
  } else {
    for (int line = 0; line < NUM_LINES; line++) {
      color_line[line] = color_line1[line];
    }
  }

  // show "ES IST"
  word2stripe(word_ES, sizeof(word_ES) / sizeof(int), color_line[1]);
  word2stripe(word_IST, sizeof(word_IST) / sizeof(int), color_line[1]);

  //Ambientebeleuchtung
  if (beforeSunrise) {
    color_ambient = CRGB(255, 255, 255);
    Ambient_on = true;
  } else if (beforeSunrise == false && afterSunset == false) {
    color_ambient = CRGB(0, 0, 0);
  } else if (afterSunset) {
    color_ambient = color_line2[10];
    Ambient_on = true;
  }
  word2stripe(ambient_OBEN, sizeof(ambient_OBEN) / sizeof(int), color_ambient);
  word2stripe(ambient_LINKS, sizeof(ambient_LINKS) / sizeof(int), color_ambient);
  word2stripe(ambient_RECHTS, sizeof(ambient_RECHTS) / sizeof(int), color_ambient);
  word2stripe(ambient_UNTEN, sizeof(ambient_UNTEN) / sizeof(int), color_ambient);

  //Sekundenzeiger
  int secs2 = secs / 2.5;
  if (Ambient_on) {
    leds[A[secs2]] = CRGB(0, 0, 0);
    if (secs2 > 0 && secs2 < 5 || secs2 > 6 && secs2 < 11 || secs2 > 12 && secs2 < 17 || secs2 > 18 && secs2 < 24) {
      leds[A[secs2 - 1]] = color_ambient / 2.9;
      leds[A[secs2 + 1]] = color_ambient / 2.9;
    }
    if (secs2 == 0 || secs2 == 6 || secs2 == 12 || secs2 == 18) {
      leds[A[secs2 + 1]] = color_ambient / 2.9;
    }
    if (secs2 == 5 || secs2 == 11 || secs2 == 17 || secs2 == 24) {
      leds[A[secs2 - 1]] = color_ambient / 2.9;
    }
  } else {
    leds[A[secs2]] = CRGB(255, 255, 255);
  }

  // restliche Uhrzeit
  if (mins >= 5 && mins < 10) {
    ..
  }

  int singleMinutes = mins % 5;
  switch (singleMinutes) {
    case 1:
      word2stripe(min_ONE, sizeof(min_ONE) / sizeof(int), color_line[1]);
      break;
    case 2:
      word2stripe(min_ONE, sizeof(min_ONE) / sizeof(int), color_line[1]);
      word2stripe(min_TWO, sizeof(min_TWO) / sizeof(int), color_line[1]);
      break;
    case 3:
      word2stripe(min_ONE, sizeof(min_ONE) / sizeof(int), color_line[1]);
      word2stripe(min_TWO, sizeof(min_TWO) / sizeof(int), color_line[1]);
      word2stripe(min_THREE, sizeof(min_THREE) / sizeof(int), color_line[10]);
      break;
    case 4:
      word2stripe(min_ONE, sizeof(min_ONE) / sizeof(int), color_line[1]);
      word2stripe(min_TWO, sizeof(min_TWO) / sizeof(int), color_line[1]);
      word2stripe(min_THREE, sizeof(min_THREE) / sizeof(int), color_line[10]);
      word2stripe(min_FOUR, sizeof(min_FOUR) / sizeof(int), color_line[10]);
      break;
  }

  if (mins >= 15) {
    hours++;
  }

  if (hours >= 12) {
    hours -= 12;
  }

  switch (hours) {
    case 0:
      word2stripe(word_ZWOELF, sizeof(word_ZWOELF) / sizeof(int), color_line[9]);
      break;
    case 1:
      if (mins > 4) {
        word2stripe(word_EINS, sizeof(word_EINS) / sizeof(int), color_line[6]);
      } else {
        word2stripe(word_EIN, sizeof(word_EIN) / sizeof(int), color_line[6]);
      }
      break;
   ..
  }
  // show "UHR" if full hour
  if (mins < 5) {
    word2stripe(word_UHR, sizeof(word_UHR) / sizeof(int), color_line[10]);
  }
}


void printdiagnosis() {
 ..
}

So sieht der ganze, an unrelevanten Stellen gekürzte Text dazu aus. Ich erwarte jetzt aber nicht, dass den jemand von euch gleich durchgeht.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.