
A 60-LED ring driven by an Arduino Nano with a DS3231 backing it up — the result is an analog-style clock that drifts less than two minutes a year, survives power outages, and lets you reskin the colour scheme in a few lines of code. Whole build is one evening of soldering and one weekend of fiddling with the look.
One WS2812B (a.k.a. NeoPixel) ring with 60 LEDs maps perfectly to a clock face — every LED is a minute, every fifth LED is an hour. The Arduino reads time from a DS3231 over I²C, computes which LEDs should be lit, and pushes the colours to the ring. The DS3231 has its own coin-cell battery, so the clock keeps time when you unplug everything.
This is a "smart" clock in the sense that you control exactly what each pixel does — fade tails on the second hand, different colours AM vs PM, brighter ticks at 12/3/6/9, dim the whole face after 22:00. Not "smart" in the Wi-Fi sense; we'll mention that variant at the end.
Parts list| Item | AliExpress | Amazon |
|---|---|---|
| Arduino Nano (CH340 clone is fine) | AliExpress Link | Amazon Link |
| WS2812B 60-LED ring (5 V, ~150 mm OD) | AliExpress Link | Amazon Link |
| DS3231 RTC module with AT24C32 EEPROM | AliExpress Link | Amazon Link |
| CR2032 coin cell (3 V, non-rechargeable) | AliExpress Link | Amazon Link |
| 5 V 3 A power supply, 5.5 × 2.1 mm barrel | AliExpress Link | Amazon Link |
| 1000 µF / 16 V electrolytic capacitor | AliExpress Link | Amazon Link |
| 12 mm tactile push buttons (×2) | AliExpress Link | Amazon Link |
| Dupont jumper wires (M-F & F-F kit) | AliExpress Link | Amazon Link |
You'll also want a 470 Ω resistor for the data line (out of any junk-box resistor pack) and a 3D-printed or laser-cut diffuser ring — see "Enclosure" near the end.
Five connections, no surprises. The 470 Ω resistor sits in series on the data line right next to the ring's DIN pad — it dampens reflections that can corrupt the first pixel.
| From | To |
|---|---|
| 5 V PSU + | Ring V+, Arduino VIN, DS3231 VCC |
| 5 V PSU − | Ring GND, Arduino GND, DS3231 GND |
| Arduino D6 | 470 Ω → Ring DIN |
| Arduino A4 (SDA) | DS3231 SDA |
| Arduino A5 (SCL) | DS3231 SCL |
| Arduino D2 | Button 1 → GND (mode) |
| Arduino D3 | Button 3 → GND (set) |
Buttons use the Arduino's internal pull-ups (INPUT_PULLUP), so the other leg goes straight to GND — no external resistor needed.
A note on logic levels: WS2812B is officially happiest with a 3.5 V minimum on its data line. The Nano runs at 5 V, so the data signal is comfortably above threshold. If you ever swap to an ESP8266 or ESP32, add a 74AHCT125 level shifter — those boards drive 3.3 V, which is right on the edge.
CodeThree libraries, all installable from the Arduino IDE Library Manager:
Skeleton sketch (drop in, set the time once, then comment out the rtc.adjust() line and re-flash):
#include <Wire.h>
#include <RTClib.h>
#include <Adafruit_NeoPixel.h>
#define LED_PIN 6
#define NUM_LEDS 60
#define BRIGHTNESS 60 // 0–255; keep ≤80 unless you have airflow
RTC_DS3231 rtc;
Adafruit_NeoPixel ring(NUM_LEDS, LED_PIN, NEO_GRB + NEO_KHZ800);
void setup() {
Wire.begin();
rtc.begin();
// Run ONCE to set the clock from your computer's compile time:
// rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));
ring.begin();
ring.setBrightness(BRIGHTNESS);
ring.show();
}
void loop() {
DateTime now = rtc.now();
ring.clear();
// Dim white tick marks at 12, 3, 6, 9
for (int i = 0; i < 60; i += 15)
ring.setPixelColor(i, ring.Color(20, 20, 20));
int hourLed = (now.hour() % 12) * 5 + now.minute() / 12;
ring.setPixelColor(hourLed, ring.Color(80, 0, 0)); // red hour
ring.setPixelColor(now.minute(), ring.Color(0, 80, 0)); // green min
ring.setPixelColor(now.second(), ring.Color(0, 0, 80)); // blue sec
ring.show();
delay(200);
}
That's the whole thing in 30-odd lines. Once it works, the fun starts:
now.hour() < 12 ? red : purple.if (now.hour() >= 22 || now.hour() < 7) ring.setBrightness(10);The rtc.adjust(DateTime(F(__DATE__), F(__TIME__))) line uses the compile time of the sketch. Procedure:
rtc.adjust(...) line.A tidier way is to wire the buttons to nudge the time forward/backward by a minute, and set it once by hand. The DS3231 is accurate enough that you'll only do this once or twice a year.
Common mistakes__TIME__ while the IDE was on a different timezone, or the DS3231 is in 12-hour mode. RTClib defaults to 24-hour; verify with a serial print.BRIGHTNESS to 40-ish; high values bias toward white because the LEDs saturate. A diffuser (frosted acrylic or matte 3D-printed PETG) makes 30 % brightness look like 100 %.A 60-LED ring is ~150 mm OD. Two common approaches:
📷 (photo placeholder — slot ds3231-module: DS3231 RTC breakout module with CR2032 battery holder and AT24C32 EEPROM)
This Arduino + DS3231 build is the right call if you want a standalone clock you flash once and forget — no router dependency, no cloud, runs offline forever. It's also the right starting point if you've never touched WS2812Bs before; everything stays at 5 V, no level-shifting drama.
If you want auto-DST and zero manual time-setting, swap the Nano for a Wemos D1 Mini (ESP8266) or an ESP32, drop the DS3231, and pull time from an NTP server. Same ring, same code structure (FastLED or NeoPixel libraries are identical on ESP), but you'll need a 74AHCT125 to bring the 3.3 V data signal up to the WS2812B's input threshold cleanly. Save that for after you've built this one.
Comments
█
█
█
█
█
█
█
█
█
█