I created a Arduino controled led clock with 60 rgb led’s. This one is inspired by the Equinox Clock from Bram Knaapen.

LED strip

For the 60 RGB leds I use a string of RGB leds that I order directly from China, each of those leds has a LPD6803 IC. A arduino library for this string can be found at adafruit’s github.

Time Keeping

For time keeping I am using a a RTC DS1307 that is connected via I2C to pin A4 and A5 on the Arduino. Pin 7 from the DS1307 is connected to pin D2 on the Arduino an is set to a 1Hz Square Wave. I am using this to give the Arduino every second a interrupt, this made the timing a lot easier. I build the DS1307 on a custom should with breakout pins.

Dimming

There is also a LDR connected at pin A2, this wil measure the light and dim the led’s accordingly.

Arduino Shield

Design

For the design of the casing I am going for a 12 angle shape. The edge will be layered with sanded plexiglas sheets for a nice glow effect. The LED’s will in a aluminum bracket. Here is the first design what I made in google sketchup.

Power

The led string if all rgb leds are on will draw about 3.6 Amps at 5 volts. This of course is way to much for the Arduino regulator. But most of the time not all led’s will be on or at full brightness. Now I am using a switched 5.1 volt / 2 Amp power-supply that I had lying around. This power supply is directly connected to the + 5v on the arduino. So it’s bypassing the regulator on the Arduino.

Video

Here is a short video overview from the first proto type, this on is fitted in a carton box, so nothing fancy yet. Now I need to get my hands on a laser cutter to build the casing.

Code

All the files, codes and sources of this project you can find on my github.

//
// Equilux, a RGB Led Clock by Dennis Kruyt ([email protected]) 2011
// Inspired by the Equinox Clock from Bram Knaapen.
//
/*****************************************************************************/

// LPD6803 lib from ladyada
#include "LPD6803.h"

// LPD6802 pins
int dataPin = 4;       // 'green' wire
int clockPin = 5;      // 'blue' wire
// Don't forget to connect 'yellow' to ground and 'red' to +5V

// LDR pin
int LDRPin = A2;

// Timer 1 is also used by the strip to send pixel clocks
#include <TimerOne.h>

// Set the first variable to the NUMBER of pixels. 60 = 60 pixels in a row
LPD6803 strip = LPD6803(60, dataPin, clockPin);

//wire and rtc
#include <Wire.h>
#include "RTClib.h"

// RTC_Millis is for a soft rtc
//RTC_Millis RTC;
RTC_DS1307 RTC;

// Define second, minute, hour
int s;
int m;
int h;

// Brightness fade up (1 or 2) depens on LDR reading
int z;

// Set brightness min/max 31
int MinBright = 6;
int MaxBright = 31;
int brightness;

// LDR
int LDRValue;

// Pin 13 is used for a sec blink led
int led = 13;
volatile int state = LOW;
  
void setup() {
  
  Serial.begin(19200);
  
  //start wire and rtc
  Wire.begin();
  RTC.begin();
  
  if (! RTC.isrunning()) {
    Serial.println("RTC is NOT running!");
    // following line sets the RTC to the date & time this sketch was compiled
    RTC.adjust(DateTime(__DATE__, __TIME__));
  }
  
  // set 1hz sqw on DS1307 pin 7, we will using this for a interrupt on arduino pin 2
  Wire.beginTransmission(0x68);              // write the control register
  Wire.send(0x07);                           // register address 07H)
  Wire.send(0x90);                           // 0x90=1Hz, 0x91=4kHz, 0x92=8kHz, 0x93=32kHz
  Wire.endTransmission();
  
  // The Arduino needs to clock out the data to the pixels
  // this happens in interrupt timer 1, we can change how often
  // to call the interrupt. setting CPUmax to 100 will take nearly all all the
  // time to do the pixel updates and a nicer/faster display, 
  // especially with strands of over 100 dots.
  // (Note that the max is 'pessimistic', its probably 10% or 20% less in reality)
  strip.setCPUmax(95);  // up this if the strand flickers or is slow
  
  // Start up the LED counter
  strip.begin();
  
  // Update the strip, to start they are all 'off'
  strip.show();
  
  //Attach pin 7 from DS1307 to Arduino pin 2 and call function clock
  attachInterrupt(0, clock, FALLING);
  
  // Set pin 13 (led) to output mode
  pinMode(led, OUTPUT);

}

// Empty loop, all is done by the 1hz interupt on pin 2
void loop () { }


void clock() {
    
  //attach Interrupt stops the strip, so start it again  
  strip.begin();
    
  //blink led on pin 13
  digitalWrite(led, state);
  state = !state;

  //Get current time
  DateTime now = RTC.now();  
  
  // mapping hour 24 => 12 => 60
  h = now.hour(), DEC;
  if (h > 12) { h = h - 12; } 
  //else if (h = 12) { h == 0; }
  h = map(h, 0, 12, 0, 60);
  
  if ( m < 15 ) { h == h; }
  else if ( m < 30 ) { h = h + 1; }
  else if ( m < 45 ) { h = h + 2; }
  else if ( m < 59 ) { h = h + 3; }
     
  m = now.minute(), DEC;
  s = now.second(), DEC;
  
    // Get LDR vaulue and set brightness  
    LDRValue = analogRead(LDRPin);
    brightness = map(LDRValue, 0, 1023, MaxBright, MinBright);
  
    // set increase step
    if ( brightness < 20 ) {
      z = 1;
    } else {
      z = 2;
    }
    
    //todo
    //strip.setPixelColor((h - 1), 0, 0, 0);
    
    strip.setPixelColor((m - 1), 0, 0, 0);
    //unset -2 ,-3 seconds
    strip.setPixelColor((s - 2 ), 0, 0, 0);
    strip.setPixelColor((s - 3 ), 0, 0, 0);
    
    // clear transistion from 59 -> 0
    if (s == 0) { strip.setPixelColor((58), 0, 0, 0); }
    if (s == 1) { strip.setPixelColor((59), 0, 0, 0); }  
    if (m == 0) { strip.setPixelColor((59), 0, 0, 0); }
    
    //start fade up/down
    for (int y = 1; y < brightness; y = y + z) {
  
         strip.setPixelColor((s - 1 ), (brightness - y), 0, 0);
         if (s == 0) { strip.setPixelColor(59, (brightness - y), 0, 0); }  
         strip.setPixelColor(s, brightness, 0, 0); 
         strip.setPixelColor((s + 1 ), y, 0, 0);
         if (s == 59) { strip.setPixelColor(0, y, 0, 0); } 
        
         strip.setPixelColor(m, 0, brightness, 0);  
         strip.setPixelColor(h, 0, 0, brightness); 
         
         // second equals minute
         if ((s + 1) == m) { strip.setPixelColor(s + 1, y, brightness, 0); } 
         if (s == m) { strip.setPixelColor(s, brightness, brightness, 0); } 
         if ((s - 1) == m) { strip.setPixelColor(s - 1, (brightness - y), brightness, 0); } 
         
         // second equals hour
         if ((s + 1) == h) { strip.setPixelColor(s + 1, y, 0, brightness); } 
         if (s == h) { strip.setPixelColor(s, brightness, 0, brightness); }
         if ((s - 1) == h) { strip.setPixelColor(s - 1, (brightness - y), 0, brightness); } 
     
         // update strip
         strip.show();
         
         delay(105 - (2 * y)); 
     }
   
    // Debug   
    //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();
    //Serial.println(h); 

}