Analog Style Arduino OLED Clock
by dziubym in Circuits > Arduino
7018 Views, 32 Favorites, 0 Comments
Analog Style Arduino OLED Clock
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
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
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
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
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
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
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
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
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
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
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.
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:
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