/** * NeoClock * * Clock using 60 WS2812B/Neopixel LEDs and DS3231 RTC * * Libraries needed: * * Adafruit NeoPixel (Library Manager) - Phil Burgess / Paint Your Dragon for Adafruit Industries - LGPL3 * * * * Arduino Timezone Library (https://github.com/JChristensen/Timezone) - Jack Christensen - CC-BY-SA * * Time Library (https://github.com/PaulStoffregen/Time) - Paul Stoffregen, Michael Margolis - LGPL2.1 */ #include #ifdef __AVR__ #include #endif #if defined(ESP8266) #include #else #include #endif /* for software wire use below #include // must be included here so that Arduino library object file references work #include SoftwareWire myWire(SDA, SCL); RtcDS3231 Rtc(myWire); for software wire use above */ /* for normal hardware wire use below */ #include // must be included here so that Arduino library object file references work #include // Makuna library RtcDS3231 Rtc(Wire); /* for normal hardware wire use above */ #include //http://www.arduino.cc/playground/Code/Time #include //https://github.com/JChristensen/Timezone #include //Central European Time (Frankfurt, Paris) TimeChangeRule CEST = {"CEST", Last, Sun, Mar, 2, 120}; //Central European Summer Time TimeChangeRule CET = {"CET ", Last, Sun, Oct, 3, 60}; //Central European Standard Time Timezone CE(CEST, CET); TimeChangeRule *tcr; //pointer to the time change rule, use to get the TZ abbrev time_t utc; #define PIN 5 unsigned long lastMillis = millis(); byte dimmer = 0x88; byte hmark = 0; byte ohour=0; byte ominute=0; byte osecond=0; boolean fader=true; Adafruit_NeoPixel strip = Adafruit_NeoPixel(60, PIN, NEO_GRB + NEO_KHZ800); void setup() { //Use below code to set time and date once from code //it will run at every reset and you will lose the time on the RTC //format is (sec, min, hr, day of week, day of month, month, year) // setRTCTime(0, 10, 14, 2, 21, 9, 21); Serial.begin(57600); strip.begin(); strip.setBrightness(50); // Some example procedures showing how to display to the pixels: colorWipe(strip.Color(255, 0, 0), 50); // Red colorWipe(strip.Color(0, 255, 0), 50); // Green colorWipe(strip.Color(0, 0, 255), 50); // Blue colorWipe(strip.Color(0, 0, 0, 255), 50); // White RGBW // Send a theater pixel chase in... //theaterChase(strip.Color(127, 127, 127), 50); // White theaterChase(strip.Color(127, 0, 0), 50); // Red //theaterChase(strip.Color(0, 0, 127), 50); // Blue //rainbow(20); //rainbowCycle(20); //theaterChaseRainbow(50); strip.clear(); strip.show(); // Initialize all pixels to 'off' Rtc.Begin(); Rtc.Enable32kHzPin(false); Rtc.SetSquareWavePin(DS3231SquareWavePin_ModeNone); if (!Rtc.GetIsRunning()) { Serial.println("Rtc was not actively running, starting now"); Rtc.SetIsRunning(true); } if (!Rtc.IsDateTimeValid()) { // Common Cuases: // 1) the battery on the device is low or even missing and the power line was disconnected Serial.println("Rtc lost confidence in the DateTime!"); } byte eechk = EEPROM.read(0); if(eechk == 0xAA) { //Assume this is our config and not a fresh chip dimmer = EEPROM.read(1); hmark = EEPROM.read(2); fader = EEPROM.read(3); } timeSync(); } void calcTime(void) { utc = now(); CE.toLocal(utc, &tcr); ohour = hour(utc); ominute = minute(utc); if(osecond != second(utc)) { osecond = second(utc); lastMillis = millis(); if(ominute == 0 && osecond == 0) { //Every hour timeSync(); } } } void addPixelColor(byte pixel, byte color, byte brightness) { color *= 8; uint32_t acolor = brightness; acolor <<= color; uint32_t ocolor = strip.getPixelColor(pixel); ocolor |= acolor; strip.setPixelColor(pixel, ocolor); } void drawClock(byte h, byte m, byte s) { strip.clear(); addPixelColor(m, 1, dimmer); if(hmark > 0) { for(byte i = 0; i<12; i++) { addPixelColor((5*i), 2, hmark); } } h %= 12; h *= 5; h += (m/12); addPixelColor(h, 2, dimmer); // 0x RR GG BB if(fader) { byte dim_s1 = dimmer; byte dim_s2 = 0; byte px_s2 = s+1; if(px_s2 >= 60) px_s2 = 0; unsigned long curMillis = millis()-lastMillis; if(curMillis < 250) { dim_s2 = 0; dim_s1 = dimmer; }else{ dim_s2 = map(curMillis, 250, 1000, 0, dimmer); dim_s1 = dimmer - map(curMillis, 250, 1000, 0, dimmer); } // Add blue low intensity dots for 12(0),3, 6 and 9 O'çlock to verify where the clock is positioned.. addPixelColor(15, 128, 10); addPixelColor(30, 128, 10); addPixelColor(45, 128, 10); addPixelColor(0, 128, 40); addPixelColor(s, 0, dim_s1); addPixelColor(px_s2, 0, dim_s2); }else{ addPixelColor(s, 0, dimmer); } // add a background color // setBrightness(Serial.parseInt()); // uint16_t j; // for(j=0; j<60; j++) { // 1 cycles of colors on wheel // strip.setPixelColor(j, Wheel(((j * 256 / strip.numPixels()) + j) & 255)); // } strip.show(); } byte rounds = 0; void loop() { calcTime(); if(rounds++ > 100) { Serial.print(ohour); Serial.print(":"); Serial.print(ominute); Serial.print(":"); Serial.print(osecond); Serial.println("(C)JG-2020"); rounds = 0; } //rainbow(21); if (osecond == 59){theaterChase(strip.Color(0, 0, 127), 40); }// Blue; } //if (ominute == 59 AND osecond == 59){theaterChase(strip.Color(0, 127, 0), 50); }// Green} //if (ohour == 11 AND ominute == 59 AND osecond == 59){theaterChase(strip.Color(127, 127, 0), 50); }// Green} else {drawClock(ohour,ominute,osecond);} delay(10); chkSer(); } void timeSync(void) { RtcDateTime dt = Rtc.GetDateTime(); setTime(dt.Hour(),dt.Minute(),dt.Second(),dt.Day(),dt.Month(),dt.Year()); Serial.print("Synced to: "); Serial.print(dt.Year()); Serial.print("-"); Serial.print(dt.Month()); Serial.print("-"); Serial.print(dt.Day()); Serial.print("-"); Serial.print(dt.Hour()); Serial.print("-"); Serial.print(dt.Minute()); Serial.print("-"); Serial.println(dt.Second()); } void timeSave(void) { utc = now(); RtcDateTime store = RtcDateTime(year(utc), month(utc), day(utc), hour(utc), minute(utc), second(utc)); Rtc.SetDateTime(store); Serial.print("Synced to: "); Serial.print(year(utc)); Serial.print("-"); Serial.print(month(utc)); Serial.print("-"); Serial.print(day(utc)); Serial.print("-"); Serial.print(hour(utc)); Serial.print("-"); Serial.print(minute(utc)); Serial.print("-"); Serial.println(second(utc)); } void setBrightness(byte brightness) { dimmer = brightness; } void chkSer(void) { unsigned int iy; byte im,id,iH,iM,iS; if(!Serial.available()) return; switch(Serial.read()) { case 'b': setBrightness(Serial.parseInt()); Serial.print(F("Brightness changed to: ")); Serial.println(dimmer); EEPROM.put(0, 0xAA); EEPROM.put(1, dimmer); break; case 't': iy = Serial.parseInt(); im = Serial.parseInt(); id = Serial.parseInt(); iH = Serial.parseInt(); iM = Serial.parseInt(); iS = Serial.parseInt(); setTime(iH,iM,iS,id,im,iy); Serial.println(F("System time changed")); break; case 'f': fader = false; EEPROM.put(0, 0xAA); EEPROM.put(3, 0); Serial.println(F("Fader off")); break; case 'F': fader = true; EEPROM.put(0, 0xAA); EEPROM.put(3, 1); Serial.println(F("Fader on")); break; case 'm': hmark = Serial.parseInt(); EEPROM.put(0, 0xAA); EEPROM.put(2, hmark); Serial.println(F("HMark changed")); break; case 's': timeSync(); Serial.println(F("Synced RTC to System")); break; case 'S': timeSave(); Serial.println(F("Synced System to RTC")); break; default: Serial.println('?'); } } // Fill the dots one after the other with a color void colorWipe(uint32_t c, uint8_t wait) { for(uint16_t i=0; i