Status:  Completed Hackster.io Project Page: https://www.hackster.io/baldengineer/binboo Github Code:  https://github.com/baldengineer/BinBoo
BinBoo Binary Clock made out of Bamboo
Binary + Bamboo = BinBoo
 

Abstract

Binary + Bamboo = BinBoo.  This project is my first attempt at making a laser-cut enclosure.  Ponoko was used to cut the project which holds itself together.  The LEDs are driven by an Arduino-based clock that incorporates a RTC1307, FTDI chip, ATmega328, and TLC5940.

Electronics

BinBoo-v1 PCB
BinBoo-v1 PCB
Schematic (PDF):  binary_clock_rev1 V1 Of the Electronics (there are many issues with v1!) Parts list:
  • (12) – Bright Blue 5mm LEDs
  • (13) – Jumper Wires
  • (1) – BinBoo Controller Board with:
    • (1) – ATmega328
    • (1) – TLC5940
    • (1) – FTDI 232
    • (Various) Decoupling capacitors
    • USB Mini-B Port

Schematic:

The core design came from the Arduino Duemilanove schematic.  There were changes to the FTDI chip in order to make it work correctly.

LED Panel:

 
BinBoo - LED Panel Front
BinBoo – LED Panel Front
How BinBoo's LED Matrix is Wired
How BinBoo’s LED Matrix is Wired
The LED panel is constructed with all Anodes connected to VCC.  The cathodes each connect to an output of the TLC5940.  Due to a design change (from straight binary to BCD), the BinBoo Controller board does not have enough outputs connected to header pins.

Firmware

The code is based on the TimeRTC example from the Arduino Time Library.  In order to set the time, a serial monitor must be used.  The syntax is simplistic:  “T<seconds since epoch>”.  The UNIX time library provides this value rather easily. Code was added for: startup effect, fading between time changes, determining the BCD of the time, and getting time from the RTC. The startup effect is useful because it helps to identify wiring mistakes since it fades the LEDs in sequence. Code as of 5/19/2012:

/*
 *
 *  BinBooV2
 *  Created by:  James C Lewis. [email protected]
 *  www.baldengineer.com
 *
 * BinBoo is a Binary clock made out of bamboo materials. The electrical hardware includes
 * a ATmega328, DS1307 RTC, and a TLC5940. These chips are connected to 11 LEDs.
 *
 * from bash:  date +%s (for number of seconds)
 * CDT offset: -18000
 * CST offset: -21600
 */
#include <Time.h>
#include <Wire.h>
#include <DS1307RTC.h>
#include <Tlc5940.h>

#define EPOCH_OFFSET -18000
#define TIME_MSG_LEN   11
#define TIME_HEADER 'T'
#define TIME_REQUEST 7
#define WAIT_INTERVAL 5000

#define DAY_BRITE 512
#define NIGHT_BRITE 128

unsigned long waitMillis;

void setup() {
  Serial.begin(9600);
  Serial.println(F("BinBoo Release 0.2 - James Lewis ([email protected])"));
  Serial.println(F("Use date +%s to get current time in seconds"));
  setSyncProvider(RTC.get);  // grab time from the RTC
  if(timeStatus()!= timeSet)
    Serial.println("Unable to sync with the RTC");  // not really sure who is going to see this one.. ;)
  else
    Serial.println("RTC has set the system time");  

  Tlc.init();
  Tlc.clear();
  Tlc.update();

  waitMillis = millis() + 1000;   // setup first crossing point
  startUpSequence();
}

void loop() {
  int previousTime=0;
  int currentTime=0;
  while(1) {      // want to avoid making currentTime/previousTime global
    if (Serial.available())
      processSyncMessage();
    if ((long)(millis() - waitMillis) >= 0) {     // need to cast to signed math...
      printTimeDate();
      currentTime = calculateTimeBits();
       setTLCtime(previousTime, currentTime);
      previousTime = currentTime;
      waitMillis += WAIT_INTERVAL;  //sit around for another second.
    }
  }
}

void setTLCtime(int previousTime, int currentTime ) {

  if (previousTime == currentTime)    // time hasn't changed, so don't do anything
    return;

  int bright = 0;    // what is the max brightness, based on the time.
  if ((hour() >= 6) && (hour() <= 18))
    bright = DAY_BRITE;
  else
    bright = NIGHT_BRITE;

  for (int i=0; i<=bright; i++) {
    int fadeAmount = 0;  // each look of the bright for, will be to fade up/down the leds
    for (int j=0; j<12; j++) {   // this loop determines which direction and intensity of fade
      switch (bitRead(previousTime, j) - bitRead(currentTime,j)) {
      case 0:  // no change, the led alone
        if bitRead(currentTime,j)
          fadeAmount = bright;
        else
          fadeAmount = 0;
        break;
      case -1: // turn the led on
        fadeAmount = i;
        break;
      case 1: // turn the led off
        fadeAmount = bright - i;
        break;
      }
      Tlc.set(j, fadeAmount);
    }
    Tlc.update();
    delay(1);
  }
}

int calculateTimeBits() {
  int hours = hourFormat12();
  int minutes = minute();
  int timeLEDs=0;

  timeLEDs = hours;
  timeLEDs = hours << 8;

  timeLEDs += (minutes/10)<<4;
  timeLEDs += minutes%10;

  if (isPM())
    bitSet(timeLEDs, 11);

  return timeLEDs;
}

void printTimeDate() {
  printTime();
  Serial.print(" ");
  printDate();
  Serial.println("");
}

void printTime() {
  Serial.print(hourFormat12());
  printDigits(minute());
  printDigits(second());
  Serial.print(" ");
  if (isAM())
    Serial.print("AM");
  else
    Serial.print("PM");
}

void printDate() {
  Serial.print(month());
  Serial.print("/");
  Serial.print(day());
  Serial.print("/");
  Serial.print(year());
}

void printDigits(int digits){
  // utility function for digital clock display: prints preceding colon and leading 0
  Serial.print(":");
  if(digits < 10)
    Serial.print('0');
  Serial.print(digits);
}

void startUpSequence() {
  for (int j=0; j<12; j++) {
    Tlc.clear();
    for (int i=0; i<(DAY_BRITE+1); i=i+32) {
      Tlc.set(j, i);
      Tlc.update();
      delay(10);
    }
    for (int i=DAY_BRITE; i > 0; i=i-32) {
      Tlc.set(j,i);
      Tlc.update();
      delay(10);
    }

  }
}

void processSyncMessage() {
  // if time sync available from serial port, update time and return true
  if (Serial.available() >=  TIME_MSG_LEN ) {  // time message consists of a header and ten ascii digits
    char c = Serial.read() ; 

    if( c == TIME_HEADER ) {
      Serial.print(c);
      time_t pctime = 0;
      for(int i=0; i < TIME_MSG_LEN -1; i++){
        c = Serial.read();
        if( c >= '0' && c <= '9'){
          pctime = (10 * pctime) + (c - '0'); // convert digits to a number
        }
      }
      pctime = pctime EPOCH_OFFSET;  // the define has a math sign in it
      Serial.print(" - ");
      Serial.println(pctime);
      RTC.set(pctime);
      setTime(pctime);   // Sync Arduino clock to the time received on the serial port
      waitMillis += 100;
    }
  }
}

Demonstration

Acknowledgments

(Links to be added) 1. Arduino Project 2. Macetech’s ChronoDot 3.  My first Arduino TLC5940 Project Page
Author

Fan of making things beep, blink and fly. Created AddOhms. Stream on Twitch. Video Host on element14 Presents and writing for Hackster.IO. Call sign KN6FGY.

Write A Comment

This site uses Akismet to reduce spam. Learn how your comment data is processed.