24 Hour Sundial

by dbishop100 in Circuits > Arduino

298 Views, 2 Favorites, 0 Comments

24 Hour Sundial

IMG_1651.jpg

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

ChatGPT Image Dec 1, 2025, 02_24_23 AM.png

[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

cad.png

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

IMG_1648.jpg

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

circuit.png

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

IMG_1644.jpg

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

code.png

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

IMG_1647.jpg

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.