Analog Style Arduino OLED Clock

by dziubym in Circuits > Arduino

7018 Views, 32 Favorites, 0 Comments

Analog Style Arduino OLED Clock

thumb.png

This is a tutorial how to show you how to create analog style clock using Arduino and a small OLED display.

There is also a video version of this tutorial. You will find the link at the end of this instructable.

This project will show you that years after you finished education some stuff you learnt may be still usefull:) Trigonometry being one of them:) Enjoy.

Supplies

uno.png
oled.png
Ds1302.png

For this project we need just three components

  • Arduino Uno (you can use any other Arduino Board)
  • 128x64 I2C OLED display
  • DS1302 Real Time Clock (RTC) module

Connectivity

diagram.png

Let's connect the components to Arduino first.

We connect:

  • VCC and ground of both OLED and RTC modules to VCC and GND of Arduino
  • SCL and SDA pins of OLED display to pins A5 & A4 on
  • Arduino
  • CLK DAT RST pins of the RTC to Arduino pins A1 A2 and A3

Clock Dial Design

des2.png
des1.png

Let's now look at the clock dial designthat will be shown on the 128x64 OLED display.

We will have:

  • circle with the radius of 32 right (center having coordinates 64 horizontaly and 32 vertically)
  • number 12 at the top
  • 12 hour pointers around the clock
  • instead of seconds have we will have the tiny circle moving around the clock
  • minutes hand created with the single line
  • thick hours hand (created with two lines side by side)


Calculating Position of Clock Hands

sin.png
formulas.png

The most tricky part of this project was to calculate position of each hand. To my surprise trigonometry I learnt at school came to the rescue. Having a circle with the radius of R and known angle α which indicates the exact position the point on the circle. We can calculate coordinates of that point with the following formulas.

X= R*sin(α)

Y= R*cos(α)

where α=0...2π

With a try an error I have adjusted these formulas and came up with

my own Arduino code formulas for calculating coordinates for seconds and minutes and hours hands (see attached slide)

Libraries Needed for OLED and RTC

libraries.png

We will need following libraries to be able to use Oled Display and RTC module (see the slide)


The libraries can be downloaded from:

Declaring and Initialising OLED and RTC Modules

init.png

We can declare the components.

  • RTC connected to pins a1 a2 and a3
// Declaring  RTC module
virtuabotixRTC myRTC(A1,A2,A3);
  • OLED display with size 128x64
#define SCREEN_WIDTH 128 // OLED display width, in pixels
#define SCREEN_HEIGHT 64 // OLED display height, in pixels

#define OLED_RESET     -1// Reset pin # (or -1 if sharing Arduino reset pin)
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);

We need to set initial time We execute this action just once. This project is missing the whole logic of setting up time. The way we set up time here is to execute single command which passes current time to the RTC module.

myRTC.setDS1302Time(10, 00,13, 4, 18, 06, 2020);

After executing this command it needs to be commented out and sketch needs to be reloaded to the board otherwise we'll be resetting this time to the same value each time we power on.

Displaying Clock Hands

hands.png

The faction draw_second is responsible for displaying the circle object corresponding to the current seconds

reading. In that function we calculate coordinates using the formulas we created and when done draw_circle method is

executed to output the circle on the screen. We define two modes:

  • 1 will draw the circle and white,
  • 0 will draw it in black. 0 mode is used as an eraser.
void draw_second(int second, int mode){
   y= (24*cos(pi-(2*pi)/60*second))+clock_center_y;
   x =(24*sin(pi-(2*pi)/60*second))+clock_center_x;
   if (mode==1) display.drawCircle(x, y, 2, SSD1306_WHITE);
   else display.drawCircle(x, y, 2, SSD1306_BLACK);
}


To display minutes we create draw_minute function. It is similar to the seconds one the only difference is that instead

of drawing a circle we draw a line starting from a center of the clock to the point corresponding to the current

minutes reading.

void draw_minute(int minute, int mode){
   y= (24*cos(pi-(2*pi)/60*minute))+clock_center_y;
   x =(24*sin(pi-(2*pi)/60*minute))+clock_center_x;
   if (mode==1)display.drawLine(clock_center_x,clock_center_y,x,y,SSD1306_WHITE); else display.drawLine(clock_center_x,clock_center_y,x,y,SSD1306_BLACK);
}

Draw hours function is a touch more complicated. Not only we draw two lines side by side to make an hour and thicker we also take minutes reading into accounts so the hours hand doesn't just jump from one our

pointer to another but rather slowly moves in between.

void draw_hour(int hour, int minute, int mode){
 
   y= (18*cos(pi-(2*pi)/12*hour-(2*PI)/720*minute))+clock_center_y;
   x =(18*sin(pi-(2*pi)/12*hour-(2*PI)/720*minute))+clock_center_x;
   y1=(18*cos(pi-(2*pi)/12*hour-(2*PI)/720*minute))+clock_center_y+1;
   x1=(18*sin(pi-(2*pi)/12*hour-(2*PI)/720*minute))+clock_center_x+1;
   if (mode==1){
    display.drawLine(clock_center_x,clock_center_y,x,y,SSD1306_WHITE);
    display.drawLine(clock_center_x+1,clock_center_y+1,x1,y1,SSD1306_WHITE);
   }
   else{
    display.drawLine(clock_center_x,clock_center_y,x,y,SSD1306_BLACK);
    display.drawLine(clock_center_x+1,clock_center_y+1,x1,y1,SSD1306_BLACK);
   }  
}


All functions have a draw and erase modes.

Displaying Clock Dial

dial.png

The last function we need, is the one that will display the dial of the clock.

  • first we draw the center of the clock which is a small circle with the radius of 3
  • then we draw the 12 our pointers around the clock
  • finally we draw the number 12 at the top
void draw_clock_face(void){
// draw the center of the clock
  display.drawCircle(clock_center_x, clock_center_y,3, SSD1306_WHITE);
  display.fillCircle(clock_center_x, clock_center_y,3, SSD1306_WHITE);

// draw hour pointers around the face of a clock
for (int i=0;i<12;i++){
   y= (32*cos(pi-(2*pi)/12*i))+clock_center_y;
   x =(32*sin(pi-(2*pi)/12*i))+clock_center_x;
   y1= (28*cos(pi-(2*pi)/12*i))+clock_center_y;
   x1 =(28*sin(pi-(2*pi)/12*i))+clock_center_x;
   display.drawLine(x1,y1,x,y,SSD1306_WHITE);
}
// print string "12" at the top of the face of the clock  
  display.drawCircle(26*sin(pi)+clock_center_x, (26*cos(pi))+clock_center_y, 6, SSD1306_BLACK);
  display.fillCircle(26*sin(pi)+clock_center_x, (26*cos(pi))+clock_center_y, 5, SSD1306_BLACK);
  display.setTextSize(1);             // Normal 1:1 pixel scale
  display.setTextColor(SSD1306_WHITE);        // Draw white text
  display.setCursor(clock_center_x-3,0);      // Start at top-left corner
  display.println(F("12"));
}

Displaying Time Read From RTC Module

time.png

We can now look at how to display real time with RTC module.

In the loop function we read the current time with update time method

There is a number of values that we can read:

  • seconds
  • minutes
  • hours

but also

  • day over week
  • day of the month
  • month and the year

In our project we'll use just the first three.

Every time the second reading changes, we erase seconds minutes and hours hands that were drawn during the last update and draw them again with updated position. Then we save the current time readings so that they can be used in the next run of the loop function for comparison.

We also need to redraw the center of the clock and the number 12 which sometimes get messed up, when performing erase actions.


 void redraw_clock_face_elements(void){
    display.drawCircle(clock_center_x, clock_center_y,3, SSD1306_WHITE);
    display.fillCircle(clock_center_x, clock_center_y,3, SSD1306_WHITE);
    display.setCursor(clock_center_x-3,0);             
    display.println(F("12"));
}
 
 void loop() {
  myRTC.updateTime();
  if (myRTC.seconds!=seconds){
    draw_second(seconds,0);
    draw_minute(minutes,0);
    draw_hour(hours,minutes,0);
    draw_second(myRTC.seconds,1);
    draw_minute(myRTC.minutes,1);
    draw_hour(myRTC.hours,myRTC.minutes,1);
    display.display();
    seconds=myRTC.seconds;
    minutes=myRTC.minutes;
    hours=myRTC.hours;
    redraw_clock_face_elements();
 }

}

Conclusion

How to create analog style clock with RTC DS1302 module , SPI ssd1309 OLED Display and Arduino Uno

This is the end of this tutorial.

If you want to see the video version of it please watch the corresponding YT video.

If you enjoyed it you can support me by giving YT video a like. You can also check my other instructables or YT videos.

Marios Ideas

You will be able to either learn something new or get some ideas for your future projects.

Here you will find link to the code:

Link to the code

If you like this content and you want to support me in creating similar videos go to my Patreon webpage https://www.patreon.com/MariosIdeas Or Paypal