An open-source ESP32-S3-based smartwatch with RTC, I2C display, buzzer, LEDs, and battery monitoring. Designed using KiCad, it features a compact PCB layout, Li-Po battery support, and USB charging
Loading README and project media…
A compact, open-source smartwatch powered by the ESP32-S3-WROOM with real-time clock, battery monitoring, and USB charging.
The Schrödinger Watch is an ESP32-S3-based open-source smartwatch designed with a focus on compact PCB layout, low power consumption, and modular features. It integrates RTC, I2C display, battery monitoring, and a USB charging circuit, making it a versatile platform for wearable tech enthusiasts.
| Feature | Description |
|---|---|
| Microcontroller | ESP32-S3-WROOM (40-pin) |
| Display | I2C OLED |
| RTC Module | DS3231 (with alarm) |
| Buttons | 3 push buttons (pull-up) |
| Buzzer | Included for alarms and notifications |
| Battery | 3.7V Li-Po battery |
| Charging Circuit | TP4056 for Li-Po charging |
| Battery Monitoring | Voltage divider for ADC measurement |
| USB Communication | CP2102 USB programmer |
| Power Switching | *P-MOSFET for auto power control |
| Protection Circuit | Schottky diode for USB protection |
The smartwatch is designed with SMD components for compactness. Below is the pin mapping:
| Component | ESP32 GPIO | Function |
|---|---|---|
| OLED SDA | GPIO 20 | I2C SDA |
| OLED SCL | GPIO 21 | I2C SCL |
| RTC SDA | GPIO 20 | I2C SDA |
| RTC SCL | GPIO 21 | I2C SCL |
| RTC Alarm | GPIO 11 | SQW/INT to ESP32 |
| Battery ADC | GPIO7 | Voltage divider to ESP32 Analog Pin |
| LED | GPIO 2 | Status Indication |
| LED | GPIO 3 | Status Indication |
| LED | GPIO 4 | Status Indication |
| Push Button 1 | GPIO 12 | User Input |
| Push Button 2 | GPIO 13 | User Input |
| Push Button 3 | GPIO 22 | User Input |
This project was proudly sponsored by PCBWay.
Their support in fabricating the custom PCB for the Schrödinger Watch has been invaluable. The quality, precision, and delivery speed were exceptional — and I’m extremely grateful for their contribution to the maker and open-source community.
If you're looking for reliable PCB prototyping, assembly, or 3D printing services, I highly recommend PCBWay.
The Schrödinger Watch PCB was designed using KiCad. The schematic consists of:
PCB Highlights:
Schrödinger Watch ⌚ – ESP32-S3 DIY Smartwatch
This is the Schrödinger Watch, a DIY smartwatch powered by the ESP32-S3-WROOM. It's a fully open-source hardware project, designed and assembled from scratch, with a focus on learning, hacking, and creativity.
⚠️ Note: This is Rev 1 of the hardware. While functional, it contains some known hardware issues listed below. A refined Rev 2 is under development and will be released by September 2025 with additional features and improved reliability.
These are hardware issues identified after assembly and testing:
Missing CE Connection on TP4056:
AMS1117 3.3V LDO Lacks Input/Output Capacitors:
No Pull-Down Resistors for Pushbuttons:
Soldering Considerations:
Rev 2 will be a major update with all hardware issues addressed and new features, including:
📌 Disclaimer
This is a learning-oriented DIY project and should not be considered a finished consumer product. Use with care and contribute to make it better!
| Component | Quantity | Specification |
|---|---|---|
| ESP32-S3-WROOM | 1 | 40-pin module |
| OLED Display | 1 | I2C, 128x64 |
| DS3231 RTC | 1 | Real-time clock module |
| Li-Po Battery | 1 | 3.7V, 500mAh |
| TP4056 Module | 1 | Battery charger |
| CP2102 | 1 | USB-to-serial |
| Buzzer | 1 | 3V piezo |
| Push Buttons | 3 | Momentary switch |
| Resistors & Capacitors | Various | SMD components |
The firmware is written in Arduino using the ESP32 library. It supports:
Press and hold the power button. The watch will display the time, battery status, and active alarms.
Use the serial monitor to set the time in RTC using setTime().
Battery percentage is displayed on-screen and can be accessed through the serial monitor.
The RTC alarm triggers a buzzer sound at the set time.
🛠️ Libraries Used
Install via Arduino Library Manager or PlatformIO.
🚧 Known Hardware Issues (Rev 1)
INPUT_PULLDOWN in firmware)The current version of the firmware is a minimal working build to demonstrate the core functionality of the Schrödinger Watch. Several features are not yet implemented:
These features will be added in the next firmware updates as part of the development toward Rev 2 and in between the current development , revision 2 of this watch expected by September 2025.
#include <Wire.h>
#include <U8g2lib.h>
#include <RTClib.h>
// this code works but to be honest there is a lot of places to improve , like switch are just interfaced but not given any function , but can be done like to set time etc etc ......
// all issues will be fixed as a progress please bare with me , but if you have the knowledge then happy to recieve help
// I2C Pins
#define SDA_PIN 20
#define SCL_PIN 21
// GPIO Definitions
#define LED_PIN 2
#define BATTERY_ADC 7
#define RTC_ALARM_PIN 11
#define BUTTON1 12
#define BUTTON2 13
#define BUTTON3 14
U8G2_SSD1306_128X64_NONAME_F_HW_I2C u8g2(U8G2_R0, U8X8_PIN_NONE);
RTC_DS3231 rtc;
void setup() {
Serial.begin(115200);
Wire.begin(SDA_PIN, SCL_PIN);
u8g2.begin();
pinMode(LED_PIN, OUTPUT);
pinMode(RTC_ALARM_PIN, INPUT);
pinMode(BATTERY_ADC, INPUT);
pinMode(BUTTON1, INPUT_PULLDOWN);
pinMode(BUTTON2, INPUT_PULLDOWN);
pinMode(BUTTON3, INPUT_PULLDOWN);
if (!rtc.begin()) {
u8g2.clearBuffer();
u8g2.setFont(u8g2_font_ncenB08_tr);
u8g2.drawStr(0, 20, "RTC Not Found");
u8g2.sendBuffer();
while (1);
}
if (rtc.lostPower()) {
rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));
}
u8g2.clearBuffer();
u8g2.setFont(u8g2_font_6x10_tr);
u8g2.drawStr(0, 10, "Schrodinger Watch");
u8g2.sendBuffer();
delay(1000);
}
void loop() {
DateTime now = rtc.now();
char timeStr[9];
sprintf(timeStr, "%02d:%02d:%02d", now.hour(), now.minute(), now.second());
float batteryVoltage = analogRead(BATTERY_ADC) * (3.3 / 4095.0) * 2; // Adjust based on divider
char voltStr[10];
dtostrf(batteryVoltage, 4, 2, voltStr);
u8g2.clearBuffer();
u8g2.setFont(u8g2_font_logisoso38_tr);
u8g2.drawStr(0, 50, timeStr);
u8g2.setFont(u8g2_font_6x10_tr);
u8g2.drawStr(0, 62, ("BAT: " + String(voltStr) + "V").c_str());
u8g2.sendBuffer();
digitalWrite(LED_PIN, !digitalRead(LED_PIN));
if (digitalRead(BUTTON1)) Serial.println("Button 1 Pressed");
if (digitalRead(BUTTON2)) Serial.println("Button 2 Pressed");
if (digitalRead(BUTTON3)) Serial.println("Button 3 Pressed");
delay(1000);
}
We welcome contributions! If you’d like to improve the watch, please:
This project is licensed under the MIT License. Feel free to use, modify, and distribute it with proper attribution.
Special thanks to the open-source hardware community for inspiring this project!