How to make an analog and digital real-time clock with an OLED display

How to make an analog and digital real-time clock with an OLED display

In this project, we will learn how to make an analog and digital real-time clock with an OLED display. For this project, I used an Arduino Nano board together with an RTC module to keep accurate time even when the power is off. Also, I have added four different modes to this project. That is time, temperature, date, and an analog clock display. You can change or customize these modes as you like, depending on your needs.

For this project, I also designed a custom PCB using JLCPCB, which makes the whole setup look cleaner and more professional compared to using jumper wires. You can print PCBs with free coupons. Another good thing is that this project can be powered using a 9V battery, so you can use it as a portable desk clock or even mount it anywhere without worrying about cables.

Ok, let’s do this project step by step. The required components are given below.

Disclosure: These Amazon links are Affiliate links. As an Amazon Associate, I earn from qualifying purchases.

Step 1

Firstly, identify these components.

Step 2

Secondly, let’s order PCBs for this project.

  • Click the “Instant Quote” button and upload the Gerber file, which you can download from the link below.
  • Gerber file – Download
  • For this project, I ordered five Red PCBs. Next, select the build time and shipping method. Finally, click “Save to Cart” and complete the payment.

Step 3

Thirdly, go ahead and unbox your PCB package.

Step 4

Next, start soldering all the components onto the PCB.

Step 5

Now, insert the battery into the RTC module. After that, connect the RTC module, OLED display, and the Arduino Nano board to the PCB.

Step 6

After that, connect the Arduino Nano board to your computer. Then copy and paste the program into the Arduino IDE and enter your real date and time. And don’t forget to install the library files, or the code won’t compile.

#include <Wire.h>
#include "RTClib.h"

RTC_DS3231 rtc;

void setup() {
  Serial.begin(9600);
  Wire.begin();

  // Initialize RTC
  if (!rtc.begin()) {
    Serial.println("Couldn't find RTC");
    while (1)
      ;
  }

  rtc.adjust(DateTime(2025, 11, 19, 9, 16, 0)); 
}

void loop() {
}
  • Now, type in your real time and date. Then select the correct board and port, and finally click the upload button to upload the code.

Step 7

Next, copy and paste the main program into the Arduino IDE so we can upload it to the Arduino Nano. Also, don’t forget to install the library files, or the code won’t compile.

#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include "RTClib.h"
#include <math.h>

#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, -1);

RTC_DS3231 rtc;

#define BUTTON_PIN 2
int mode = 0;
bool lastButtonState = HIGH;
unsigned long lastDebounce = 0;

String getDayOfWeek(uint8_t day) {
  switch (day) {
    case 1: return "Mon";
    case 2: return "Tue";
    case 3: return "Wed";
    case 4: return "Thu";
    case 5: return "Fri";
    case 6: return "Sat";
    case 7: return "Sun";
  }
  return "";
}

// ------------------- LOADING SCREEN -------------------
void showLoadingScreen() {
  display.clearDisplay();
  display.setTextSize(2);
  display.setTextColor(SSD1306_WHITE);
  display.setCursor(10, 5);
  display.println("CLOCK");

  display.setTextSize(1);
  display.setCursor(28, 25);
  display.println("BOOTING...");

  display.display();

  int barX = 10, barY = 40, barW = 108, barH = 10;
  display.drawRect(barX, barY, barW, barH, SSD1306_WHITE);
  display.display();

  for (int i = 1; i <= barW - 2; i++) {
    display.fillRect(barX + 1, barY + 1, i, barH - 2, SSD1306_WHITE);
    display.display();
    delay(15);
  }
  delay(300);
}

// ------------------- DRAW ANALOG CLOCK -------------------
void drawAnalogClock(DateTime now) {
  int cx = SCREEN_WIDTH / 2;
  int cy = SCREEN_HEIGHT / 2;
  int radius = 30;

  // Draw clock circle
  display.drawCircle(cx, cy, radius, SSD1306_WHITE);

  // Draw hour marks
  for (int i = 0; i < 12; i++) {
    float angle = i * 30 * 3.14159 / 180;
    int x1 = cx + (radius - 2) * sin(angle);
    int y1 = cy - (radius - 2) * cos(angle);
    int x2 = cx + radius * sin(angle);
    int y2 = cy - radius * cos(angle);
    display.drawLine(x1, y1, x2, y2, SSD1306_WHITE);
  }

  // Calculate angles
  float secondAngle = now.second() * 6 * 3.14159 / 180;
  float minuteAngle = now.minute() * 6 * 3.14159 / 180;
  float hourAngle = ((now.hour() % 12) + now.minute() / 60.0) * 30 * 3.14159 / 180;

  // Draw hands
  // Hour hand
  int hx = cx + (radius - 12) * sin(hourAngle);
  int hy = cy - (radius - 12) * cos(hourAngle);
  display.drawLine(cx, cy, hx, hy, SSD1306_WHITE);

  // Minute hand
  int mx = cx + (radius - 6) * sin(minuteAngle);
  int my = cy - (radius - 6) * cos(minuteAngle);
  display.drawLine(cx, cy, mx, my, SSD1306_WHITE);

  // Second hand
  int sx = cx + (radius - 2) * sin(secondAngle);
  int sy = cy - (radius - 2) * cos(secondAngle);
  display.drawLine(cx, cy, sx, sy, SSD1306_WHITE);
}

// ------------------- SETUP -------------------
void setup() {
  Serial.begin(9600);
  Wire.begin();

  pinMode(BUTTON_PIN, INPUT_PULLUP);

  if (!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {
    Serial.println("OLED failed!");
    while (1);
  }

  if (!rtc.begin()) {
    Serial.println("RTC not found!");
    while (1);
  }

  showLoadingScreen();
}

// ------------------- LOOP -------------------
void loop() {
  bool reading = digitalRead(BUTTON_PIN);

  if (reading == LOW && lastButtonState == HIGH && (millis() - lastDebounce) > 200) {
    mode++;
    if (mode > 3) mode = 0;  // now 4 modes (0-3)
    lastDebounce = millis();
  }
  lastButtonState = reading;

  DateTime now = rtc.now();
  float tempC = rtc.getTemperature();

  display.clearDisplay();

  // ------------------- MODE 0: CLOCK -------------------
  if (mode == 0) {
    display.setTextSize(2);
    display.setCursor(0, 10);
    char timeBuffer[9];
    sprintf(timeBuffer, "%02d:%02d:%02d", now.hour(), now.minute(), now.second());
    display.println(timeBuffer);

    display.setTextSize(2);
    display.setCursor(0, 40);
    char dateBuffer[11];
    sprintf(dateBuffer, "%04d-%02d-%02d", now.year(), now.month(), now.day());
    display.println(dateBuffer);
  }

  // ------------------- MODE 1: TEMP + TIME -------------------
  if (mode == 1) {
    display.setTextSize(2);
    display.setCursor(0, 5);
    display.print("Tem: ");
    display.print(tempC, 1);
    display.println("C");

    display.setCursor(0, 40);
    display.setTextSize(2);
    char timeBuffer[9];
    sprintf(timeBuffer, "%02d:%02d:%02d", now.hour(), now.minute(), now.second());
    display.println(timeBuffer);
  }

  // ------------------- MODE 2: DAY + DATE -------------------
  if (mode == 2) {
    display.setTextSize(3);
    display.setCursor(0, 5);
    display.println(getDayOfWeek(now.dayOfTheWeek()));

    display.setTextSize(2);
    display.setCursor(0, 40);
    char dateBuffer[11];
    sprintf(dateBuffer, "%04d-%02d-%02d", now.year(), now.month(), now.day());
    display.println(dateBuffer);
  }

  // ------------------- MODE 3: ANALOG CLOCK -------------------
  if (mode == 3) {
    drawAnalogClock(now);
  }

  display.display();
}
  • Now, select the correct board and port in the Arduino IDE. After that, click the upload button to upload the program.

Step 8

Finally, remove the USB cable and connect the 9V battery to your clock. Now you can experience all the features by pressing the mode button and switching between the displays. Enjoy this project! The full video guide is given below, and we hope to see you in the next project.

How to make an analog and digital real-time clock with an OLED display

Similar Posts

Leave a Reply

Your email address will not be published. Required fields are marked *