## Background I've always been fascinated with time. I remember being a kid 1980s and initially struggling with telling time on an analog clock or watch-face. One of my grandparents had a grandfather clock and I remember watching it and wondering how it worked on the inside as the pendulum swung back and forth. In the last decade or so I've discovered other types of clocks, like the [binary clock](https://en.wikipedia.org/wiki/Binary_clock). I've wanted to build one for a very long time in some way. I figured Arduino was probably the simplest way to go. ## Materials 1. [Arduino MEGA 2560](https://cdn.robotshop.com/media/a/ard/rb-ard-33/pdf/arduinomega2560datasheet.pdf) (or a microcontroller of some kind) 1. And the Arduino IDE or some way of compiling and uploading your "sketches" 2. [DS3231](https://www.analog.com/media/en/technical-documentation/data-sheets/ds3231.pdf) real-time clock module (how else are we going to keep time?) 3. Breadboards for testing 1. I also used a prototype PCB for practicing my soldering and making the wiring a little easier 4. A bunch of color-coded wires (or whatever you want as long as you know what goes where) 5. [TLC5947](https://www.ti.com/lit/ds/symlink/tlc5947.pdf), an LED driver for handling the voltage and resistance to a bunch of lights 6. And about 20 LEDs. I used 6 green, 7 blue and 7 red. ## Connection Details ### DS3231 RTC to Arduino: - VCC → 5V - GND → GND - SDA → SDA pin - SCL → SCL pin ### TLC5947 Arduino to LED Driver: - Digital pins D2-D7 → LED driver inputs (for hours) - Digital pins D8-D14 → LED driver inputs (for minutes) - Digital pins D15-D21 → LED driver inputs (for seconds) - 5V and GND → Driver power ### LED Array Layout: - **Hours**: 2 LEDs for tens place (can represent 0-2) and 4 LEDs for ones place (can represent 0-9) - **Minutes**: 3 LEDs for tens place (can represent 0-5) and 4 LEDs for ones place (can represent 0-9) - **Seconds**: 3 LEDs for tens place (can represent 0-5) and 4 LEDs for ones place (can represent 0-9) Each LED represents a binary bit (powers of 2: 2^0, 2^1, 2^2, etc.) ## Arduino Code ```c /* * Binary Clock using Arduino MEGA, DS3231 RTC, and TLC5947 LED Driver * * Hardware: * - Arduino MEGA (actually a knock-off) * - DS3231 Real Time Clock module * - TLC5947 constant current LED driver (24-channel) * - 20 LEDs * * LED Layout (3 columns): * Column 1 (right): Seconds (4 LEDs for 1s, 3 LEDs for 10s) * Column 2 (middle): Minutes (4 LEDs for 1s, 3 LEDs for 10s) * Column 3 (left): Hours (4 LEDs for 1s, 2 LEDs for 10s) */ #include <Wire.h> #include <RTClib.h> #include <Adafruit_TLC5947.h> // TLC5947 Configuration #define DATA_PIN 11 // Data pin #define CLOCK_PIN 13 // Clock pin #define LATCH_PIN 10 // Latch pin #define NUM_TLC 1 // Number of TLC5947 chips #define NUM_CHANNELS (24 * NUM_TLC) // 24 channels per chip // Initialize TLC5947 Adafruit_TLC5947 tlc = Adafruit_TLC5947(NUM_TLC, CLOCK_PIN, DATA_PIN, LATCH_PIN); // RTC module RTC_DS3231 rtc; // Maximum brightness (12-bit = 0-4095) #define MAX_BRIGHTNESS 4095 // Map the LEDs to TLC5947 channels // Hours (tens place) - 2 LEDs needed (max value 2) const int hourTens[] = {0, 1}; // Hours (ones place) - 4 LEDs needed (max value 9) const int hourOnes[] = {2, 3, 4, 5}; // Minutes (tens place) - 3 LEDs needed (max value 5) const int minuteTens[] = {6, 7, 8}; // Minutes (ones place) - 4 LEDs needed (max value 9) const int minuteOnes[] = {9, 10, 11, 12}; // Seconds (tens place) - 3 LEDs needed (max value 5) const int secondTens[] = {13, 14, 15}; // Seconds (ones place) - 4 LEDs needed (max value 9) const int secondOnes[] = {16, 17, 18, 19}; void setup() { Serial.begin(9600); // Initialize the TLC5947 LED driver tlc.begin(); // Initialize the RTC if (!rtc.begin()) { Serial.println("Couldn't find RTC"); while (1); } // Set the RTC to the date & time this sketch was compiled // Uncomment this line to set the time on the RTC (only needed once) // rtc.adjust(DateTime(F(__DATE__), F(__TIME__))); // If RTC lost power, set the time if (rtc.lostPower()) { Serial.println("RTC lost power, setting the time!"); // Set the RTC to the date & time this sketch was compiled rtc.adjust(DateTime(F(__DATE__), F(__TIME__))); } // Turn off all LEDs initially for (int i = 0; i < NUM_CHANNELS; i++) { tlc.setPWM(i, 0); } tlc.write(); } void loop() { DateTime now = rtc.now(); int hours = now.hour(); int minutes = now.minute(); int seconds = now.second(); int hourTensDigit = hours / 10; int hourOnesDigit = hours % 10; int minuteTensDigit = minutes / 10; int minuteOnesDigit = minutes % 10; int secondTensDigit = seconds / 10; int secondOnesDigit = seconds % 10; // Reset all LEDs prior to start for (int i = 0; i < NUM_CHANNELS; i++) { tlc.setPWM(i, 0); } displayBinary(hourTens, 2, hourTensDigit); displayBinary(hourOnes, 4, hourOnesDigit); displayBinary(minuteTens, 3, minuteTensDigit); displayBinary(minuteOnes, 4, minuteOnesDigit); displayBinary(secondTens, 3, secondTensDigit); displayBinary(secondOnes, 4, secondOnesDigit); tlc.write(); // Uncomment to print time to serial for debugging // Serial.print(hours); // Serial.print(":"); // if (minutes < 10) Serial.print("0"); // Serial.print(minutes); // Serial.print(":"); // if (seconds < 10) Serial.print("0"); // Serial.println(seconds); // Update every second delay(1000); } void displayBinary(const int pins[], int numPins, int value) { for (int i = 0; i < numPins; i++) { // Check if the i-th bit is set if (value & (1 << i)) { tlc.setPWM(pins[i], MAX_BRIGHTNESS); } else { tlc.setPWM(pins[i], 0); } } } ```