BitBastelei #234 - WS2812B (Neopixel) Uhr
(132 MB) 00:38:13
2017-03-12 11:00 🛈Die WS2812B, auch bekannt als Neopixel, sind RGB-LEDs mit internem Steuer-IC, welche sich über einen einzelnen Datenpin kaskadieren und separat ansteuern lassen. Als in meinem Feed ein Angebot für ¼-Kreise mit 15 dieser LEDs durchtickerte war der Plan schnell klar: 4 ¼-Kreise á 15 LEDs macht 60 LEDs. Passend für eine Uhr. Mal schauen, ob es auch funktioniert.
Zur Zeithaltung kommt ein DS3231 zum Einsatz – ein I²C-Chip, welcher speziell für Uhren gedacht ist und genauer funktioniert als die internen Taktgeber der üblichen µCs.
Inhalt:
- 00:00 LED-Module & Aufbauplan
- 08:22 LED-Test mit Adafruit-Library
- 12:32 Warum RTC statt Systemtakt / millis()?
- 17:05 Blick auf die Software
- 34:13 Uhr in Aktion
Code:
/** * 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 * * Rtc by Makuna (Library Manager) - Michael C. Miller * * 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 <Adafruit_NeoPixel.h> #ifdef __AVR__ #include <avr/power.h> #endif #if defined(ESP8266) #include <pgmspace.h> #else #include <avr/pgmspace.h> #endif #include <SoftwareWire.h> // must be included here so that Arduino library object file references work #include <RtcDS3231.h> #include <Time.h> //http://www.arduino.cc/playground/Code/Time #include <Timezone.h> //https://github.com/JChristensen/Timezone #include <EEPROM.h> //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; SoftwareWire myWire(8, 9); RtcDS3231<SoftwareWire> Rtc(myWire); #define PIN 6 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() { Serial.begin(115200); strip.begin(); 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); } addPixelColor(s, 0, dim_s1); addPixelColor(px_s2, 0, dim_s2); }else{ addPixelColor(s, 0, dimmer); } strip.show(); } byte rounds = 0; void loop() { calcTime(); if(rounds++ > 100) { Serial.print(ohour); Serial.print(":"); Serial.print(ominute); Serial.print(":"); Serial.println(osecond); rounds = 0; } 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('?'); } }