UPDATE
Now using Network Time Protocol (NTP)
https://coeleveld.com/nodemcu-esp8266-esp-12e-v1-0-clock/
Bicycle rim Hero Xr-1 27 inch (700mm) 20H clincher, black.
5mm thick (depron) foam strip for padding.
DS3231 High Precision Real-Time Clock Module (replacing I2C identical DS1307)
SMD pixel RGB strip (30 LEDs per meter, WS2812, 5050 LED)
// Code collected and completed by Tobias Floery <tobias@floery.net> //SMD RGB pixel LED strip // FastSPI Library from http://code.google.com/p/fastspi/ #include <FastSPI_LED.h> // Adafruits RTClib from https://github.com/adafruit/RTClib #include <Wire.h> #include "RTClib.h" RTC_DS1307 RTC; // Sometimes chipsets wire in a backwards sort of way //struct CRGB { unsigned char b; unsigned char r; unsigned char g; }; //struct CRGB { unsigned char r; unsigned char g; unsigned char b; }; struct CRGB { unsigned char g; unsigned char r; unsigned char b; }; struct CRGB *leds; // Number of RGB Pixel for FastSPI #define NUM_LEDS 60 // Datapin for FastSPI #define PIN 11 // Datarate - valued 0 to 7. Choose a higher value if flickering occurs //#define RATE 0 #define FILTER_LEN 8 // Brightness level int level=15; // Brightness correction for Leds unsigned char bright[] = {0, 2, 4, 7, 11, 18, 30, 40, 50, 65, 80,96,125,160, 200, 255}; void setup() { Serial.begin(57600); // init RTClib Wire.begin(); RTC.begin(); // Following line sets the RTC to the date & time this sketch was compiled /* RTC.adjust(DateTime(__DATE__, __TIME__)); */ // Setup FastSPI Lib FastSPI_LED.setLeds(NUM_LEDS); FastSPI_LED.setChipset(CFastSPI_LED::SPI_WS2811); FastSPI_LED.setPin(PIN); //FastSPI_LED.setDataRate(RATE); FastSPI_LED.init(); FastSPI_LED.start(); leds = (struct CRGB*)FastSPI_LED.getRGBData(); // setup measurement for LDR digitalWrite(A0, HIGH); // set pullup on analog pin 0 pinMode(A1, OUTPUT); digitalWrite(A1, LOW); } unsigned int ldr=0; void doLDR() { unsigned int ldr_value = analogRead(0); //reads the LDR values //Adjust for LDR variations. //dark = 1023 //light = 0 //If your LDR for example reaches a max analogRead value of 350 instead of 1023 for 100% dark. //unsigned int ldr_adjusted=map(ldr_value,0,350,0,1023); unsigned int ldr_adjusted=map(ldr_value,0,700,0,1023); //set max limit (to avoid potential 'divide-by-zero's). if (ldr_adjusted >= 1023) ldr_adjusted = 1023; //ldr follows ldr_adjusted, but is averaged so that values only change gradually ldr = ((unsigned long)(FILTER_LEN-1)*ldr+ldr_adjusted)/FILTER_LEN; unsigned int light_level=0; //translate [0-1023] to [15-0] //light_level = (1024-ldr)>>6; light_level=map(ldr,0,1023,15,0); if (light_level >= 15) light_level = 15; if (light_level <= 1) light_level = 1; //DEBUG SPI // /* Serial.println("ldr_value [0-???]:"); Serial.println(ldr_value); Serial.println("ldr_adjusted [0-1023]:"); Serial.println(ldr_adjusted); Serial.println("ldr:"); Serial.println(ldr); Serial.println("light_level:"); Serial.println(light_level); // */ //level=2; level = light_level; } DateTime old; void loop() { // get time DateTime now = RTC.now(); // DEBUG RTC // /* Serial.print(now.year(), DEC); Serial.print('/'); Serial.print(now.month(), DEC); Serial.print('/'); Serial.print(now.day(), DEC); Serial.print(' '); Serial.print(now.hour(), DEC); Serial.print(':'); Serial.print(now.minute(), DEC); Serial.print(':'); Serial.print(now.second(), DEC); Serial.println(); // */ if (now.second()!=old.second()) { old = now; doLDR(); } // clear LED array memset(leds, 0, NUM_LEDS * 3); if (level < 4) { // this is the night mode // set LED background for (int i=0; i<NUM_LEDS; i++) { leds[i].r = bright[level]; leds[i].g = (bright[level]+1)/2; } // set pixels //leds[(now.second())%60].r = bright[level]; leds[(now.minute())%60].g = 0; leds[(now.minute())%60].r = bright[level+2]; unsigned char hourpos = (now.hour()%12)*5; leds[((59+hourpos)%60)%60].g = 0; leds[(hourpos)%60].g = 0; leds[((hourpos+1))%60].g = 0; leds[(hourpos)%60].r = bright[level+2]; } else { // set pixels leds[(now.second())%60].r = bright[level]; leds[(now.minute())%60].b = bright[level]; unsigned char hourpos = (now.hour()%12)*5; leds[((59+hourpos)%60)%60].g = bright[level/2]; leds[(hourpos)%60].g = bright[level]; leds[((hourpos+1))%60].g = bright[level/2]; } // update LEDs FastSPI_LED.show(); // wait some time delay(500); }
The FastSPI_LED library is no longer available and has evolved into the FastLED library with slightly different syntax. Use the following updated Arduino code:
// Original code by Tobias Floery <tobias@floery.net> // Converted to FastLED by Tablelands Computers <info@tablelandscomputers.com> // FastLED Library from https://github.com/FastLED/FastLED #include <FastLED.h> // Adafruits RTClib from https://github.com/adafruit/RTClib #include <Wire.h> #include "RTClib.h" RTC_DS1307 RTC; #define NUM_LEDS 60 #define LED_TYPE WS2812 #define DATA_PIN 11 #define COLOR_ORDER GRB CRGB leds[NUM_LEDS]; // Filter averaging factor - higher value means more sluggish response to changes in ambient brightness #define FILTER_LEN 8 // Brightness level initial value int level=15; // Brightness correction for Leds unsigned char bright[] = {0, 2, 4, 7, 11, 18, 30, 40, 50, 65, 80,96,125,160, 200, 255}; void setup() { Serial.begin(57600); // init RTClib Wire.begin(); RTC.begin(); // Following line sets the RTC to the date & time this sketch was compiled /* RTC.adjust(DateTime(__DATE__, __TIME__)); */ // Setup FastLED Lib FastLED.addLeds<LED_TYPE,DATA_PIN,COLOR_ORDER>(leds,NUM_LEDS).setCorrection(TypicalLEDStrip); // setup measurement for LDR digitalWrite(A0, HIGH); // set pullup on analog pin 0 pinMode(A1, OUTPUT); digitalWrite(A1, LOW); } unsigned int ldr=0; void doLDR() { unsigned int ldr_value = analogRead(0); //reads the LDR values //Adjust for LDR variations. //dark = 1023 //light = 0 //If your LDR for example reaches a max analogRead value of 350 instead of 1023 for 100% dark. //unsigned int ldr_adjusted=map(ldr_value,0,350,0,1023); unsigned int ldr_adjusted=map(ldr_value,0,700,0,1023); //set max limit (to avoid potential 'divide-by-zero's). if (ldr_adjusted >= 1023) ldr_adjusted = 1023; //ldr follows ldr_adjusted, but is averaged so that values only change gradually ldr = ((unsigned long)(FILTER_LEN-1)*ldr+ldr_adjusted)/FILTER_LEN; unsigned int light_level=0; //translate [0-1023] to [15-0] //light_level = (1024-ldr)>>6; light_level=map(ldr,0,1023,15,0); if (light_level >= 15) light_level = 15; if (light_level <= 1) light_level = 1; //DEBUG SPI // /* Serial.println("ldr_value [0-???]:"); Serial.println(ldr_value); Serial.println("ldr_adjusted [0-1023]:"); Serial.println(ldr_adjusted); Serial.println("ldr:"); Serial.println(ldr); Serial.println("light_level:"); Serial.println(light_level); // */ //level=2; level = light_level; } DateTime old; void loop() { // get time DateTime now = RTC.now(); // DEBUG RTC // /* Serial.print(now.year(), DEC); Serial.print('/'); Serial.print(now.month(), DEC); Serial.print('/'); Serial.print(now.day(), DEC); Serial.print(' '); Serial.print(now.hour(), DEC); Serial.print(':'); Serial.print(now.minute(), DEC); Serial.print(':'); Serial.print(now.second(), DEC); Serial.println(); // */ if (now.second()!=old.second()) { old = now; doLDR(); } // clear LED array memset(leds, 0, NUM_LEDS * 3); if (level < 4) { // this is the night mode // set LED background for (int i=0; i<NUM_LEDS; i++) { leds[i].r = bright[level]; leds[i].g = (bright[level]+1)/2; } // set pixels //leds[(now.second())%60].r = bright[level]; leds[(now.minute())%60].g = 0; leds[(now.minute())%60].r = bright[level+2]; unsigned char hourpos = (now.hour()%12)*5; leds[((59+hourpos)%60)%60].g = 0; leds[(hourpos)%60].g = 0; leds[((hourpos+1))%60].g = 0; leds[(hourpos)%60].r = bright[level+2]; } else { // set pixels leds[(now.second())%60].r = bright[level]; leds[(now.minute())%60].b = bright[level]; unsigned char hourpos = (now.hour()%12)*5; leds[((59+hourpos)%60)%60].g = bright[level/2]; leds[(hourpos)%60].g = bright[level]; leds[((hourpos+1))%60].g = bright[level/2]; } // update LEDs //FastLED.setBrightness(100); FastLED.show(); FastLED.delay(500); // wait some time //delay(500); }
Library Source Files:
RTClib-master
FastLED-master
Day mode
Night mode
For a final version of the code -including hour hand progression as the minutes fill the hour and 5 minute interval number marks:
// Original code by Tobias Floery <tobias@floery.net> // Converted to FastLED by Tablelands Computers <info@tablelandscomputers.com> // FastLED Library from https://github.com/FastLED/FastLED #include <FastLED.h> // Adafruits RTClib from https://github.com/adafruit/RTClib #include <Wire.h> #include "RTClib.h" RTC_DS1307 RTC; #define NUM_LEDS 60 #define LED_TYPE WS2812 #define DATA_PIN 11 #define COLOR_ORDER GRB CRGB leds[NUM_LEDS]; // Filter averaging factor - higher value means more sluggish response to changes in ambient brightness #define FILTER_LEN 8 // Brightness level initial value int level=15; // Brightness correction for Leds unsigned char bright[] = {0, 2, 4, 7, 11, 18, 30, 40, 50, 65, 80,96,125,160, 200, 255}; void setup() { Serial.begin(57600); // init RTClib Wire.begin(); RTC.begin(); // Following line sets the RTC to the date & time this sketch was compiled /* RTC.adjust(DateTime(__DATE__, __TIME__)); */ // Setup FastLED Lib FastLED.addLeds<LED_TYPE,DATA_PIN,COLOR_ORDER>(leds,NUM_LEDS).setCorrection(TypicalLEDStrip); // setup measurement for LDR digitalWrite(A0, HIGH); // set pullup on analog pin 0 pinMode(A1, OUTPUT); digitalWrite(A1, LOW); } unsigned int ldr=0; void doLDR() { unsigned int ldr_value = analogRead(0); //reads the LDR values //Adjust for LDR variations. //dark = 1023 //light = 0 //If your LDR for example reaches a max analogRead value of 350 instead of 1023 for 100% dark. unsigned int ldr_adjusted=map(ldr_value,0,700,0,1023); //set max limit (to avoid potential 'divide-by-zero's). if (ldr_adjusted >= 1023) ldr_adjusted = 1023; //ldr follows ldr_adjusted, but is averaged so that values only change gradually ldr = ((unsigned long)(FILTER_LEN-1)*ldr+ldr_adjusted)/FILTER_LEN; unsigned int light_level=0; //translate [0-1023] to [15-0] //light_level = (1024-ldr)>>6; light_level=map(ldr,0,1023,15,0); if (light_level >= 15) light_level = 15; if (light_level <= 1) light_level = 1; //DEBUG SPI // /* Serial.println("ldr_value [0-???]:"); Serial.println(ldr_value); Serial.println("ldr_adjusted [0-1023]:"); Serial.println(ldr_adjusted); Serial.println("ldr:"); Serial.println(ldr); Serial.println("light_level:"); Serial.println(light_level); // */ //level=2; level = light_level; } DateTime old; void loop() { // get time DateTime now = RTC.now(); // DEBUG RTC // /* Serial.print(now.year(), DEC); Serial.print('/'); Serial.print(now.month(), DEC); Serial.print('/'); Serial.print(now.day(), DEC); Serial.print(' '); Serial.print(now.hour(), DEC); Serial.print(':'); Serial.print(now.minute(), DEC); Serial.print(':'); Serial.print(now.second(), DEC); Serial.println(); // */ if (now.second()!=old.second()) { old = now; doLDR(); } // clear LED array memset(leds, 0, NUM_LEDS * 3); if (level < 4) { // this is the night mode // set LED background for (int i=0; i<NUM_LEDS; i++) { leds[i].r = bright[level]; leds[i].g = (bright[level]+1)/2; } // set pixels //leds[(now.second())%60].r = bright[level]; leds[(now.minute())%60].g = 0; leds[(now.minute())%60].r = bright[level+2]; unsigned char hourpos = (now.hour()%12)*5; // To let the hour hand creep to the next hour as the minutes progress, // for every 12 minutes offset the hourpos by 1 (= 1 LED). if (now.minute() >= 12) hourpos=hourpos+1; if (now.minute() >= 24) hourpos=hourpos+1; if (now.minute() >= 36) hourpos=hourpos+1; if (now.minute() >= 48) hourpos=hourpos+1; leds[((59+hourpos)%60)%60].g = 0; leds[(hourpos)%60].g = 0; leds[((hourpos+1))%60].g = 0; leds[(hourpos)%60].r = bright[level+2]; } else { // light the number marks leds[0].r = 2; leds[15].r = 2; leds[30].r = 2; leds[45].r = 2; leds[0].b = 5; leds[15].b = 5; leds[30].b = 5; leds[45].b = 5; leds[5].r = 2; leds[10].r = 2; leds[20].r = 2; leds[25].r = 2; leds[35].r = 2; leds[40].r = 2; leds[50].r = 2; leds[55].r = 2; leds[5].b = 5; leds[10].b = 5; leds[20].b = 5; leds[25].b = 5; leds[35].b = 5; leds[40].b = 5; leds[50].b = 5; leds[55].b = 5; // set pixels leds[(now.second())%60].r = bright[level]; leds[(now.second())%60].g = 0; leds[(now.second())%60].b = 0; leds[(now.minute())%60].r = 0; leds[(now.minute())%60].g = 0; leds[(now.minute())%60].b = bright[level]; //hour=0, 1, 2, 3, 4, ... ,22, 23 //hourpos = 0, 5 ,10, 15 ,20, ... , 50, 55 unsigned char hourpos = (now.hour()%12)*5; // To let the hour hand creep to the next hour as the minutes progress, // for every 12 minutes offset the hourpos by 1 (= 1 LED). if (now.minute() >= 12) hourpos=hourpos+1; if (now.minute() >= 24) hourpos=hourpos+1; if (now.minute() >= 36) hourpos=hourpos+1; if (now.minute() >= 48) hourpos=hourpos+1; leds[((59+hourpos)%60)%60].g = bright[level/2]; leds[(hourpos)%60].g = bright[level]; leds[((hourpos+1))%60].g = bright[level/2]; } // update LEDs //FastLED.setBrightness(100); FastLED.show(); FastLED.delay(500); // wait some time //delay(500); }