LumiDial: a 72-LED Analog Wristwatch Powered by ATmega328

by taifur in Circuits > Wearables

747 Views, 10 Favorites, 0 Comments

LumiDial: a 72-LED Analog Wristwatch Powered by ATmega328

cover.jpg
cover1.jpg
cover2.jpg
LumiDial Wrist Watch

LumiDial is a custom-built wristwatch that blends classic analog style with modern LED technology. Instead of using physical hands, it uses 72 SMD LEDs arranged in a circular layout — 60 LEDs to indicate seconds and minutes, and 12 LEDs to mark the hours. At its heart lies an ATmega328 microcontroller, programmed to control the precise timing and LED animation that mimic the smooth motion of a traditional analog clock.

I designed the PCB myself, had it fabricated and assembled by JLCPCB, and then fitted it neatly inside a readymade stainless steel watch case. The result is a unique fusion of electronics, design, and craftsmanship — a wearable piece of engineering art that glows with precision and creativity.

In this project, I’ll walk you through the entire process — from circuit design and PCB layout to assembly, programming, and enclosure — so you can build your own version of LumiDial or use the idea as inspiration for your next DIY electronics project.

You can clone the schematic & PCB design from https://oshwlab.com/taifur/led_round_watch.

You can also visit my personal blog site: https://makerbangla.com/

Supplies

5433-01.jpg
5433-05.jpg
28.png
watch-case.jpg

Here’s the list of all the parts and tools you’ll need to bring this LED wristwatch to life! I tried to keep the design simple and based on easily available components so anyone can recreate it. You can substitute equivalent parts if you already have something similar in your toolbox.

If you plan to order the PCB with assembly service from JLCPCB, you don’t need to buy the individual electronic components separately — they will be assembled for you. The only items you’ll need to source yourself are the stainless steel watch case and Li-ion battery.

Hardware Components:

  1. Microcontroller – ATmega328P (Package - TQFP32) (Aliexpress)
  2. RTC – DS3231MZ+ (Package - SMD) (Aliexpress)
  3. SMD RED LED - 60pcs (Package - 0603) (Aliexpress)
  4. SMD BLUE LED - 12pcs (Package - 0603) (Aliexpress)
  5. SMD Tactile Switch - 1 pc (Package - 3x2.5mm) (Aliexpress)
  6. Crystal Oscillator 16MHz (Package - SMD) (Aliexpress)
  7. Load Capacitors for the crystal - 20 pF, 2pcs (Package - 0603) (Aliexpress)
  8. Current-limiting Resistors - 470 Ω (Package - 0603) (Aliexpress)
  9. Pull-up / general Resistors - 4.7 kΩ, 3pcs (Package - 0603) (Aliexpress)
  10. Decoupling Capacitor - 100 nF (0.1 µF), 1pcs (Package - 0603) (Aliexpress)
  11. Bulk Capacitor - 10 µF, 1pc (Package - 0805) (Aliexpress)
  12. Filter Capacitor - 1uF, 1pc (Package - 0603) (Aliexpress)
  13. 40mm (inner diameter) Stainless Steel Watch Case (Aliexpress)
  14. 150mAh Li-ion Battery (Aliexpress)
  15. DC Magnetic Pogo Pin Connector 2Pin (Aliexpress)


Tools:

  1. Pogo Pin Probe Clip - 6 Pins with 2.54mm Pitch (Aliexpress)
  2. CP2102 USB to TTL UART Serial Converter (Aliexpress)
  3. 6pcs Female to Female Jumper Wires (Aliexpress)

Circuit Design

schematic.png
schematic-2.png
schematic-mcu.png

I designed the schematic for LumiDial using EasyEDA, and the complete circuit diagram is shown in the image above.

At the heart of the circuit is an ATmega328P SMD microcontroller, which acts as the brain of the watch. It controls all 72 LEDs, communicates with the RTC, and handles user input through a single button.

🔹 Real-Time Clock (RTC)

For precise timekeeping, I used the DS3231MZ+ SMD real-time clock module. It’s connected to the ATmega328P via the default I²C pins (SDA and SCL). Two 4.7kΩ pull-up resistors are added on these lines to ensure reliable I²C communication. The DS3231 provides highly accurate time information, even when the main circuit is powered off (with a backup battery if added).

🔹 LED Matrix Display

The 72 SMD LEDs are arranged in a matrix configuration to minimize pin usage:

  1. The common anodes of the LEDs are grouped into 9 lines and connected to digital pins D0 to D8 of the microcontroller, each through a 470Ω current-limiting resistor.
  2. The common cathodes are grouped into 8 lines and connected to pins D9 to D16.

This matrix setup allows the ATmega328P to control all 72 LEDs efficiently using multiplexing. Out of these, 12 blue LEDs represent the hour markers, and 60 red LEDs represent the seconds and minutes.

🔹 Time Adjustment Button

A single SMD push button is connected to the INT1 pin of the ATmega328P. It’s used to adjust or set the time manually. When pressed, it triggers an interrupt that puts the microcontroller into time-setting mode.

🔹 Clock Crystal & Capacitors

To keep the ATmega328P running precisely, a 16 MHz SMD crystal is connected to its XTAL1 and XTAL2 pins, along with two 20 pF capacitors to ground.

For stable power delivery, I added three decoupling capacitors:

  1. 10 µF electrolytic capacitor for bulk filtering
  2. 1 µF ceramic capacitor for mid-frequency noise
  3. 100 nF ceramic capacitor close to the IC for high-frequency noise suppression

These capacitors help keep the circuit stable and reduce fluctuations in the power supply, especially important when driving many LEDs simultaneously.

🔹 Power and Stability

The entire circuit is powered directly from a 3.7 V, 150 mAh Li-ion battery.

This compact battery provides enough capacity for more than one full day. The ATmega328P and DS3231 both operate reliably at this voltage, and the LEDs are bright enough at 3.7 V without the need for a separate voltage regulator.

For safety and consistent performance, a small decoupling capacitor across the battery terminals helps absorb voltage dips when many LEDs switch simultaneously.

💡 Note: I designed the schematic in EasyEDA, and the exported circuit image is attached below. You can open the schematic in EasyEDA to explore the connections or modify it for your own build.


PCB Design

2D_PCB1_2025-10-09.png
2D_PCB1_2025-10-09 (1).png
pcb1.png
bottom.png
3D_PCB1_2025-10-09 (1).png
3D_PCB1_2025-10-09.png

After completing the schematic, I designed a custom PCB for LumiDial in EasyEDA, focusing not only on functionality but also on aesthetic beauty and symmetry, since this is a wristwatch meant to look as elegant as it performs.

🔹 Aesthetic Layout

To achieve a clean and balanced appearance, I placed the ATmega328P microcontroller at the exact center of the PCB.

Surrounding it, I arranged:

  1. 12 blue LEDs in an inner circle to indicate the hours
  2. 60 red LEDs in an outer circle to display the minutes and seconds

This layout gives the watch a true analog-style dial look — glowing rings of light that represent time in a dynamic yet minimal way.

For an extra touch of elegance, I added gold-finish (ENIG) hour markings directly on the PCB silkscreen. These golden labels make the board look premium and help visually identify each hour position.

🔹 Component Placement

To keep the top surface neat and LED-focused, I placed all other components on the bottom side of the PCB.

This includes:

  1. DS3231MZ+ RTC
  2. 16 MHz crystal and capacitors
  3. 10 µF, 1 µF, and 100 nF capacitors
  4. The SMD button switch
  5. Power input pads

By keeping the support circuitry underneath, the top face of the watch remains sleek and symmetrical — ideal for display and photography.

🔹 Current-Limiting Resistors

I used eight 470 Ω SMD resistors to limit current through the LEDs.

These resistors are arranged in a square pattern around the central MCU, not only for electrical convenience but also to maintain the geometric harmony of the design.

🔹 Programming Interface

To program the ATmega328P directly on the board, I included a 6-pin gold-plated programming pad on the PCB’s bottom side.

The pins are arranged in a 2.54 mm spaced row with the following connections:

  1. MISO
  2. MOSI
  3. SCK
  4. RST
  5. GND
  6. VCC

Instead of using a bulky header, these pads are designed for a pogo pin clip, allowing quick and reliable connections for uploading code or updating firmware without affecting the watch’s compact form factor.

🔹 Final Touches

The PCB was designed as a two-layer board to maintain routing clarity and reduce interference between LED rows and columns.

Special care was taken to keep all traces symmetrical and evenly spaced to match the visual flow of the LED rings.

Once the layout was finalized, I generated Gerber files and ordered the board with a matte black solder mask and ENIG gold finish, which gives the LumiDial a professional and luxurious look.

💡 Note: I designed and previewed the PCB in EasyEDA’s 3D viewer, which helped visualize the final look of the board before manufacturing. The image below shows the final PCB layout.

PCB Assembly and Soldering

watch-face.jpg
breaking.jpg
font.jpg
watch-pcb.jpg
watcg-back.jpg

To make the assembly process fast, precise, and professional, I used JLCPCB’s SMT Assembly Service for the LumiDial watch.

After finalizing the PCB layout and generating the Gerber, BOM, and Pick & Place files from EasyEDA, I directly uploaded them to JLCPCB for fabrication and assembly.

🔹 JLCPCB Assembly Service

JLCPCB handled both PCB manufacturing and SMD component placement with excellent quality and precision.

They assembled all SMD parts including the ATmega328P microcontroller, DS3231MZ+ RTC, resistors, capacitors, crystal, and the SMD push button.

When I received the board, it was professionally assembled, clean, and completely functional — no missing components or misalignments.

The solder joints were shiny and perfect, and all components were positioned exactly as designed. The overall build quality exceeded expectations and gave the project a truly factory-made feel.

🔹 Manual Soldering

Since all SMD parts were already assembled by JLCPCB, I only had to solder a few external parts manually:

  1. The 3.7 V Li-ion battery (150 mAh)
  2. A 2-pin magnetic pogo pad for charging the battery

The magnetic charging connector makes it easy to recharge the watch without opening the case — just snap the magnetic cable onto the pads, and it starts charging.

I used a fine-tip soldering iron and low-temperature solder for these connections to avoid heat damage to the nearby components.

🔹 Final Check

After soldering, I carefully inspected all solder joints under a magnifier and cleaned the flux residue with isopropyl alcohol.

Then I connected a pogo pin programming clip to the gold pads on the bottom side of the board to upload the firmware. The watch powered up immediately, and all 72 LEDs lit up beautifully in the expected pattern.

💡 Tip: If you plan to get your board assembled by JLCPCB, make sure to clearly mark top and bottom layers in EasyEDA, and verify component orientation in their online preview before placing the order.


Programming the Watch

IMG_2298.jpeg
IMG_2299.jpeg
program1.jpg
program2.jpg
program3.jpg
IMG_2300.jpeg

Once the PCB assembly was complete, the next step was to upload the firmware into the ATmega328P microcontroller.

Since I included a 6-pin gold-plated programming pad on the PCB, I was able to program the board without any connector — using a pogo pin clip instead.

🔹 Programming Setup

The six gold pads on the bottom of the PCB are arranged in a 2.54 mm spaced row, with the following pin order:

  1. MISO
  2. MOSI
  3. SCK
  4. RST
  5. GND
  6. VCC

These pads are actually an SPI programming header, which method works perfectly for boards without a USB interface and gives you full control over fuse settings and bootloader options through the MiniCore board package.

For quick connection, I used a magnetic pogo pin clip, which securely touches the gold pads and allows hassle-free uploading — no soldering or plugging required.

🔹 Preparing the Arduino IDE

I programmed the LumiDial using the Arduino IDE, which provides an easy way to compile and upload sketches to the ATmega328P.

  1. Open Arduino IDE
  2. Install MiniCore

(Install via: Tools BoardBoards Manager → Search “MiniCore” → Install)

🔹 Set Up the Arduino UNO as an ISP Programmer

  1. Open the Arduino IDE.
  2. Go to File → Examples → 11.ArduinoISP → ArduinoISP.
  3. Select:
  4. Board: Arduino UNO
  5. Port: the COM port of your UNO
  6. Click Upload to load the ISP firmware onto the UNO.
  7. After upload, your UNO is ready to act as an ISP programmer.

🔹 Connect the Arduino UNO to the LumiDial

LumiDial board has six gold-plated pads for SPI programming. Use the pogo-pin adapter to connect them to the Arduino UNO as follows:


LumiDial → Function → Arduino UNO Pin
--------------------------------------------------------------
VCC → Power (5V) → 5V
GND → Ground → GND
MOSI → Master Out Slave In → D11
MISO → Master In Slave Out → D12
SCK → Serial Clock → D13
RST → Reset → D10

Notes:

  1. Always connect GND between both boards.
  2. Make sure your LumiDial board voltage matches the UNO output (usually 5 V).
  3. You can use pogo pins or a small jig to make firm contact with the pads.

🔹 Configure the MiniCore Board Settings

In Arduino IDE → Tools, select the following:

  1. Board: ATmega328 (MiniCore)
  2. Clock: (Select according to your design — usually 8 MHz internal or 16 MHz external)
  3. BOD: Disabled (optional)
  4. EEPROM: Retain EEPROM
  5. Compiler LTO: Enabled
  6. Variant: 328P
  7. Bootloader:
  8. Yes → if you want serial upload later
  9. No → for direct SPI upload (recommended for LumiDial)
  10. Programmer: Arduino as ISP

🔹 Uploading the Code

Now you’re ready to flash your LumiDial code:

  1. Hold Shift and click the Upload button
  2. (or choose Sketch → Upload Using Programmer)
  3. Wait until you see “Done Uploading” in the IDE.

That’s it! Your LumiDial watch firmware is now programmed directly into the ATmega328P.

If everything is connected properly, the sketch will upload in a few seconds. Once done, the watch will automatically start running, displaying time using the red and blue LEDs.

🔹 Testing After Upload

After successful programming:

  1. The blue LEDs should light up at hour positions.
  2. The red LEDs will indicate the minute and second progression.
  3. Pressing the SMD button will enter time-adjustment mode (if implemented in your code).

You can easily tweak LED brightness, update the animation, or add power-saving modes by modifying the sketch.

💡 Tip: For best results, keep the Li-ion battery connected while uploading the code — it ensures stable voltage and prevents resets during programming.


Arduino Code I developed for the LumiDial is as follows:

#include <DS3231M.h>

DS3231M_Class DS3231M;

const int button_pin = 2;

const int anode[] = {0, 1, 17, 3, 4, 5, 6, 7, 8};
const int cathode[] = {9, 10, 11, 12, 13, 14, 15, 16};

//dinamically calculate number of elements in a array
const int rows = sizeof(anode) / sizeof(anode[0]);
const int cols = sizeof(cathode) / sizeof(cathode[0]);

const int totalLEDs = 60;

int minute;
int second;
int hour;

int sec_row;
int sec_col;
int min_row;
int min_col;

volatile bool wakeUp = false;
unsigned long buttonPressTime = 0;

void wake_up()
{
wakeUp = true;
}

void setup() {
//DateTime(F(__DATE__), F(__TIME__))
for(int i=0; i<18; i++){
pinMode(i, OUTPUT);
}
pinMode(button_pin, INPUT_PULLUP);
//attachInterrupt(0, wake_up, LOW);
//Serial.begin(9600);
while (!DS3231M.begin()) // Initialize RTC communications
{
//Serial.println("Not found");
//delay(1000);
}
DS3231M.adjust(DateTime(2025, 7, 22, 12, 0, 0)); // Set to specific Date/Time

}

void loop() {
DateTime now = DS3231M.now();
hour = now.hour();
minute = now.minute();
second = now.second();
// Light second, minute, and hour hands briefly
turnOffAllLEDs();
lightSecondLED(second);
delayMicroseconds(200);
turnOffAllLEDs();
lightMinuteLED(minute);
delayMicroseconds(200);
turnOffAllLEDs();
lightHourLED(hour);
delayMicroseconds(1);

//reset the time at 12 on button press
if(digitalRead(button_pin) == LOW) {
DS3231M.adjust(DateTime(2025, 7, 22, 12, 0, 0));
/*
buttonPressTime = millis();
while (digitalRead(button_pin) == LOW); // wait for release
unsigned long pressDuration = millis() - buttonPressTime;

if (pressDuration > 1500) {
// reset time on long press
DS3231M.adjust(DateTime(2025, 7, 22, 6, 45, 30));
}
else{
// Sleep if short press
//goToSleep();
}
*/
}
}

void lightSecondLED(int index) {
sec_row = index / cols; // anode index
sec_col = index % cols; // cathode index
// Light only the current LED
digitalWrite(anode[sec_row], HIGH);
digitalWrite(cathode[sec_col], LOW);
}

void lightMinuteLED(int index) {
min_row = index / cols; // anode index
min_col = index % cols; // cathode index
// Light only the current LED
digitalWrite(anode[min_row], HIGH);
digitalWrite(cathode[min_col], LOW);
}

void lightHourLED(int index) {
if(index>12) index = index - 12;
if(index<4 || index == 12){
digitalWrite(7, HIGH);
digitalWrite(8, LOW);
if(index==1)digitalWrite(cathode[5], LOW);
else if(index==2)digitalWrite(cathode[6], LOW);
else if(index==3)digitalWrite(cathode[7], LOW);
else if(index==12)digitalWrite(cathode[4], LOW);
}
else if(index>=4 && index<12){
digitalWrite(8, HIGH);
digitalWrite(7, LOW);
digitalWrite(cathode[index-4], LOW);
}
}

void lightOneLED(int index) {
int row = index / cols; // anode index
int col = index % cols; // cathode index
// Light only the current LED
digitalWrite(anode[row], HIGH);
digitalWrite(cathode[col], LOW);
}

void turnOffAllLEDs() {
for (int i = 0; i < rows; i++) digitalWrite(anode[i], LOW);
for (int j = 0; j < cols; j++) digitalWrite(cathode[j], HIGH);
}

void goToSleep() {
delay(100); // Let serial flush
wakeUp = false;
LowPower.powerDown(SLEEP_FOREVER, ADC_OFF, BOD_OFF);
}

Downloads

Testing and Calibration

IMG_2303.jpeg
dial1.jpg
dial2.jpg
efco.jpg

After programming the LumiDial watch, the next step is to test and calibrate the circuit to ensure everything is working perfectly — from LED operation to accurate timekeeping by the RTC.

This is the stage where the watch comes to life, showing its beautiful analog-style LED pattern for the first time.

🔹 Initial Power-On

After uploading the firmware and connecting the Li-ion battery, the watch powers on immediately.

If everything is working correctly:

  1. The blue LEDs will light up at the hour positions.
  2. The red LEDs will begin to move around the outer circle, representing the minutes and seconds.

If no LEDs light up, double-check the battery polarity and ensure the programming upload completed successfully.

🔹 LED Function Test

To verify the LED matrix wiring:

  1. Use a simple LED test sketch that lights each LED one by one.
  2. Observe whether all 72 LEDs illuminate properly.
  3. Check for any mismatched or dim LEDs — this can indicate reversed polarity, soldering issues, or a faulty resistor connection.

Thanks to the JLCPCB assembly, all SMD components are perfectly soldered, so most issues (if any) are usually related to LED placement or matrix mapping in the code.

🔹 RTC Verification

The DS3231MZ+ RTC is factory-calibrated for accuracy, but it’s a good idea to verify it once:

  1. After setting the time through your sketch or button, let the watch run for several hours.
  2. Compare the time displayed on LumiDial with a reference clock (like your phone or PC).
  3. The difference should be less than a second per day, confirming proper RTC communication and timing stability.

If the time drifts, recheck the I²C connections or update the RTC using your sketch’s set-time function.

🔹 Time Adjustment Button

The single SMD button connected to the INT1 pin allows you to enter time-setting mode:

  1. Short press: Increment the hour or minute (depending on your firmware).
  2. Long press: Switch between hour and minute settings.

This simple control system makes time calibration quick and intuitive, without needing any external buttons or switches.

🔹 Power and Battery Runtime

During testing, monitor the battery performance:

  1. At full charge, the 150 mAh Li-ion battery powers LumiDial for more than one full day of continuous operation.
  2. You can recharge it easily through the 2-pin magnetic charging pad without removing the battery or opening the case.

This makes it convenient to test different firmware versions or LED animations repeatedly without worrying about re-soldering connections.

🔹 Final Checks

Before closing this stage:

  1. Confirm that all LEDs respond correctly to time changes.
  2. Verify that the RTC keeps time accurately.
  3. Ensure that the charging pads and button work smoothly.

Once these are done, your LumiDial circuit is fully tested, calibrated, and ready for final assembly into the case.

💡 Tip: If you notice minor timing drift, you can fine-tune it in code by adjusting the RTC calibration registers or adding a correction factor in your sketch.


🧠 Power Optimization Update

In the first version of the LumiDial wristwatch, the ATmega328P microcontroller was running at 16 MHz using an external crystal, which allowed the watch to operate for around 30 hours on a full charge. However, for a wristwatch that continuously drives LEDs and reads time from the RTC, power efficiency is critical. To extend the battery life, I re-optimized the firmware and hardware configuration. The system clock was reduced from 16 MHz external to 2 MHz internal, which immediately lowered the overall current consumption of the microcontroller. In addition, I turned off all unused peripherals—such as the ADC, UART, SPI (used only during programming), and extra timers—by configuring the Power Reduction Register. This approach kept only the I²C interface active for RTC communication and the digital I/O pins for LED control. With these optimizations, the LumiDial consumes significantly less power, resulting in a much longer runtime per charge without affecting its timekeeping accuracy or LED animation performance.


Following is my optimized code:

#include <DS3231M.h>
#include <avr/power.h>
#include <avr/io.h>

DS3231M_Class DS3231M;

const int button_pin = 2;

// LED matrix pins
const int anode[] = {0, 1, 17, 3, 4, 5, 6, 7, 8};
const int cathode[] = {9, 10, 11, 12, 13, 14, 15, 16};

const int rows = sizeof(anode) / sizeof(anode[0]);
const int cols = sizeof(cathode) / sizeof(cathode[0]);

int hour, minute, second;
int sec_row, sec_col, min_row, min_col;
volatile bool wakeUp = false;
int hour_count = 0, adjusted_hour = 0;

void setup() {
// ---------- Disable Unused Peripherals ----------
power_adc_disable(); // Disable Analog-to-Digital Converter
power_usart0_disable(); // Disable Serial
power_timer1_disable(); // Disable 16-bit Timer1
power_timer2_disable(); // Disable 8-bit Timer2
power_spi_disable(); // Disable SPI (only used for programming)
// Keep I2C (TWI) enabled for DS3231M RTC

// ---------- Pin Initialization ----------
for (int i = 0; i < rows; i++) {
pinMode(anode[i], OUTPUT);
digitalWrite(anode[i], LOW); // Default low to save power
}
for (int j = 0; j < cols; j++) {
pinMode(cathode[j], OUTPUT);
digitalWrite(cathode[j], HIGH); // Default high (turn off LEDs)
}

pinMode(button_pin, INPUT_PULLUP);

// ---------- Initialize RTC ----------
while (!DS3231M.begin()) {
// Wait until RTC is found (no Serial printing for power saving)
}

// Set RTC time once if needed (comment out after first run)
//DS3231M.adjust(DateTime(2025, 7, 22, 6, 0, 0));
}

void loop() {
DateTime now = DS3231M.now();
hour = now.hour();
minute = now.minute();
second = now.second();

// Refresh display
turnOffAllLEDs();
lightSecondLED(second);
//delayMicroseconds(200);
delayMicroseconds(100);

turnOffAllLEDs();
lightMinuteLED(minute);
//delayMicroseconds(200);
delayMicroseconds(100);

turnOffAllLEDs();
lightHourLED(hour);
//delayMicroseconds(1);
delayMicroseconds(1);

// Reset time on button press, only hour can be adjusted
// minute and second starts from zero
if (digitalRead(button_pin) == LOW) {
hour_count += 1;
delay(200);
if(hour_count>12) hour_count = 1;
adjusted_hour = hour + hour_count;
DS3231M.adjust(DateTime(2025, 7, 22, adjusted_hour, 0, 0));
hour_count = 0;
}
}

// ---------- LED Control Functions ----------
void lightSecondLED(int index) {
sec_row = index / cols;
sec_col = index % cols;
digitalWrite(anode[sec_row], HIGH);
digitalWrite(cathode[sec_col], LOW);
}

void lightMinuteLED(int index) {
min_row = index / cols;
min_col = index % cols;
digitalWrite(anode[min_row], HIGH);
digitalWrite(cathode[min_col], LOW);
}

void lightHourLED(int index) {
if (index > 12) index -= 12;

if (index < 4 || index == 12) {
digitalWrite(7, HIGH);
digitalWrite(8, LOW);
if (index == 1) digitalWrite(cathode[5], LOW);
else if (index == 2) digitalWrite(cathode[6], LOW);
else if (index == 3) digitalWrite(cathode[7], LOW);
else if (index == 12) digitalWrite(cathode[4], LOW);
} else if (index >= 4 && index < 12) {
digitalWrite(8, HIGH);
digitalWrite(7, LOW);
digitalWrite(cathode[index - 4], LOW);
}
}

void turnOffAllLEDs() {
for (int i = 0; i < rows; i++) digitalWrite(anode[i], LOW);
for (int j = 0; j < cols; j++) digitalWrite(cathode[j], HIGH);
}

Assembly in Watch Case

dial3.jpg
dial4.jpg
dial5.jpg
dial6.jpg

Instead of using a 3D-printed enclosure, I chose a ready-made stainless steel wristwatch case for assembling the LumiDial circuit.

This gives the project a premium and durable finish, just like a commercial smartwatch, while maintaining the handmade DIY spirit.

🔹 Choosing the Watch Case

To fit the LumiDial PCB perfectly, the inner diameter of the watch dial must be exactly 40 mm.

This dimension matches the circular PCB design — the board sits snugly inside the case without any gaps or need for additional spacers.

A stainless steel case not only looks elegant but also provides good mechanical strength and heat resistance during soldering.

It also enhances the overall visual appeal, complementing the gold-finished PCB and glowing LED dial beautifully.

🔹 Placing the PCB

After testing and calibration, I carefully placed the assembled PCB inside the 40 mm stainless steel watch case.

Make sure the LED side faces outward, properly aligned with the glass window of the case so that the LED rings are centered and evenly visible from the front.

The fit should be tight enough that the PCB stays in place without wobbling. If needed, a thin rubber or plastic ring can be used as an insulator between the PCB edge and the metal body.

🔹 Battery Connection

Next, I soldered the 3.7 V, 150 mAh Li-ion battery to the designated pads on the PCB.

Keep the battery wires short and neatly routed to avoid interference with the case closing.

Once connected, the circuit powers up, and the LED clock display activates inside the watch — giving the first complete preview of LumiDial in its final form.

Enabling Magnetic Charging

C0.jpg
C1.jpg
C2.jpg
C3.jpg
C4.jpg
C5.jpg
C6.jpg

This is an update

🔹 Magnetic Charging Connector Installation

For convenient recharging, I used a 2-pin magnetic charging connector that attaches externally to the back of the watch.

To integrate it cleanly with the metal case:

  1. I measured the exact outline of the magnetic connector on the back side of the stainless steel case.
  2. Using a laser cutter, I cut a precise opening according to those measurements.
  3. The magnetic connector was then inserted and fixed securely into the opening.
  4. Finally, I soldered its two contact pins to the battery pads on the PCB, ensuring proper polarity.

This setup allows the watch to be charged externally — just by snapping the magnetic cable onto the back of the case — without opening it or disconnecting the battery.

🔹 Final Fit and Finish

After all connections were made:

  1. I cleaned the inside of the glass cover to remove dust or fingerprints.
  2. I closed the back cover carefully, ensuring the magnetic connector sat flush with the steel surface.
  3. The result is a compact, professional-looking wristwatch that blends handcrafted electronics with a real watch body.

When powered on, the red and blue LEDs glow through the front glass in a beautiful analog-style pattern — turning LumiDial into a functional, stylish piece of wearable tech.

💡 Tip: When selecting your own case, always verify the internal clearance for both the PCB and the battery thickness. A 40 mm inner diameter case with at least 8–10 mm depth works perfectly for LumiDial.


Preparing the Charger

C01.jpg
cc1.jpg
cc2.jpg
cc3.jpg
cc4.jpg

I built a custom two-pin magnetic pogo connector combined with a TP4056 charging module. To make it look neat and durable, I designed a small protective enclosure in Tinkercad and 3D-printed it. The enclosure holds the pogo pins firmly in place and aligns them perfectly with the charging pads on the watch. It also provides a clean finish and protects the solder joints from bending or shorting. Inside the case, I connected the pogo pins to the TP4056 module using thin flexible wires, ensuring correct polarity between the BAT+ and BAT– terminals. After assembling, I sealed the connector in the 3D-printed shell, giving it a compact and professional appearance. Now, whenever I need to charge the watch, I simply snap the magnetic connector onto the back, and the watch begins charging instantly with the TP4056 LED showing the charging status.

Result and Final Demonstration

IMG_2361.jpg
f1.jpg
IMG_2349.jpg

After completing all the assembly steps, LumiDial finally came to life — glowing elegantly through the glass window of the stainless steel case.

The result is a fully functional, analog-style LED wristwatch that combines precision electronics, aesthetic design, and wearable craftsmanship in one compact build.

🔹 The Final Look

When powered on, the 12 blue LEDs illuminate the hour positions, while the 60 red LEDs around the outer ring display the minutes and seconds.

The LEDs form a clean, circular analog clock layout, with smooth transitions that mimic the motion of traditional watch hands — but in a vibrant, modern form.

Thanks to the matte-black PCB, gold-finished markings, and stainless steel body, the final appearance is both minimal and luxurious.

The symmetry of the layout — with the ATmega328P at the center and resistor squares around it — makes the whole dial look balanced and artistic, even when the LEDs are off.

🔹 Performance and Accuracy

Powered by the DS3231MZ+ RTC, the watch maintains excellent time accuracy, with less than a second drift per month!

The ATmega328P handles LED multiplexing and timekeeping efficiently, consuming very little power when idle.

The 150 mAh Li-ion battery provides more than 24 hours of continuous operation, and charging is effortless using the magnetic 2-pin connector mounted on the back of the case.

Simply snap the charging cable in place — no need to open or disassemble the watch.

🔹 Everyday Usability

  1. The single SMD button makes time adjustment easy and intuitive.
  2. The bright SMD LEDs are visible even under moderate light conditions.
  3. The entire build is compact, comfortable, and stylish enough for daily wear.

Whether on your wrist or as a desk clock, LumiDial stands out as a unique blend of art and engineering.

🔹 Reflection

This project was designed with both technical precision and aesthetic value in mind.

From schematic design in EasyEDA, to JLCPCB’s professional assembly, to the final stainless steel case integration, every step was focused on achieving a clean, functional, and beautiful result.

The LumiDial demonstrates how a custom PCB, thoughtful component arrangement, and creative presentation can transform a simple microcontroller project into a wearable piece of art.

💡 Tip: You can modify the firmware to display animations, special effects, or even include temperature data from the DS3231 for added features.