diff --git a/60LED_WS2812B_NTP_Clock.ino b/60LED_WS2812B_NTP_Clock.ino index a94153b..bd85364 100644 --- a/60LED_WS2812B_NTP_Clock.ino +++ b/60LED_WS2812B_NTP_Clock.ino @@ -42,13 +42,24 @@ #define LDR_PIN A6 #define DATA_PIN 17 #endif -#define NUM_LEDS 60 +/* useful preselection +* NO following hour +* NO three block hour marking +* quarter hour marking +*/ +#define NUM_LEDS 60 //24 #define SERIAL_BAUD 115200 #define RGBW -volatile bool singleSecond = true; //show seconds +const bool clockwiseRing = false; +volatile bool singleSecond = false; //show seconds volatile bool allDotsOn = true; //lighten up all leds +#if NUM_LEDS == 60 volatile bool followingHour = true; //move hour like an analog one +#endif +#if NUM_LEDS == 24 +volatile bool followingHour = false; //move hour like an analog one +#endif volatile int hourOffset = 0; void bootAnimCallback(); @@ -190,7 +201,7 @@ const char wifiInitialApPassword[] = "12345678"; // -- Maximal length the input-range attributes can have. #define COLOR_ATTR_LENGTH 60 // -- Configuration specific key. The value should be modified if config structure was changed. -#define CONFIG_VERSION "V1.1.4" +#define CONFIG_VERSION "V1.1.5" const char CUSTOMHTML_SCRIPT_INNER[] PROGMEM = "\n\ function colorCh(id)\n\ @@ -300,9 +311,19 @@ IotWebConfParameterGroup timeGroup = IotWebConfParameterGroup("Time", "Time sett IotWebConfTextParameter ntpServerParam = IotWebConfTextParameter("NTP Server", "ntpServer", ntpServerParamValue, STRING_LEN, "pool.ntp.org"); IotWebConfParameterGroup ledGroup = IotWebConfParameterGroup("LED", "LED settings"); IotWebConfNumberParameter maxBrightnessParam = IotWebConfNumberParameter("Max BRIGHTNESS", "max brightness", maxBrightnessParamValue, NUMBER_LEN, "200", "20..254", "min='20' max='254' step='1'"); +#if NUM_LEDS == 60 IotWebConfCheckboxParameter singleSecondParam = IotWebConfCheckboxParameter("Show Seconds", "singleSecond", singleSecondParamValue, STRING_LEN, true); +#endif +#if NUM_LEDS == 24 +IotWebConfCheckboxParameter singleSecondParam = IotWebConfCheckboxParameter("Show Seconds", "singleSecond", singleSecondParamValue, STRING_LEN, false); +#endif IotWebConfCheckboxParameter allDotsOnParam = IotWebConfCheckboxParameter("all Dots lighten on", "allDotsOn", allDotsOnParamValue, STRING_LEN, true); +#if NUM_LEDS == 60 IotWebConfCheckboxParameter followingHourParam = IotWebConfCheckboxParameter("following Hour", "followingHour", followingHourParamValue, STRING_LEN, true); +#endif +#if NUM_LEDS == 24 +IotWebConfCheckboxParameter followingHourParam = IotWebConfCheckboxParameter("following Hour", "followingHour", followingHourParamValue, STRING_LEN, false); +#endif ColorWithValueParameter hourColorParam = ColorWithValueParameter("Stundenfarbe", "hourColorParam", hourColorParamValue, COLOR_ATTR_LENGTH, "#FFD700"); ColorWithValueParameter minuteColorParam = ColorWithValueParameter("Minutenfarbe", "minuteColorParam", minuteColorParamValue, COLOR_ATTR_LENGTH, "#800000"); ColorWithValueParameter secondsColorParam = ColorWithValueParameter("Sekundenfarbe", "secondsColorParam", secondsColorParamValue, COLOR_ATTR_LENGTH, "#000000"); @@ -433,7 +454,9 @@ void iotWebConfConfigSaved() //Serial.println(singleSecondParam.isChecked() ? "true" : "false"); allDotsOn = allDotsOnParam.isChecked() ? true : false; //Serial.println(allDotsOnParam.isChecked() ? "true" : "false"); +#if NUM_LEDS == 60 followingHour = followingHourParam.isChecked() ? true : false; +#endif //Serial.println(followingHourParam.isChecked() ? "true" : "false"); transformHtmltoStrip(&highnoonColor, (char*)&highnoonColorParamValue); @@ -452,7 +475,9 @@ void iotWebConf_Setup() { ledGroup.addItem(&maxBrightnessParam); ledGroup.addItem(&singleSecondParam); ledGroup.addItem(&allDotsOnParam); +#if NUM_LEDS == 60 ledGroup.addItem(&followingHourParam); +#endif ledGroup.addItem(&hourColorParam); ledGroup.addItem(&minuteColorParam); ledGroup.addItem(&secondsColorParam); @@ -507,11 +532,18 @@ void syncNTP() { #endif Serial.println(printLocalTime()); if (NTPreachable) { - //inverted logic - remaining time - currentSec = 60 - timeinfo.tm_sec; - currentMin = 60 - timeinfo.tm_min; - currentHour = 12 - MOD(timeinfo.tm_hour, 12); - Serial.println("NTP mapped: " + String(currentHour) + ":" + String(currentMin) + ":" + String(currentSec)); + if (clockwiseRing) { + currentSec = timeinfo.tm_sec; + currentMin = timeinfo.tm_min; + currentHour = MOD(timeinfo.tm_hour, 12); + } + else { + //inverted logic - remaining time + currentSec = 60 - timeinfo.tm_sec; + currentMin = 60 - timeinfo.tm_min; + currentHour = 12 - MOD(timeinfo.tm_hour, 12); + } + Serial.println("NTP mapped: " + String(int(currentHour * NUM_LEDS / 12)) + ":" + String(int(currentMin * NUM_LEDS / 60)) + ":" + String(int(currentSec * NUM_LEDS / 60))); bootAnim.disable(); ledRefresh.enable(); clockTick.enable(); @@ -571,24 +603,33 @@ void loop() void ledRefreshCallback() { temp = allDotsOn ? backlightColor : black; strip.ClearTo(temp); - //1 dot hour marking for (int dot = 0; dot < NUM_LEDS; dot++) { +#if NUM_LEDS == 60 + //1 dot hour marking if (MOD(dot, 5) == 0) { strip.SetPixelColor(dot, hourMarkingColor); } +#endif +#if NUM_LEDS == 24 + //1 dot quarter marking + if (MOD(dot, 6) == 0) { + strip.SetPixelColor(dot, hourMarkingColor); + } +#endif } +#if NUM_LEDS == 60 //3 dots hour strip.SetPixelColor(MOD((currentHour * 5 - 1 + hourOffset), NUM_LEDS), hourColor); strip.SetPixelColor(MOD((currentHour * 5 + 0 + hourOffset), NUM_LEDS), hourColor); strip.SetPixelColor(MOD((currentHour * 5 + 1 + hourOffset), NUM_LEDS), hourColor); - +#endif strip.SetPixelColor(0, highnoonColor); //define high noon if (singleSecond) { - strip.SetPixelColor(MOD((currentSec + 0), NUM_LEDS), (secondsColor)); - //strip.SetPixelColor(MOD((currentSec + 0), NUM_LEDS), (allDotsOn ? black : secondsColor)); + strip.SetPixelColor(MOD(int(currentSec * NUM_LEDS / 60 + 0), NUM_LEDS), secondsColor); } - strip.SetPixelColor(MOD((currentMin + 0), NUM_LEDS), minuteColor); + strip.SetPixelColor(MOD(int(currentHour * NUM_LEDS / 12 + 0), NUM_LEDS) , hourColor); + strip.SetPixelColor(MOD(int(currentMin * NUM_LEDS / 60 + 0), NUM_LEDS), minuteColor); strip.Show(); } @@ -597,37 +638,71 @@ void clockTickCallback() { #ifdef LDR_PIN ldrValue = (ldrValue + analogRead(LDR_PIN)); #endif - if (currentSec < 0) { - currentSec = 59; - currentMin--; - if (!NTPreachable) { - syncNTP(); - } - if (currentMin < 0) { - currentMin = 59; - currentHour--; - if (currentHour < 0) { - currentHour = 11; + if (clockwiseRing) { + if (currentSec >= 60) { + currentSec = 0; + currentMin++; + if (!NTPreachable) { syncNTP(); } + if (currentMin >= 60) { + currentMin = 0; + currentHour++; + if (currentHour >= 12) { + currentHour = 0; + syncNTP(); + } + } + if (followingHour) { + hourOffset = int (currentMin * NUM_LEDS / 60 / 12); //negative value + //Serial.println("hourOffset: " + String(hourOffset)); + } + //Serial.println(String(interruptCounter) + " | Ring Index: " + String(currentHour / (12 / NUM_LEDS)) + ":" + String(currentMin / (60 / NUM_LEDS)) + ":" + String(currentSec / (60 / NUM_LEDS))); } - if (followingHour) { - hourOffset = 0 - ((60 - currentMin) / 12); //negative value - //Serial.println("hourOffset: " + String(hourOffset)); - } - //Serial.println(String(interruptCounter) + " | Ring Index: " + String(currentHour * 5) + ":" + String(currentMin) + ":" + String(currentSec)); + currentSec++; + + } + else { + if (currentSec < 0) { + currentSec = 59; + currentMin--; + if (!NTPreachable) { + syncNTP(); + } + if (currentMin < 0) { + currentMin = 59; + currentHour--; + if (currentHour < 0) { + currentHour = 11; + syncNTP(); + } + } + if (followingHour) { + hourOffset = 0 + int((60 - currentMin * NUM_LEDS / 60) / 12); //negative value + //Serial.println("hourOffset: " + String(hourOffset)); + } + //Serial.println(String(interruptCounter) + " | Ring Index: " + String(currentHour / (12 / NUM_LEDS)) + ":" + String(currentMin / (60 / NUM_LEDS)) + ":" + String(currentSec / (60 / NUM_LEDS))); + } + currentSec--; } - currentSec--; } void bootAnimCallback() { strip.ClearTo(black); int tail = -1; - currentSec--; - if (currentSec < 0) { - currentSec = NUM_LEDS-1; - tail = 1; + if (clockwiseRing) { + currentSec++; + if (currentSec >= NUM_LEDS) { + currentSec = 0; } + } + else { + currentSec--; + tail = 1; + if (currentSec < 0) { + currentSec = NUM_LEDS - 1; + } + } if (iotWebConf.getState() == IOTWEBCONF_STATE_ONLINE && !NTPreachable) { strip.ClearTo(white);