24 Hour Sundial
According to Wikipedia sundials are among the oldest form of time telling invented, our oldest example comes from Egypt 3,500 years ago. Unfortunately a sun dial only works when the sun is up.
You may be asking yourself, what if I want to tell time at night?
Until now this was not possible with a sundial. Even better, this is a project someone with very limited electronics experience can easily complete
Supplies
[AI Image because my workbench is a mess right now]
Here's the tools and supplies I used for this project.
Software:
Fusion 360 - CAD Modeling
Cura - Chosen 3D Printer Slicer
Arduino IDE
Tools:
3D Printer
Soldering Iron (Optional)
Glue Gun
Supplies:
Arduino Uno
Real Time Clock Module
Servo Motor
Various Jumper Wires
Small Bread Board
Current Limiting Resistor (optional)
CAD Design
I wont go over this too much as everyone uses a different process and different software, if you would like to follow my project exactly I will provide the STLs further down.
Instead I will briefly cover some design considerations for someone not used to designing their own parts.
Consideration 1: Because of the necessary offset of the plane the light travels as compared to the face of the sun dial it leaves a large open area - Designing a filler part for this section may give the final product a cleaner look.
Consideration 2: This design provides an opening for a power cord to get through, however programming the board was not considered and hence a hole was not left.
Consideration 3: A thinner gimble (the needle of the dial) will produce a thinner shadow.
Consideration 4: This was designed for the Arduino uno, however utilizing a smaller board such as an ESP32 or Arduino nano may yield better results due to the reduced size of parts.
Design is an iterative process: I went through 3 different prototypes before I settled on one that is both functional and I am happy with.
Printing
To print all my parts I used an Ender 3 Pro with the Cura slicer. Total print time was roughly 7 hours, I recommend using supports for at least the face. Additionally I used 25% infill but there is not much infill on these parts to begin with.
Attached below are my STLs
Circuit
The circuit is pretty self explanatory, I chose not to use a current limiting resistor because my LED seems to do fine without it but your milage my vary, make sure you attach it to the 3.3V output rather than the 5V output if you choose not to.
This is where a soldering iron comes in handy, solder leads to the ends of the LED before connecting it to the Arduino.
A further text summary of the connections are as follows
RTC Module -> GND to GND
5V to 5V
SDA to SDA
SLC to SLC
Servo -> GND to GND
5V to 5V
Signal to digital pin 9
LED -> GND to GND
Anode (long side of LED) to 3.3V
Put It All Together
The pieces should fit together, I didn't build in any alignment tabs so i recommend building in this order:
1) Put the electronics onto the base, align power jack with base opening.
2) Glue the servo motor in place, rather than being flat on the base ensure the servo is at an angle -- the motor shaft should be near the center.
3) Attach the arm to the underside of the servo arm, I used tape but glue will provide a more permanent connection.
4) Fix the LED to the end of the arm facing towards the center of the dial
5) Turn the arm to 90 degrees, the position the arm would be at noon and place the body of the dial onto the base with the arm in the center of the notch.
WAIT! We are forgetting a step!
Programming
Here's the code I used, feel free to copy - the important part that may be specific to you is tuning the max and min angle. Some notes on the code - this assumes each hour interval would use the same amount of steps per hour though further testing this is not precisely true however it is close enough for the purposes of this project.
For a more accurate version one could take note of the degree each hour occurs at, store those data points in a array and linearly step between those points.
Code:
#include <Servo.h>
#include <Wire.h> //includes the wire.h library
#include <RTClib.h> // includes the RTC libray
const int MIN_ANGLE = 30; // start of sweep
const int MAX_ANGLE = 110; // end of sweep
const int SPAN = MAX_ANGLE - MIN_ANGLE; // 80 degrees
RTC_DS3231 rtc;
Servo sunServo; // create servo object to control a servo
// twelve servo objects can be created on most boards
int pos = 0; // variable to store the servo position
void setup() {
Serial.begin(9600); // starts the serial monitor at 9600 baud
sunServo.attach(9); // attaches the servo on pin 9 to the servo object
Serial.println("Initialize RTC module"); // prints "Initialize RTC module" in serial monitor
if (! rtc.begin()) {
Serial.println("Couldn't find RTC");
while (1);
}
if (rtc.lostPower()) {
Serial.println("RTC lost power, let's set the time!");
rtc.adjust(DateTime(F(__DATE__), F(__TIME__))); // Sets to compile time
// Or set a specific time:
// rtc.adjust(DateTime(2025, 11, 29, 18, 15, 0)); // Year, Month, Day, Hour, Minute, Second
}
}
void loop() {
DateTime now = rtc.now();
int hour = now.hour();
int minute = now.minute();
int currentMin = hour * 60 + minute; // 0–1439
// Time anchors
int t6am = 6 * 60; // 360
int t6pm = 18 * 60; // 1080
float angle;
if (currentMin >= t6am && currentMin < t6pm) {
// 6 AM → 6 PM (forward sweep: 30 → 130)
float fraction = (currentMin - t6am) / 720.0; // 0 → 1
angle = MIN_ANGLE + SPAN * fraction;
} else {
// 6 PM → 6 AM (backward sweep: 130 → 30)
int minsSince6pm;
if (currentMin >= t6pm)
minsSince6pm = currentMin - t6pm;
else
minsSince6pm = currentMin + (1440 - t6pm); // wrap midnight
float fraction = minsSince6pm / 720.0; // 0 → 1
angle = MAX_ANGLE - SPAN * fraction;
}
// Clamp (for safety)
if (angle < MIN_ANGLE) angle = MIN_ANGLE;
if (angle > MAX_ANGLE) angle = MAX_ANGLE;
sunServo.write((int)angle);
// Debug
Serial.print("Time: ");
Serial.print(hour); Serial.print(":"); Serial.print(minute);
Serial.print(" Angle: ");
Serial.println(angle);
delay(5000);
}
Finishing Touches
To finish simply secure the top and needle onto the top of the body. This is best done with the clock turned on so you can align the time correctly.