An interesting nice looking analog style clock, which is also extremely simple to build.

This time I will show you how to make an interesting nice looking clock, which is also extremely simple to build. The exact time time is displayed on a large LCD screen in the form of an elliptical analog clock. The time can also be easily adjusted with the help of three buttons.

In this case, for the sake of simplicity, a real-time clock module is not used, so the accuracy is not so high and depends mostly on the crystal within the microcontroller.

The device consists of several components:

- Arduino Nano microcontroller

- ST7920 chip based LCD display with 128x64 dots resolution

- and three buttons

The basic code is downloaded from the blaber.com.pl site by adjusting it to the above-mentioned display which is more accessible and much cheaper than the original. Code is a modification of the digital clock, and although it works, it still requires a lot of work on the graphics. This is a great example of how to use the u8g2 library to draw objects and write text on different types of displays.

When switching on, the time is 12:00 and we have to manually set the current time. We make it easy with the help of three buttons. The middle button is used to enter the settings mode, and with the first click the Minutes are set, and with the second click the Hours. In settings mode, the arrows are moved with the help of the other two buttons. When it comes to precision, considering that we do not use RTC module the clock is quite accurate. In my case for 24 hours the difference between real time and that of the clock was only a few seconds.

Finally, the device is built into a suitable box made of PVC material with thicknesses of 3mm and 5mm and coated with self-adhesive colored wallpaper.

Schematic.jpg
        #include <Arduino.h>
#include <U8g2lib.h>
#include <TimerOne.h>



U8G2_ST7920_128X64_1_SW_SPI u8g2(U8G2_R2, /* clock=*/ 13, /* data=*/ 11, /* CS=*/ 10, /* reset=*/ 8);


byte inPin1 = 7;                  //digital input sw-1 marking hours or minutes
byte inPin2 = 6;                  //sw-2 digital input correcting minutes
byte inPin3 = 5;                  //digital input sw-3 correcting hours 
byte P1, P2;                      //button states
uint8_t s, m, g;                  //declaration of seconds, minutes and hours
boolean kropki;                   //variable of the dots
const char tarczaX[60] = {        //X coordinates of the target points
  64, 61, 56, 53, 50, 48, 45, 42, 40, 40,
  35, 34, 31, 29, 28, 28, 28, 29, 31, 34,
  35, 38, 40, 42, 45, 48, 50, 53, 56, 61,
  64, 68, 72, 76, 79, 82, 85, 87, 90, 92,
  94, 96, 98, 99, 100, 100, 100, 99, 98, 96,
  94, 92, 90, 87, 85, 82, 79, 76, 68, 64 };
const char tarczaY[60] = {        //y coordinates of the target points
  54, 54, 54, 54, 53, 52, 51, 49, 48, 48,
  44, 43, 40, 37, 35, 32, 27, 26, 23, 21,
  19, 17, 15, 13, 12, 10,  9,  8,  8,  8,
   8,  8,  8,  8,  8,  9, 10, 12, 13, 15,
  17, 19, 21, 23, 26, 32, 35, 37, 40, 42,
  44, 46, 48, 48, 48, 52, 53, 54, 54, 54 };  
  
void setup() {
  u8g2.begin();
  pinMode(inPin1, INPUT_PULLUP);          //setting the pin as a digital input
  pinMode(inPin2, INPUT_PULLUP);
  pinMode(inPin3, INPUT_PULLUP);
  u8g2.setContrast(220);
  Timer1.initialize(1000000);
  Timer1.attachInterrupt(toggleOutput);
  P1 = 0; P2 = 0; s = 0; m = 0; g = 0;

}

void loop() {
  u8g2.setFont(u8g2_font_9x15B_tr);
  u8g2.setFontDirection(2);           //select the direction of subtitles
  Dipsw();
  u8g2.firstPage();
  char m_str[3];
  strcpy(m_str, u8x8_u8toa(m, 2));    //Replace m with a string with 2 digits
  do {
    u8g2.drawStr(115,27,"9");
    u8g2.drawStr(20,27,"3");
    u8g2.drawStr(67,0,"6");
    u8g2.drawStr(73,52,"12"); 
    u8g2.drawDisc(64,32,3);                     //center of the clock
    u8g2.drawDisc(42,57,2);                     //hour 1
    u8g2.drawDisc(24,49,2);                     //hour 2
    u8g2.drawDisc(24,14,2);                     //hour 4
    u8g2.drawDisc(42,5,2);                      //hour 5
    u8g2.drawDisc(85,5,2);                      //hour 7
    u8g2.drawDisc(104,14,2);                    //hour 8
    u8g2.drawDisc(104,49,2);                    //hour 10
    u8g2.drawDisc(85,57,2);                     //hour 11    
    if (P1 == 1){ u8g2.drawStr(10,0,"M");}      //marking correcting minutes
    if (P1 == 2){ u8g2.drawStr(10,0,"H");}      //marking of correcting hours
    //drawing hour hand
    if (g == 0 or g == 12){u8g2.drawTriangle(64,49, 67,32, 61,32);}
    if (g == 1 or g == 13){u8g2.drawTriangle(50,49, 67,34, 61,30);}
    if (g == 2 or g == 14){u8g2.drawTriangle(40,42, 65,35, 60,30);}
    if (g == 3 or g == 15){u8g2.drawTriangle(32,32, 64,35, 64,29);}
    if (g == 4 or g == 16){u8g2.drawTriangle(40,21, 63,29, 63,35);}
    if (g == 5 or g == 17){u8g2.drawTriangle(48,13, 66,30, 62,34);}
    if (g == 6 or g == 18){u8g2.drawTriangle(64,13, 68,32, 60,32);}
    if (g == 7 or g == 19){u8g2.drawTriangle(79,13, 67,34, 62,30);}
    if (g == 8 or g == 20){u8g2.drawTriangle(88,21, 66,35, 63,30);}
    if (g == 9 or g == 21){u8g2.drawTriangle(96,32, 64,35, 64,29);}
    if (g == 10 or g == 22){u8g2.drawTriangle(88,42, 64,35, 65,28);}
    if (g == 11 or g == 23){u8g2.drawTriangle(79,49, 67,31, 62,35);}
    //drawing a second hand
    u8g2.drawLine(64,32, tarczaX[s], tarczaY[s]);
    // draw minute hand
    //u8g2.drawStr(20,50,m_str);
    if (m == 0) {u8g2.drawLine(67,32, 64,54); u8g2.drawLine(61,32, 64,54);}
    if (m == 1) {u8g2.drawLine(67,32, 60,54); u8g2.drawLine(61,32, 60,54);}
    if (m == 2) {u8g2.drawLine(67,32, 56,54); u8g2.drawLine(61,32, 56,54);}
    if (m == 3) {u8g2.drawLine(66,33, 53,54); u8g2.drawLine(61,31, 53,54);}
    if (m == 4) {u8g2.drawLine(66,33, 50,53); u8g2.drawLine(61,31, 50,53);}
    if (m == 5) {u8g2.drawLine(65,34, 48,52); u8g2.drawLine(61,30, 48,52);}
    if (m == 6) {u8g2.drawLine(64,34, 45,51); u8g2.drawLine(61,30, 45,51);}
    if (m == 7) {u8g2.drawLine(64,34, 42,49); u8g2.drawLine(61,30, 42,49);}
    if (m == 8) {u8g2.drawLine(64,34, 40,48); u8g2.drawLine(61,30, 40,48);}
    if (m == 9) {u8g2.drawLine(64,35, 38,46); u8g2.drawLine(61,30, 38,46);} 
    if (m == 10) {u8g2.drawLine(65,35, 35,44); u8g2.drawLine(62,30, 35,44);}
    if (m == 11) {u8g2.drawLine(64,35, 34,43); u8g2.drawLine(62,29, 34,43);}
    if (m == 12) {u8g2.drawLine(64,35, 31,40); u8g2.drawLine(62,29, 31,40);}
    if (m == 13) {u8g2.drawLine(64,35, 29,37); u8g2.drawLine(63,29, 29,37);}
    if (m == 14) {u8g2.drawLine(64,35, 28,35); u8g2.drawLine(63,29, 28,35);}
    if (m == 15) {u8g2.drawLine(64,35, 28,32); u8g2.drawLine(63,29, 28,32);} //
    if (m == 16) {u8g2.drawLine(63,35, 28,27); u8g2.drawLine(64,29, 28,27);}
    if (m == 17) {u8g2.drawLine(63,35, 29,26); u8g2.drawLine(64,29, 29,26);}
    if (m == 18) {u8g2.drawLine(63,35, 31,23); u8g2.drawLine(64,29, 31,23);}
    if (m == 19) {u8g2.drawLine(63,35, 34,21); u8g2.drawLine(64,29, 34,21);}          
    if (m == 20) {u8g2.drawLine(63,35, 35,19); u8g2.drawLine(65,29, 35,19);}
    if (m == 21) {u8g2.drawLine(63,35, 38,17); u8g2.drawLine(65,29, 38,17);}
    if (m == 22) {u8g2.drawLine(62,34, 40,15); u8g2.drawLine(65,29, 40,15);}
    if (m == 23) {u8g2.drawLine(62,34, 42,13); u8g2.drawLine(65,29, 42,13);}
    if (m == 24) {u8g2.drawLine(62,34, 45,12); u8g2.drawLine(66,29, 45,12);}
    if (m == 25) {u8g2.drawLine(61,34, 48,10); u8g2.drawLine(66,32, 48,10);}
    if (m == 26) {u8g2.drawLine(61,33, 50,9); u8g2.drawLine(66,30, 50,9);}
    if (m == 27) {u8g2.drawLine(66,32, 53,8); u8g2.drawLine(61,33, 53,8);}
    if (m == 28) {u8g2.drawLine(67,32, 56,8); u8g2.drawLine(61,33, 56,8);}
    if (m == 29) {u8g2.drawLine(67,32, 61,8); u8g2.drawLine(61,32, 61,8);}          
    if (m == 30) {u8g2.drawLine(67,32, 64,8); u8g2.drawLine(61,32, 64,8);} ///
    if (m == 31) {u8g2.drawLine(67,32, 68,8); u8g2.drawLine(61,32, 68,8);}
    if (m == 32) {u8g2.drawLine(67,32, 72,8); u8g2.drawLine(61,32, 72,8);}
    if (m == 33) {u8g2.drawLine(67,32, 76,8); u8g2.drawLine(61,31, 76,8);}
    if (m == 34) {u8g2.drawLine(67,32, 79,8); u8g2.drawLine(62,31, 79,8);}
    if (m == 35) {u8g2.drawLine(67,33, 82,9); u8g2.drawLine(62,30, 82,9);}
    if (m == 36) {u8g2.drawLine(66,34, 85,10); u8g2.drawLine(62,30, 85,10);}
    if (m == 37) {u8g2.drawLine(66,34, 87,12); u8g2.drawLine(62,30, 87,12);}
    if (m == 38) {u8g2.drawLine(66,34, 90,13); u8g2.drawLine(63,30, 90,13);}
    if (m == 39) {u8g2.drawLine(66,35, 92,15); u8g2.drawLine(63,30, 92,15);}          
    if (m == 40) {u8g2.drawLine(66,35, 94,17); u8g2.drawLine(63,30, 94,17);}
    if (m == 41) {u8g2.drawLine(65,35, 96,19); u8g2.drawLine(64,30, 96,19);}
    if (m == 42) {u8g2.drawLine(65,35, 98,21); u8g2.drawLine(64,30, 98,21);}
    if (m == 43) {u8g2.drawLine(65,35, 99,23); u8g2.drawLine(64,29, 99,23);}
    if (m == 44) {u8g2.drawLine(64,35, 100,26); u8g2.drawLine(64,29, 100,26);}
    if (m == 45) {u8g2.drawLine(64,35, 100,32); u8g2.drawLine(64,29, 100,32);} ///
    if (m == 46) {u8g2.drawLine(64,35, 100,35); u8g2.drawLine(64,29, 100,35);}
    if (m == 47) {u8g2.drawLine(64,35, 99,37); u8g2.drawLine(64,29, 99,37);}
    if (m == 48) {u8g2.drawLine(64,35, 98,40); u8g2.drawLine(64,29, 98,40);}
    if (m == 49) {u8g2.drawLine(64,35, 96,42); u8g2.drawLine(65,28, 96,42);}          
    if (m == 50) {u8g2.drawLine(64,35, 94,44); u8g2.drawLine(65,28, 94,44);}
    if (m == 51) {u8g2.drawLine(63,35, 92,46); u8g2.drawLine(66,30, 92,46);}
    if (m == 52) {u8g2.drawLine(63,35, 90,48); u8g2.drawLine(66,30, 90,48);}
    if (m == 53) {u8g2.drawLine(64,34, 87,48); u8g2.drawLine(66,29, 87,48);}
    if (m == 54) {u8g2.drawLine(63,35, 85,48); u8g2.drawLine(67,31, 85,48);}
    if (m == 55) {u8g2.drawLine(67,31, 82,52); u8g2.drawLine(63,35, 82,52);}
    if (m == 56) {u8g2.drawLine(67,31, 79,53); u8g2.drawLine(62,35, 79,53);}
    if (m == 57) {u8g2.drawLine(67,31, 76,54); u8g2.drawLine(62,35, 76,54);}
    if (m == 58) {u8g2.drawLine(67,31, 72,54); u8g2.drawLine(62,34, 72,54);}
    if (m == 59) {u8g2.drawLine(67,31, 68,54); u8g2.drawLine(62,32, 68,54);}                  
  } while ( u8g2.nextPage() );
  delayMicroseconds(10000); 
}

void toggleOutput(){
    s++;
    if (s == 60) {
      s = 0;
      m++;
    }
    if (m == 60) {
      m = 0;
      g++;
    }
    if (g == 24) {
      g = 0;
    } 
    kropki = !kropki;               //blinking colon every 1 sec.
}

void Dipsw(){
  byte readPin1, readPin1A, readPin2, readPin2A, readPin3, readPin3A;
  readPin1 = digitalRead(inPin1);           //read the state of the rotation button
  readPin2 = digitalRead(inPin2);           //reading the status of the right move button
  readPin3 = digitalRead(inPin3);           //reading the state of the move left button
  delay(1);
  readPin1A = digitalRead(inPin1);
  readPin2A = digitalRead(inPin2);
  readPin3A = digitalRead(inPin3);
  if (readPin1 == LOW and readPin1 == readPin1A) {
    //setting the time - selecting hours or minutes
    P1++;
    delay(200);
    if (P1 == 3){
      P1 = 0;
    }
  }  
  if (readPin2 == LOW and readPin2 == readPin2A) {
    //correcting hours and minutes up
    if (P1 == 1){                           //correcting minutes
       m++;
       if (m == 59) {m = 0;}
    }
    if (P1 == 2){                           //framing minutes
      g++;
      if (g == 24){g = 0;}
    }
    delay(200);
  }
  if (readPin3 == LOW and readPin3 == readPin3A) { 
  //correcting hours and minutes down
    if (P1 == 1){                           //correcting minutes
      m--;
      if (m >= 60) {m = 59;}
      if (m <= 0) {m = 59;}
    }
    if (P1 == 2){                           //correcting hours
      g--;
      if (g >= 24){g = 23;}
      if (g <= 0){g = 23;}
    }
    delay(200);
  }
}
    
Mirko Pavleski
Electronics , Arduino , Physics

Categories