Hallo,
bei dem miesen Wetter hatte ich heute etwas Zeit mich um die Uhr zu kümmern.
Habe es geschafft, die Farbabweichung mal festzuhalten, damit ihr eine Vorstellung habt.
Die Nutzung von Delay() habe ich umgangen, das Problem besteht weiterhin.
#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>
#define NUM_LEDS 140
#define NUM_LINES 11
#define DATA_PIN 2
#define SSID "..."
#define KEY "..."
#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);
bool beforeSunrise = false;
bool afterSunset = false;
bool Ambient_on = false;
int laSunrise = 0;
int laSunset = 0;
byte brightness = 255;
timeval tv;
time_t now;
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(500);
}
blankscreen(true);
//Farben definieren
color_line1[1] = CRGB (102, 255, 255); //kalt
...
color_line1[10] = CRGB (0, 102, 0);
color_line2[1] = CRGB (102, 255, 255); //warm
...
color_line2[10] = CRGB (255, 50, 0);
gettimeofday(&tv, nullptr);
now = time(nullptr);
}
uint32_t millis_start = 0;
uint32_t millis_delay = 0;
uint8_t hourx;
uint8_t minx;
uint8_t wdayx;
int timeinmin;
void loop() {
if (millis() - millis_delay > (10000 - 677)) { //Anti-delay-Abfrage, Programmlaufzeit berücksichtigt, sonst wird Uhr ungenau
if (millis() - millis_start > 18000000) { //300 min vergangen, Zeit neu holen
gettimeofday(&tv, nullptr);
now = time(nullptr);
millis_start = millis(); //Zeit in ms seit Arduinostart
} else {
now = now + 10; // 10 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;
wdayx = localtime(&now)->tm_wday;
timeinmin = hourx * 60 + minx;
setbrightnes();
if (LEDs_on()) {
timeToStripe(hourx, minx); // calculate time and fill leds array
FastLED.setBrightness(brightness);
FastLED.show();
}
//printdiagnosis(); //optional, falls Fehlerbehebung
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
((hourx > 14 && hourx < 23) &&
(wdayx > 0 && wdayx < 6)) || // Mo-Fr abend
((hourx > 6 && hourx < 23) &&
(wdayx == 6 || wdayx == 0))) { //tagsüber Samstag, Sonntag
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
void setbrightnes() {
int high = 255;
int low = 7;
int atsun = 100; //Helligkeit bei Sonnenauf/untergang
int set_startdim = laSunset - 120; // 2h vor Sonnenuntergang
int set_enddim = laSunset + 240;
int rise_startdim = laSunrise - 60;
int rise_enddim = laSunrise + 180;
if (timeinmin < set_startdim && timeinmin > rise_enddim) { //tagsüber
brightness = high;
}
if (timeinmin > set_enddim || timeinmin < rise_startdim) { //nachts
brightness = low;
}
if (timeinmin > set_startdim && timeinmin < set_enddim) { // Zeitraum für Dimmen abends
if (timeinmin < laSunset) { // Dimmen vor Sonnenuntergang
brightness = mapfloat(timeinmin, laSunset, set_startdim, atsun, high );
} else { // Dimmen nach Sonnenuntergang
brightness = mapfloat(timeinmin, set_enddim, laSunset, low, atsun );
}
}
if (timeinmin < rise_enddim && timeinmin > rise_startdim) { // Zeitraum für Dimmen früh
if (timeinmin > laSunset) { // Dimmen nach Sonnenaufgang
brightness = mapfloat(timeinmin, laSunrise, rise_enddim, atsun, high );
} else { // Dimmen vor Sonnenaufgang
brightness = mapfloat(timeinmin, rise_startdim, laSunrise, low, atsun );
}
}
}
//calculate if its sunset/rise
void isSun() {
Dusk2Dawn datenschutz_ort(45, 16, 0);
laSunrise = datenschutz_ort.sunrise(2018, localtime(&now)->tm_mon, localtime(&now)->tm_mday, true);
laSunset = datenschutz_ort.sunset(2018, localtime(&now)->tm_mon, localtime(&now)->tm_mday, true);
laSunrise = laSunrise + 100; // notwendige Korrektur - keine Ahnung weshalb
if (laSunrise + 120 > timeinmin) {
beforeSunrise = true;
} else {
beforeSunrise = false;
}
if (laSunset - 60 < timeinmin) {
afterSunset = true;
} else {
afterSunset = false;
}
}
// push the time (words) to leds array
void timeToStripe(uint8_t hours, uint8_t mins) {
//Farbe der Buchstaben korrekt auswählen
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);
...
if (mins >= 5 && mins < 10) {
word2stripe(word_FUENF1, sizeof(word_FUENF1) / sizeof(int), color_line[1]);
word2stripe(word_NACH, sizeof(word_NACH) / sizeof(int), color_line[4]);
} else if (mins >= 10 && mins < 15) {
...
int singleMinutes = mins % 5;
switch (singleMinutes) {
case 1:
word2stripe(min_ONE, sizeof(min_ONE) / sizeof(int), color_line[1]);
break;
...
}
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;
...
}
}
// blank screen (to specific color if given, and put it on the matrix if set)
void printdiagnosis() {
...
}
Der Code ist an einigen Stellen etwas gekürzt, um die Übersichtlichkeit zu wahren. Die Struktur ist trotz der Kürzungen immer erkennbar. Falls ihr doch den kompletten Code mit dem ganzen unwichtigen Firlefanz außenrum braucht, schreibt einfach nochmal kurz.