Time Since Wedding – E-Paper Clock is a custom clock I built as a wedding gift for my friend.Instead of displaying the current time, this clock shows how much time has passed since the wedding, measured in hours and days.
The goal of this project was to create something meaningful, minimal, and long-lasting.By using an e-paper display, the clock stays visible at all times while consuming very little power, making it perfect for a desk or shelf.
The clock connects to Wi-Fi, synchronises time from the internet, and updates itself automatically every hour.
How the Clock WorksWhen the device powers on for the first time, it creates its own Wi-Fi hotspot.The user connects to this hotspot using a phone or laptop and opens a configuration page in a web browser.SSID = WeddingClock_Setup
PASS = 12345678
From this page, the user selects their home Wi-Fi network and enters the password.Once connected, the device synchronizes the current time using an NTP server.
The wedding date and time are stored in the firmware.After syncing the time, the clock calculates how many hours and days have passed since the wedding and displays the result on the e-paper screen.
If the device cannot connect to the saved Wi-Fi network, it automatically reopens the setup mode so the user can reconfigure it easily.
Hardware UsedMain components used in this project:
- Seeed Studio XIAO ESP32-C3
- 2.9-inch monochrome e-paper display
I also used my custom adapter PCB for XIAO ESP32C3
The XIAO ESP32-C3 was chosen for its small size, built-in Wi-Fi, and low power consumption, making it ideal for always-on display projects.
Enclosure and 3D PrintingI used Fusion 360 to design the enclosure for this project. Then, I exported STL files for 3D printing.
The enclosure for the Time Since Wedding – E-Paper Clock was 3D printed using JLC3DP’s 3D printing service.
The design is simple and minimal to match the clean look of the e-paper display.JLC3DP offers multiple materials and finishes, allowing the enclosure to feel solid and look professional.
Get your 3d print now https://jlc3dp.com/?from=gokul
Assembaly1. Solder the XIAO to the PCB adapter
2. Connect the XIAO to the E-Paper module by following the wiring diagram provided. You can also see the battery connection in this diagram. If you want to power this project with a battery, you can add it by following this wiring guide. Alternatively, if you only need to power the project via USB, you can proceed with that option as well.
3. Install the eink module into the display frame by securing it with M2 5mm screws.
4. Secure the XIAO PCB using M3 screws.
5. Install the antenna
6. Add some glue and close it off
7. Connect it to the PC for programming and powering.
Here is the full code for this project
#include <WiFi.h>
#include <WebServer.h>
#include <Preferences.h>
#include <time.h>
#include <GxEPD2_BW.h>
#include <Fonts/FreeMonoBold18pt7b.h>
#include <Fonts/FreeMonoBold12pt7b.h>
// ================= E-PAPER PINS =================
#define CS_PIN D1
#define DC_PIN D3
#define RST_PIN D0
#define BUSY_PIN D5
GxEPD2_BW<GxEPD2_290_BS, GxEPD2_290_BS::HEIGHT> display(
GxEPD2_290_BS(CS_PIN, DC_PIN, RST_PIN, BUSY_PIN)
);
// ================= WIFI =================
WebServer server(80);
Preferences prefs;
const char* apSSID = "WeddingClock_Setup";
const char* apPASS = "12345678";
unsigned long lastHourShown = 0;
uint8_t refreshCount = 0; // for ghosting control
// ================= HEART BITMAP =================
// 15x16 monochrome heart
const unsigned char image_cards_hearts_bits[] PROGMEM = {
0x1C, 0x38,
0x3E, 0x7C,
0x7F, 0xFE,
0xFF, 0xFF,
0xFF, 0xFF,
0x7F, 0xFE,
0x3F, 0xFC,
0x1F, 0xF8,
0x0F, 0xF0,
0x07, 0xE0,
0x03, 0xC0,
0x01, 0x80,
0x00, 0x00,
0x00, 0x00,
0x00, 0x00,
0x00, 0x00
};
// ================= WEDDING TIME =================
// Oct 19, 2025 – 6:15 AM IST → 00:45 UTC
time_t getWeddingEpochUTC() {
struct tm t = {};
t.tm_year = 2025 - 1900;
t.tm_mon = 9;
t.tm_mday = 19;
t.tm_hour = 0;
t.tm_min = 45;
t.tm_sec = 0;
t.tm_isdst = 0;
return mktime(&t);
}
// ================= DISPLAY UI =================
void drawWeddingUI(unsigned long hoursPassed, unsigned long daysPassed) {
char hrsBuf[20];
char daysBuf[20];
sprintf(hrsBuf, "%09lu Hrs", hoursPassed);
sprintf(daysBuf, "%09lu Dys", daysPassed);
bool fullRefresh = (refreshCount >= 6);
if (fullRefresh) {
display.setFullWindow(); // anti-ghosting
refreshCount = 0;
} else {
display.setPartialWindow(0, 0, display.width(), display.height());
refreshCount++;
}
display.firstPage();
do {
display.fillScreen(GxEPD_WHITE);
display.setTextColor(GxEPD_BLACK);
display.setTextWrap(false);
// Hours
display.setFont(&FreeMonoBold18pt7b);
display.setCursor(10, 73);
display.print(hrsBuf);
// Days
display.setCursor(10, 112);
display.print(daysBuf);
// Names
display.setFont(&FreeMonoBold12pt7b);
display.setCursor(56, 31);
display.print("Arjun");
display.setCursor(152, 31);
display.print("Amgitha");
// Heart
display.drawBitmap(
131, 17,
image_cards_hearts_bits,
15, 16,
GxEPD_BLACK
);
} while (display.nextPage());
}
// ================= TIME COUNTERS =================
void showTimeCounters() {
time_t now;
time(&now);
time_t weddingEpoch = getWeddingEpochUTC();
if (now < weddingEpoch) {
drawWeddingUI(0, 0);
return;
}
unsigned long seconds = now - weddingEpoch;
drawWeddingUI(seconds / 3600, seconds / 86400);
}
// ================= WIFI CONFIG PAGE =================
void handleRoot() {
String page =
"<!DOCTYPE html><html><head>"
"<meta name='viewport' content='width=device-width, initial-scale=1'>"
"<style>"
"body{font-family:Arial;background:#f2f2f2;padding:20px;}"
".card{background:#fff;padding:20px;border-radius:14px;"
"max-width:400px;margin:auto;box-shadow:0 10px 25px rgba(0,0,0,.15);}"
"h2{text-align:center;}"
"select,input,button{width:100%;padding:12px;margin-top:10px;"
"border-radius:8px;border:1px solid #ccc;}"
"button{background:#000;color:#fff;font-weight:bold;}"
"</style></head><body>"
"<div class='card'><h2>Wedding Clock Wi-Fi</h2>"
"<form action='/connect'><label>Network</label><select name='ssid'>";
int n = WiFi.scanNetworks();
for (int i = 0; i < n; i++)
page += "<option value='" + WiFi.SSID(i) + "'>" + WiFi.SSID(i) + "</option>";
page +=
"</select><label>Password</label>"
"<input type='password' name='pass'>"
"<button type='submit'>Connect</button>"
"</form></div></body></html>";
server.send(200, "text/html", page);
}
void handleConnect() {
prefs.putString("ssid", server.arg("ssid"));
prefs.putString("pass", server.arg("pass"));
server.send(200, "text/html", "Connecting… Rebooting");
delay(1500);
ESP.restart();
}
// ================= WIFI LOGIC =================
bool connectToSavedWiFi() {
String ssid = prefs.getString("ssid", "");
String pass = prefs.getString("pass", "");
if (ssid == "") return false;
WiFi.begin(ssid.c_str(), pass.c_str());
unsigned long start = millis();
while (WiFi.status() != WL_CONNECTED && millis() - start < 15000) {
delay(500);
}
return WiFi.status() == WL_CONNECTED;
}
void startConfigPortal() {
WiFi.softAP(apSSID, apPASS);
IPAddress ip = WiFi.softAPIP();
display.setFullWindow();
display.firstPage();
do {
display.fillScreen(GxEPD_WHITE);
display.setFont(&FreeMonoBold12pt7b);
display.setCursor(10, 50);
display.print("Connect to:");
display.setCursor(10, 75);
display.print(apSSID);
display.setCursor(10, 100);
display.print(ip.toString());
} while (display.nextPage());
server.on("/", handleRoot);
server.on("/connect", handleConnect);
server.begin();
}
// ================= NTP =================
void syncTimeNTP() {
configTime(0, 0, "pool.ntp.org", "time.nist.gov");
time_t now;
while (time(&now) < 100000) delay(500);
}
// ================= SETUP =================
void setup() {
Serial.begin(115200);
display.init(115200, true, 50, false);
display.setRotation(1);
prefs.begin("wifi", false);
if (!connectToSavedWiFi()) {
startConfigPortal();
return;
}
syncTimeNTP();
showTimeCounters();
}
// ================= LOOP =================
void loop() {
server.handleClient();
time_t now;
time(&now);
unsigned long hour = now / 3600;
if (hour != lastHourShown) {
lastHourShown = hour;
showTimeCounters();
}
delay(1000);
}So we are done with the build
The 3D-printed enclosure turns the electronics into a polished desk object suitable as a wedding gift.
Customizing the Clock (Names and Wedding Date)This project is easy to personalize.You can customize the clock with your own names and your own wedding date and time by editing just a few lines in the code.
Changing the Names on the DisplayIn the display code, you will find the section where the names are printed
display.setFont(&FreeMonoBold12pt7b);
display.setCursor(56, 31);
display.print("Arjun");
display.setCursor(152, 31);
display.print("Amgitha");To customise the clock, simply replace the names inside the quotes
display.print("Alex");
display.print("Jamie");If your names are longer or shorter, you can adjust the cursor positions slightly to keep everything centred.
Changing the Wedding Date and TimeThe wedding date and time are defined using a struct tm, which makes it easy to edit safely.
Locate this function in the code
time_t getWeddingEpochUTC() {
struct tm t = {};
t.tm_year = 2025 - 1900;
t.tm_mon = 9; // October (0-based)
t.tm_mday = 19;
t.tm_hour = 0;
t.tm_min = 45;
t.tm_sec = 0;
t.tm_isdst = 0;
return mktime(&t);
}This example represents October 19, 2025, at 6:15 AM IST, which converts to 00:45 UTC.
Converting Your Local Time to UTCIf your wedding time is in Indian Standard Time (IST):
- IST = UTC + 5 hours 30 minutes
- Subtract 5 hours and 30 minutes from your local time
Wedding time:December 1, 2026 – 4:00 PM IST
Converted to UTC:
- 10:30 AM UTC
Updated code
t.tm_year = 2026 - 1900;
t.tm_mon = 11; // December
t.tm_mday = 1;
t.tm_hour = 10;
t.tm_min = 30;If your local time is already in UTC, you can enter it directly.
Final ResultThe final result is a low-power, always-visible Time Since Wedding clock that quietly tracks how long a marriage has lasted.
It’s simple, personal, and designed to run reliably for years with minimal maintenance.
ConclusionTime Since Wedding – E-Paper Clock is more than just a clock.It’s a small reminder of a special moment, built with care and designed to last.
Special ThanksA huge thanks to JLCPCB for fabricating the PCB and JLC3DP for supporting this project with their amazing 3D printing service.
JLC3DP is the future of manufacturing, offering a user-friendly online platform for advanced 3D printing with: ✅ Instant quoting & real-time tracking ✅ 48-hour lead time & door-to-door delivery ✅ 20+ material options ✅ Enterprise-grade quality ✅ Prices starting at just $0.3, with up to $70 in new user coupons!
✨ Try them out atJLC3DP.com#JLC3DP




_t9PF3orMPd.png?auto=compress%2Cformat&w=40&h=40&fit=fillmax&bg=fff&dpr=2)





Comments