A clock using the Roman numeral system with 16 RGB LEDs.
The hours are displayed in a 12-hour format, with orange indicating a.m. and blue indicating p.m.
Briefly pressing the button changes the brightness between three levels.
By pressing the button a little longer, the display toggles between time and date. The date display automatically switches back to the time display after 10 seconds.
It enters adjustment mode by holding the button for more than 2 seconds. Time can be adjusted by pressing once, or date can be adjusted by pressing twice.
- Short button press: Increases the number.
- Long button press: Changes the unit to increase.
| Unit | Color | Range |
|---|---|---|
| Hour | Orange or Blue | 12 (as 0), 1 ~ 11; a.m./p.m. |
| Minute | Green | 0 ~ 59 |
| Year | Yellow | 25 (as 2025) ~ 40 (as 2040) |
| Month | Red | 1 ~ 12 |
| Day | Purple | 1 ~ 31 |
It returns to normal mode by holding the button for more than 2 seconds again.
- An ATtiny85
- Ring-arranged 16 WS2812Bs
- A 8 MHz crystal oscillator
- Two 10pF ceramic capacitors
- A USB connector for supplying power
- A tactile switch
- Wires, connectors, etc...
For accurate timekeeping, the CPU clock is driven by an external crystal oscillator circuit.
The current time is indicated by 16 LEDs arranged in a ring. The mapping of Roman numerals is shown as follows. The first 6 are assigned to the upper number and the remaining 10 are assigned to the lower number.
Install ATTinyCore boards to the Arduino IDE and configure the settings as follows.
| Attribute | Value |
|---|---|
| Board | ATtiny25/45/85 (No bootloader) |
| Chip | ATtiny85 |
| Clock | 8 MHz (External) |
| B.O.D. Level | B.O.D. Disabled (saves power) |
| Save EEPROM | EEPROM retained |
| Timer 1 Clock | CPU (CPU frequency) |
| LTO | Enabled |
| millis()/micros() | Enabled |
This sketch depends on following library. (You can add this by library manager)
Be careful. The external oscillator circuit is required for programming both the bootloader and the sketches.
Usually the interval between each loop() function call is 125 ms (= one eighth of a second), but it's 126 ms once every 85 loops in my case.
This may be affected by the circuit conditions.
Therefore, you should adjust the constant ADJUSTER_MAX.
These codes are licensed under MIT License.

