Project tutorial
Adjusting Clock on 128×64 Monochrome Display (ST7920)

Adjusting Clock on 128×64 Monochrome Display (ST7920) © GPL3+

Using 128×64 monochrome display with ST7920, I made an adjusting RTC clock based on an Arduino board.

  • 1,968 views
  • 0 comments
  • 13 respects

Components and supplies

Apps and online services

About this project

Using a 128×64 monochrome display with an ST7920, I made an adjusting RTC clock based on an Arduino board.

Part for adjusting clock is from Doz’ Blog.

I use u8glib library and my set for ST7920 display is

In movie named RTC clock on 128×64 display with ST7290 (4), you can see the latest version vs not optimized version:

If button from roary encoder is short pushed, you can see:

And if long push (more 3-4 seconds), clock enter in adjust mode, first for year.

After you push again button, you can adjust mounth (rotate left for decrease value and rotate right for encrease the value).

After that, you can adjust day of month.

Next is to adjust the hour.

Then minutes.

After new push enter in normal mode, as clock... see next video (is not optimized version, but similar with optimized version of the clock).

Code

u8glib_RTC_clock2.inoJava
/*
based on sketch from http://bentommye.blogspot.com/2013/10/analog-lcd-clock-arduino-lcd.html
http://bentommye.blogspot.com/2013/10/analog-lcd-clock-arduino-lcd.html
  // Dawn & Dusk controller. http://andydoz.blogspot.ro/2014_08_01_archive.html
  // 16th August 2014 - (C) A.G.Doswell 2014
completed by Nicu FLORICA (niq_ro) - http://nicuflorica.blogspot.com/
& http://www.arduinotehniq.com
*/

// Date and time functions using a DS1307 RTC connected via I2C and Wire lib
#include <Wire.h>
#include "RTClib.h"
#include <Encoder.h> // from http://www.pjrc.com/teensy/td_libs_Encoder.html
Encoder knob(3, 2); //encoder connected to pins 2 and 3 (and ground)

#if defined(ARDUINO_ARCH_SAMD)
// for Zero, output on USB Serial console, remove line below if using programming port to program the Zero!
   #define Serial SerialUSB
#endif
RTC_DS1307 rtc;
char daysOfTheWeek[7][12] = {"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"};
//char daysOfTheWeek[7][12] = {"Duminica", "Luni", "Marti", "Miercuri", "Joi", "Vineri", "Sambata"};

#include "U8glib.h"
// setup u8g object, please remove comment from one of the following constructor calls
// IMPORTANT NOTE: The complete list of supported devices is here: http://code.google.com/p/u8glib/wiki/device
//  U8GLIB_ST7920_128X64_1X u8g(13, 11, 10); // SPI Com: SCK = en = 13, MOSI = rw = 11, CS = di = 10
// se orginal code for your LCD!!!!!!
//U8GLIB_KS0108_128 u8g(8, 9, 10, 11, 4, 5, 6, 7, 13, 2, 3, A5, 12);   // 8Bit Com: D0..D7: 8,9,10,11,4,5,6,7 en=18, cs1=14, cs2=15,di=17,rw=16
U8GLIB_ST7920_128X64_1X u8g(7, 6, 5 ,8); //Enable, RW, RS, RESET

int X = 0;
int Y = 0;
int I = 0;
int X2 = 0;
int Y2 = 0;
int X3 = 0;
int Y3 = 0;
int Timer = 0;
int Minutt = 0;
int Sekund = 0;
float Vinkel = 0;
int an = 0;
int luna = 0;
int zi = 0;
int zis = 0;

int ScreenWith = 128;
int ScreenWithC = 64;
int ScreenHeight = 64;
int ScreenHeightC = 32;
int yArray[128];
int deics = ScreenWith/4;
int deigrec = 14;
int deics2 = 0;
int de = 10;

//the variables provide the holding values for the set clock routine
int setyeartemp; 
int setmonthtemp;
int setdaytemp;
int setoretemp;
int setzitemp;
int setminstemp;
int setsecs = 0;
int maxday; // maximum number of days in the given month
int TimeMins; // number of seconds since midnight
int TimerMode = 2; //mode 0=Off 1=On 2=Auto
int TimeOut = 10;
int TimeOutCounter;

// These variables are for the push button routine
int buttonstate = 0; //flag to see if the button has been pressed, used internal on the subroutine only
int pushlengthset = 1500; // value for a long push in mS
int pushlength = pushlengthset; // set default pushlength
int pushstart = 0;// sets default push value for the button going low
int pushstop = 0;// sets the default value for when the button goes back high

int knobval; // value for the rotation of the knob
boolean buttonflag = false; // default value for the button flag
#define buton 4
//char s[3] = "";

#include <stdlib.h>
char tmp_string[8];

void draw(void) {
  // graphic commands to redraw the complete screen should be placed here 
//  u8g.setFont(u8g_font_6x10);
  //u8g.setFont(u8g_font_osb21); 
    TegnKlokkeBg();
   DateTime now = rtc.now();
    TegnViser(Timer-1, 12.0, 15); // Omdreinig, Omdreiningstall / omdreining, radius 
    TegnViser(Minutt-5, 60.0, 24); // Omdreinig, Omdreiningstall / omdreining, radius  
  //  TegnViser(Sekund, 60-deics, 27); // Omdreinig, Omdreiningstall / omdreining, radius
   TegnViser(Sekund-6, 60.0, 27);
  // TegnViser(Sekund, 60.0, 27);

u8g.setFont(u8g_font_6x10);   
u8g.setPrintPos(2*deics + deics2, 63); 
if (zi < 10) u8g.print("0");
u8g.print(zi);
u8g.print("/");
if (luna < 10) u8g.print("0");
u8g.print(luna);
u8g.print("/");
//u8g.print(an-2000);
u8g.print(an);

//u8g.setPrintPos(2*deics + deics2, 50); 
//u8g.print(daysOfTheWeek[zis]);

u8g.setPrintPos(2*deics + deics2+de, 28); 
//u8g.setFont(u8g_font_fur17);
//u8g.setFont(u8g_font_10x20);
u8g.setFont(u8g_font_freedoomr25n);
if (Timer < 10) u8g.print(" ");
u8g.print(Timer);
if (Sekund%2 != 1)
u8g.print(":");

u8g.setPrintPos(2*deics + deics2+de, 56); 
if (Minutt < 10) u8g.print("0");
u8g.print(Minutt);
 u8g.setFont(u8g_font_6x10);   
}

void TegnViser(float Omdreining, float forhold, int Radius) {
    Vinkel = Omdreining * 2.0 * 3.1415 / forhold - 1,5707; // 12 timer blir til 2Pi  
    X2 = ScreenWithC -deics + Radius * cos(Vinkel);
    Y2 = ScreenHeightC + Radius * sin(Vinkel);
    u8g.drawLine(ScreenWithC-deics, ScreenHeightC, X2, Y2);
}

void TegnKlokkeBg() { // draw clock background
    //u8g.drawCircle(ScreenWithC, ScreenHeightC, 30);
    u8g.drawCircle(ScreenWithC-deics, ScreenHeightC, 1);
  
  //  u8g.setFont(u8g_font_unifont);
 //   u8g.setFontPosTop();
    u8g.drawStr(55-deics, 4+deigrec, "12");
    u8g.drawStr(83-deics, 25+deigrec, "3");
    u8g.drawStr(60-deics, 45+deigrec, "6");
    u8g.drawStr(39-deics, 25+deigrec, "9");
  
    for(int TimeStrek = 0; TimeStrek<12; TimeStrek++) { // draw time lines
      Vinkel = TimeStrek / 12.0 * 2 * 3.1415;
      X2 = ScreenWithC-deics + 30 * cos(Vinkel);
      Y2 = ScreenHeightC + 30 * sin(Vinkel);
      X3 = ScreenWithC-deics + 28 * cos(Vinkel);
      Y3 = ScreenHeightC + 28 * sin(Vinkel);
      u8g.drawLine(X2, Y2, X3, Y3);
    }

}


void setup(void) {

  // flip screen, if required
  // u8g.setRot180();

  // set SPI backup if required
  //u8g.setHardwareBackup(u8g_backup_avr_spi);
/*
  // assign default color value
  if ( u8g.getMode() == U8G_MODE_R3G3B2 )
    u8g.setColorIndex(255);     // white
  else if ( u8g.getMode() == U8G_MODE_GRAY2BIT )
    u8g.setColorIndex(3);         // max intensity
  else if ( u8g.getMode() == U8G_MODE_BW )
    u8g.setColorIndex(1);         // pixel on
*/
 //   u8g.setFont(u8g_font_osb21);
 u8g.setFont(u8g_font_6x10);


#ifndef ESP8266
  while (!Serial); // for Leonardo/Micro/Zero
#endif

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

  if (! rtc.isrunning()) {
    Serial.println("RTC is NOT running!");
    // following line sets the RTC to the date & time this sketch was compiled
    rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));
    // This line sets the RTC with an explicit date & time, for example to set
    // January 21, 2014 at 3am you would call:
    // rtc.adjust(DateTime(2014, 1, 21, 3, 0, 0));
  }
//  rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));

pinMode(buton,INPUT);//push button on encoder connected to A0 (and GND)
digitalWrite(buton,HIGH); //Pull button high
}

void loop(void) {
//u8g.setFont(u8g_font_unifont);
 u8g.setFont(u8g_font_6x10);


 DateTime now = rtc.now();
 Timer = now.hour(), DEC;
 Minutt = now.minute(), DEC;
 Sekund = now.second(), DEC;
    Serial.print(Timer);
    Serial.print(':');
    Serial.print(Minutt);
    Serial.print(':');
    Serial.print(Sekund);
    Serial.print(" - ");
    an = now.year(), DEC;
    Serial.print(an);
    Serial.print('/');
    luna = now.month(), DEC;
    Serial.print(luna);
    Serial.print('/');
    zi = now.day(), DEC;
    Serial.print(zi);
    Serial.print(" (");
   zis = now.dayOfTheWeek();
   Serial.print(daysOfTheWeek[zis]);
    Serial.println(") ");
  
  // picture loop
  u8g.firstPage(); 
  do {
    draw();
  } while( u8g.nextPage() );
  // rebuild the picture after some delay
  delay(100);

 pushlength = pushlengthset;
 pushlength = getpushlength();
 delay (10);
 
 if (pushlength < pushlengthset) 
 {
  //ShortPush ();   
   Serial.println("short push");
    // picture loop
  u8g.firstPage(); 
  do {
    draw1();
  } while( u8g.nextPage() );
  // rebuild the picture after some delay
  delay(1000);

 }
  //This runs the setclock routine if the knob is pushed for a long time
       if (pushlength > pushlengthset) {
  //       lcd.clear();
  Serial.println("long push");
         DateTime now = rtc.now();
         setyeartemp=now.year(),DEC;
         setmonthtemp=now.month(),DEC;
         setdaytemp=now.day(),DEC;
         setoretemp=now.hour(),DEC;
         setminstemp=now.minute(),DEC;
   //      setzitemp = now.dayOfTheWeek();
         setclock();
         pushlength = pushlengthset;
       };
//}

  
} // end main loop


// subroutine to return the length of the button push.
int getpushlength() 
{
  buttonstate = digitalRead(buton);  
       if(buttonstate == LOW && buttonflag==false) {     
              pushstart = millis();
              buttonflag = true;
          };     
       if (buttonstate == HIGH && buttonflag==true) {
         pushstop = millis ();
         pushlength = pushstop - pushstart;
         buttonflag = false;
       };
        Serial.println("_");
       return pushlength;
}

void draw1(void) {
  // graphic commands to redraw the complete screen should be placed here  
  //u8g.setFont(u8g_font_unifont);
  //u8g.setFont(u8g_font_osb21);
  u8g.drawStr( 10, 32, "Thx to niq_ro!");
}


//sets the clock
void setclock (){
  // u8g.setFont(u8g_font_unifont);
   setyear ();
   setmonth ();
   setday ();
//   setzi();
   setore ();
   setmins (); 
   rtc.adjust(DateTime(setyeartemp,setmonthtemp,setdaytemp,setoretemp,setminstemp,setsecs));
   delay (1000); 
}

// The following subroutines set the individual clock parameters
int setyear () {
    pushlength = pushlengthset;
    pushlength = getpushlength ();
    if (pushlength != pushlengthset) {
      return setyeartemp;
    }
    knob.write(0);
    delay (50);
    knobval=knob.read();
    if (knobval < -1) { //bit of software de-bounce
      knobval = -1;
      delay (50);
    }
    if (knobval > 1) {
      knobval = 1;
      delay (50);
    }
    setyeartemp=setyeartemp + knobval;
    if (setyeartemp < 2018) { //Year can't be older than currently, it's not a time machine.
      setyeartemp = 2018;
    }
//itoa(setyeartemp - 2000, tmp_string, 10); // https://www.avrfreaks.net/forum/how-do-i-print-variable-u8glib
itoa(setyeartemp, tmp_string, 10); // https://www.avrfreaks.net/forum/how-do-i-print-variable-u8glib
  u8g.firstPage(); 
  do {
  u8g.drawStr( 0, 20, "Set Year");
//  u8g.drawStr( 0, 40, "20"); 
  u8g.drawStr(25, 40, tmp_string);
  } while( u8g.nextPage() );  
    setyear();
}

int setmonth () {
    pushlength = pushlengthset;
    pushlength = getpushlength ();
    if (pushlength != pushlengthset) {
      return setmonthtemp;
    }

 //   lcd.setCursor (0,1);
    knob.write(0);
    delay (50);
    knobval=knob.read();
    if (knobval < -1) {
      knobval = -1;
    }
    if (knobval > 1) {
      knobval = 1;
    }
    setmonthtemp=setmonthtemp + knobval;
    if (setmonthtemp < 1) {// month must be between 1 and 12
      setmonthtemp = 1;
    }
    if (setmonthtemp > 12) {
      setmonthtemp=12;
    }
    itoa(setmonthtemp, tmp_string, 10);
    u8g.firstPage(); 
  do {
  u8g.drawStr( 0, 20, "Set Month");
  u8g.drawStr(25, 40, tmp_string);
  } while( u8g.nextPage() ); 
    setmonth();
}


int setday () {
  if (setmonthtemp == 4 || setmonthtemp == 5 || setmonthtemp == 9 || setmonthtemp == 11) { //30 days hath September, April June and November
    maxday = 30;
  }
  else {
  maxday = 31; //... all the others have 31
  }
  if (setmonthtemp ==2 && setyeartemp % 4 ==0) { //... Except February alone, and that has 28 days clear, and 29 in a leap year.
    maxday = 29;
  }
  if (setmonthtemp ==2 && setyeartemp % 4 !=0) {
    maxday = 28;
  }
    pushlength = pushlengthset;
    pushlength = getpushlength ();
    if (pushlength != pushlengthset) {
      return setdaytemp;
    }
    knob.write(0);
    delay (50);
    knobval=knob.read();
    if (knobval < -1) {
      knobval = -1;
    }
    if (knobval > 1) {
      knobval = 1;
    }
    setdaytemp = setdaytemp+ knobval;
    if (setdaytemp < 1) {
      setdaytemp = 1;
    }
    if (setdaytemp > maxday) {
      setdaytemp = maxday;
    }
  itoa(setdaytemp, tmp_string, 10);  
    u8g.firstPage(); 
  do {
  u8g.drawStr( 0, 20, "Set Day");
u8g.drawStr(25, 40, tmp_string);
  } while( u8g.nextPage() ); 
    setday();
}


int setzi () {
    pushlength = pushlengthset;
    pushlength = getpushlength ();
    if (pushlength != pushlengthset) {
      return setzitemp;
    }
    knob.write(0);
    delay (50);
    knobval=knob.read();
    if (knobval < -1) {
      knobval = -1;
    }
    if (knobval > 1) {
      knobval = 1;
    }
    setzitemp=setzitemp + knobval;
    if (setzitemp < 0) {// month must be between 0 and 6
      setzitemp = 0;
    }
    if (setzitemp > 6) {
      setzitemp=6;
    }
    itoa(setzitemp, tmp_string, 10);
    u8g.firstPage(); 
  do {
  u8g.drawStr( 0, 20, "Set Day of Week");
  u8g.drawStr(25, 40, tmp_string);
  u8g.drawStr(0,60, daysOfTheWeek[setzitemp]);
  } while( u8g.nextPage() ); 
    setzi();
}

int setore () {
    pushlength = pushlengthset;
    pushlength = getpushlength ();
    if (pushlength != pushlengthset) {
      return setoretemp;
    }
    knob.write(0);
    delay (50);
    knobval=knob.read();
    if (knobval < -1) {
      knobval = -1;
      delay (50);
    }
    if (knobval > 1) {
      knobval = 1;
      delay (50);
    }
    setoretemp=setoretemp + knobval;
    if (setoretemp < 0) {
      setoretemp = 0;
    }
    if (setoretemp > 23) {
      setoretemp=23;
    }
   itoa(setoretemp, tmp_string, 10);  
    u8g.firstPage(); 
  do {
  u8g.drawStr( 0, 20, "Set Hour");
u8g.drawStr(25, 40, tmp_string);
  } while( u8g.nextPage() ); 
    setore();
}

int setmins () {
    pushlength = pushlengthset;
    pushlength = getpushlength ();
    if (pushlength != pushlengthset) {
      return setminstemp;
    }
    knob.write(0);
    delay (50);
    knobval=knob.read();
    if (knobval < -1) {
      knobval = -1;
      delay (50);
    }
    if (knobval > 1) {
      knobval = 1;
      delay (50);
    }
    setminstemp=setminstemp + knobval;
    if (setminstemp < 0) {
      setminstemp = 0;
    }
    if (setminstemp > 59) {
      setminstemp=59;
    }
   itoa(setminstemp, tmp_string, 10);  
    u8g.firstPage(); 
  do {
  u8g.drawStr( 0, 20, "Set Minutes");
u8g.drawStr(25, 40, tmp_string);
  } while( u8g.nextPage() ); 
    setmins();
}
// see https://arduino.cz/tutorial-uzivani-hodin-realneho-casu-ds1307-a-ds3231-s-arduinem/
// http://tronixstuff.com/2014/12/01/tutorial-using-ds1307-and-ds3231-real-time-clock-modules-with-arduino/

Schematics

schematic
original schematic by me
Schema ceas epbdiyagir

Comments

Similar projects you might like

Adjusting Dual Clock using DS3231 on 1.8" ST7735 Display

Project showcase by FLORICA Tudor-Nicusor

  • 4,503 views
  • 2 comments
  • 12 respects

Digital & Binary Clock In 8 Digits x 7 Segments LED Display

Project showcase by LAGSILVA

  • 1,827 views
  • 2 comments
  • 9 respects

Tiny Calendar and Clock Featuring Moon Phase in a LED Matrix

Project showcase by LAGSILVA

  • 6,075 views
  • 6 comments
  • 33 respects

Complete Digital Clock Including Alarm and Motion Sensor

Project tutorial by LAGSILVA

  • 12,679 views
  • 11 comments
  • 50 respects

Analog Clock with LED Matrix and Arduino

Project tutorial by LAGSILVA

  • 12,268 views
  • 8 comments
  • 39 respects

Digital And Binary Clock With Two LED Matrix And RTC

Project tutorial by LAGSILVA

  • 6,117 views
  • 10 comments
  • 27 respects
Add projectSign up / Login