Instead of displaying numbers, what if your clock spoke to you in unnecessarily verbose English? âIT IS QUARTER PAST TEN.â That is the magic of a Word Clock. Itâs a beautiful piece of modern decor that takes an absurd amount of time to build. Weâre combining Addressable NeoPixels with a Real-Time Clock to illuminate a letter matrix. Prepare to do a lot of wiring.
A Word Clock relies on a grid of letters (usually 10x11). Behind this grid is a matrix of 110 addressable RGB LEDsâone for every single letter. The letters are arranged so that by lighting up specific combinations, you can spell out any time in five-minute increments.
The brain of the operation is an Arduino Nano, which reads the current time from the DS3231 RTC. The DS3231 is crucial here because it has a battery backup and a temperature-compensated crystal oscillator (TCXO), meaning it wonât lose time even if you unplug the clock or the room gets hot.
Once the Arduino knows the time, it runs through a series of if/else statements to figure out which specific LEDs in the NeoPixel strip need to turn on to spell out that time.
Here is the core electronics hardware youâll need:
For the physical enclosure, you will need a 10x11 letter grid. You can find pre-made designs online to laser-cut out of wood or acrylic, 3D print, or even print onto thick cardstock and cut out with a hobby knife. You will also need a âbaffleâ grid to go behind the letters so the light from one LED doesnât bleed into the neighboring letters.
GND to Arduino GND.VCC to Arduino 5V.SDA to Arduino A4.SCL to Arduino A5.5V and GND directly to the power supply.GND to the power supply GND so they share a common ground.DIN (Data In) to Arduino Digital Pin 6, placing the 330Ω resistor inline between the Arduino and the strip.Because the full word clock code is quite long (mapping 110 LEDs!), here is a structural overview of how the logic works using the FastLED library and the RTClib library:
#include <Wire.h>
#include "RTClib.h"
#include <FastLED.h>
#define LED_PIN 6
#define NUM_LEDS 110
#define BRIGHTNESS 50
#define LED_TYPE WS2812B
#define COLOR_ORDER GRB
CRGB leds[NUM_LEDS];
RTC_DS3231 rtc;
// Define the words based on your specific LED layout!
// Example: The word "IT" might be LEDs 0 and 1.
int word_IT[] = {0, 1, -1};
int word_IS[] = {3, 4, -1};
// ... define all words ...
void setup() {
FastLED.addLeds<LED_TYPE, LED_PIN, COLOR_ORDER>(leds, NUM_LEDS);
FastLED.setBrightness(BRIGHTNESS);
if (!rtc.begin()) {
while (1); // Stop if RTC not found
}
}
// Function to light up an array of LEDs
void displayWord(int wordArray[], CRGB color) {
for (int i = 0; wordArray[i] != -1; i++) {
leds[wordArray[i]] = color;
}
}
void loop() {
DateTime now = rtc.now();
// Clear all LEDs first
FastLED.clear();
// Always turn on "IT IS"
displayWord(word_IT, CRGB::White);
displayWord(word_IS, CRGB::White);
// Logic to determine the hour and minute
int h = now.hour();
int m = now.minute();
// Example Minute Logic:
if (m >= 15 && m < 20) {
displayWord(word_QUARTER, CRGB::White);
displayWord(word_PAST, CRGB::White);
} else if (m >= 30 && m < 35) {
displayWord(word_HALF, CRGB::White);
displayWord(word_PAST, CRGB::White);
}
// Example Hour Logic (Simplified):
if (h == 10 || h == 22) {
displayWord(word_TEN_HOUR, CRGB::White);
}
// Push the data to the LED strip
FastLED.show();
delay(1000); // Wait a second before updating again
}
Take your time assembling the physical grid, and youâll be rewarded with an amazing centerpiece for your living room or workshop!