Time To Hack Binary Clock

From NYC Resistor Wiki

Introduction[edit]

The "Time To Hack" Binary Clock is Justin's first laser project. It uses 10 LED lights to display the current time in binary. 4 white LEDs represent hours, 6 red LEDs represent minutes. More Images Here

Parts List[edit]

  • 2 x 12"x12" Gray Translucent Acrylic
  • 1 x 12"x12" Clear or other Translucent Acrylic
  • 1 x Arduino Diecimila
  • 4 x Ultra Bright White LEDs
  • 6 x Red LEDs
  • 4 x B3? mounting screws, with nuts and washers (fits 3.5mm diameter hole)
  • 4 x ?? mounting screws with nuts (fits 4.75mm diameter hole)

The Basic Concept[edit]

Use three pieces of acrylic, each with similar holes cut in them. The top piece only has four holes for the mounting screws that hold the whole thing together and the "Time To Hack" etch. Under that is the clear piece with holes for the mounting screws and lights. Under that is the back piece which is the part that we actually mount to the wall. The extra space on the square piece of acrylic is used to cut out spacers which fit between each of the layers. In this revision I mounted the Arduino on the back piece, but it should've been mounted on the middle piece (see below) as it made me use a ton of extra wire, and it was really difficult to get the whole thing to come together in the end.

Lessons[edit]

Dos[edit]

  • Do run lots of tests on cardboard. Test every step along the way.
  • Do ask lots of questions and get input from other people.
  • Do make first, then code
  • Do use spare space on the acrylic to make spacers

Don'ts[edit]

  • Don't put the board and the lights on separate plates
  • Don't use a Diecimila, use a LilyPad
  • Don't be lazy, if you do use a Diecimila, use header pins and solder

Code[edit]

// TimeToHack.cpp - Justin Day 9/1/2008

/* 
  * Please note that I grabbed pieces of this code from Maurice Ribble 
  * http://www.glacialwanderer.com/hobbyrobotics/?cat=4
  */

#include "WProgram.h"
#include <Wire.h>

#define DEBUG            0
#define DS1307_I2C_ADDRESS 0x68
#define FIRST_PIN        2
#define LAST_PIN         11
#define FIRST_PIN_HOUR   5
#define LAST_PIN_HOUR    2
#define FIRST_PIN_MIN    6
#define LAST_PIN_MIN     11
#define PIN_SEC          13
#define BIT(x,y)     ((x & (1 << y)) >> y)

void lightTest() {
   int i=0;
   
   for (i=FIRST_PIN_HOUR; i>=LAST_PIN_HOUR; i--) {
       digitalWrite(i,1);
       delay(500);
       digitalWrite(i,0);
   }
   
   for (i=FIRST_PIN_MIN; i<=LAST_PIN_MIN; i++) {
       digitalWrite(i,1);
       delay(500);
       digitalWrite(i,0);
   }
   
   digitalWrite(PIN_SEC,0);
   delay(500);
   digitalWrite(PIN_SEC,1);
   delay(500);
   digitalWrite(PIN_SEC,0);
   
}

// Convert normal decimal numbers to binary coded decimal
byte decToBcd(byte val)
{
  return ( (val/10*16) + (val%10) );
}

// Convert binary coded decimal to normal decimal numbers
byte bcdToDec(byte val)
{
  return ( (val/16*10) + (val%16) );
}

// 1) Sets the date and time on the ds1307
// 2) Starts the clock
// 3) Sets hour mode to 24 hour clock
// Assumes you're passing in valid numbers
void setDateDs1307(byte second,        // 0-59
                   byte minute,        // 0-59
                   byte hour,          // 1-23
                   byte dayOfWeek,     // 1-7
                   byte dayOfMonth,    // 1-28/29/30/31
                   byte month,         // 1-12
                   byte year)          // 0-99
{
   Wire.beginTransmission(DS1307_I2C_ADDRESS);
   Wire.send(0);
   Wire.send(decToBcd(second));    // 0 to bit 7 starts the clock
   Wire.send(decToBcd(minute));
   Wire.send(decToBcd(hour));      // If you want 12 hour am/pm you need to set
                                   // bit 6 (also need to change readDateDs1307)
   Wire.send(decToBcd(dayOfWeek));
   Wire.send(decToBcd(dayOfMonth));
   Wire.send(decToBcd(month));
   Wire.send(decToBcd(year));
   Wire.endTransmission();
}

// Gets the date and time from the ds1307
void getDateDs1307(byte *second,
          byte *minute,
          byte *hour,
          byte *dayOfWeek,
          byte *dayOfMonth,
          byte *month,
          byte *year)
{
  // Reset the register pointer
  Wire.beginTransmission(DS1307_I2C_ADDRESS);
  Wire.send(0);
  Wire.endTransmission();

  Wire.requestFrom(DS1307_I2C_ADDRESS, 7);

  // A few of these need masks because certain bits are control bits
  *second     = bcdToDec(Wire.receive() & 0x7f);
  *minute     = bcdToDec(Wire.receive());
  *hour       = bcdToDec(Wire.receive() & 0x3f);  // Need to change this if 12 hour am/pm
  *dayOfWeek  = bcdToDec(Wire.receive());
  *dayOfMonth = bcdToDec(Wire.receive());
  *month      = bcdToDec(Wire.receive());
  *year       = bcdToDec(Wire.receive());
}

int readNextNumber() {
    char buffer[5];
    char c;
    int n = 0;
    
    do {
      c = Serial.read();
      buffer[n] = c;
      n++;
    }
    while (c >= '0' && c <= '9' && n<5);
    
    buffer[n] = 0;
    int result = atoi(buffer);
    
    return result;
}

void checkToSetClock() {
    int year;
    int month;
    int day;
    int hour;
    int minute;
    
    if (Serial.available() > 0) {
      Serial.print("Setting clock YYYY/MM/DD hh:mm> ");
      year = readNextNumber();
      month = readNextNumber();
      day = readNextNumber();
      hour = readNextNumber();
      minute = readNextNumber();
      
      if (year >= 100) { year -= 2000; }
      setDateDs1307(0,(byte)minute,(byte)hour,1,(byte)day,(byte)month,(byte)year);
      Serial.println("Clock has been set.");
    }
}

void setup() {
  Wire.begin();
  Serial.begin(9600); 
  int i=0;

  for (i=FIRST_PIN;i<=LAST_PIN;i++) {
      pinMode(i,OUTPUT);
  }
  
  pinMode(PIN_SEC,OUTPUT);

#if DEBUG  
  Serial.println("Start program");
#endif

  lightTest();
}

void loop() {
  byte second, minute, hour, dayOfWeek, dayOfMonth, month, year;
  int i = 0;
  
  getDateDs1307(&second, &minute, &hour, &dayOfWeek, &dayOfMonth, &month, &year);

#if DEBUG
  Serial.print((int)year);
  Serial.print("/");
  Serial.print((int)month);
  Serial.print("/");
  Serial.print((int)dayOfMonth);
  Serial.print(" ");
  Serial.print((int)hour);
  Serial.print(":");
  Serial.print((int)minute);
  Serial.print(":");
  Serial.print((int)second);
  Serial.print(" ");
#endif

  if (hour > 12)
    hour -= 12;

  for(i=3;i>=0;i--) {
#if DEBUG
    Serial.print(BIT(hour,i));
#endif
    digitalWrite(LAST_PIN_HOUR+i, BIT(hour,i));
  }

#if DEBUG
  Serial.print(":");
#endif
  for(i=5;i>=0;i--) {
#if DEBUG
    Serial.print(BIT(minute,i));
#endif
    digitalWrite(LAST_PIN_MIN-i, BIT(minute,i));
  }
  
  digitalWrite(PIN_SEC,second % 2);
  
#if DEBUG
  Serial.println();
#endif

  checkToSetClock();
  
  //no need to rush
  delay(1000);
}

Drawing[edit]

If the SVGs don't work for you, email me and I can give you the Corel Draw files that I exported them from. Inkscape SVG -> Corel Draw drawing -> fixed Corel Draw drawing -> SVG == FAIL :)