Display time

So I am trying to find a way to display the time on a LCD screen. Probably I can't know what time is it without using some sort of external hardware? So what is the easyest way to get time display on arduino?

Probably the easiest way to manage dates and times without external hardware is to use the DateTime library here: Arduino Playground - DateTime

You will need a way to set the clock, the example code uses the serial port to get time from a PC, but you can also set the time using buttons. I recently saw a very clever clock that used tilt sensors for setting the time: http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1233339782/4

Driving a typical text LCD with output from the library is simple, in the example sketch, change the calls from Serial.print to calls to print to the LCD

Thank you!

Now I just need to figure out how to set time at the time of uploading the sketch to the arduino. I don't need serial communication and/or buttons. And I only need hours and minutes. So any hint about that? I don't know how to set the time and then display it.

Here is a simple sketch that displays the hour/minute/seconds on an lcd. It uses the LiquidCrystal library that is distributed with the arduino and I suggest you get the LCD example 'hello world' sketch going first and when you have something displaying on the lcd you can try this sketch to display a digital clock.

Have fun!

#include <LiquidCrystal.h>
#include <DateTime.h>

// simple sketch to display a digital clock on an LCD
// see the LiquidCrystal documentation for more info on this

LiquidCrystal lcd(12, 11, 10, 5, 4, 3, 2);

void setup(){
  DateTime.sync(1230768000); // set jan 1 2009 as the default time
}

void  loop(){     
  if(DateTime.available()) { 
    unsigned long prevtime = DateTime.now(); 
    while( prevtime == DateTime.now() )  // wait for the second to rollover
      ;
    DateTime.available(); //refresh the Date and time properties
    digitalClockDisplay( );   // update digital clock  
  } 
}

void printDigits(byte digits){
  // utility function for digital clock display: prints preceding colon and leading 0
  lcd.print(":");
  if(digits < 10)
    lcd.print('0');
  lcd.print(digits,DEC);
}

void digitalClockDisplay(){
  lcd.home();
  // digital clock display of current time
  lcd.print(DateTime.Hour,DEC);  
  printDigits(DateTime.Minute);  
  printDigits(DateTime.Second);   
}

I have not run this sketch so let me know how you get on

I figured it out a few minutes ago myself. But thanks for this! Now just to integrate this into my other functions. It is a little strange that after using this the other parts of my program are running slower.

The example sketch I posted above wastes a lot of time doing nothing !

as long as you call the following functions in your loop when you want the time updated you should be fine:
DateTime.available(); //refresh the Date and time properties
digitalClockDisplay( ); // update digital clock

So this part:
DateTime.available(); //refresh the Date and time properties
Needs to be in the home screen function? Or can I call this only when I need to display the time? Because I am using functions and the home screen (where the time is) gets called when the user selects it. So does this have to be in the loop or can it be in the home function? And I am using my own formatting to display the time so I don't need digitalClockDisplay.

You only need to call DateTime.available just before you display the time.

The purpose of that function is to update the internal time counter and take a snapshot of the time properties so that subsequent calls to get the time properties will be up to date and consistent .

Great! Working like it should now!

Good to hear you have it going. Please post more about your project when you have it finished

I will!

Just another question. If I need someday to set the time using buttons, I can use something like this?

DateTime.sync(DateTime.makeTime(0, 40, 10, 18, 2, 2009));

DateTime.sync(DateTime.makeTime(0, 40, 10, 18, 2, 2009));

Yep, thats how you can do it :wink:

Have fun!

Great! I just added the ability to set the time when arduino starts. For that I am using a potenciometer.

If anyone is interested - here is the code for function that sets time:

void nastaviuro()
{
  char buffer[2]; //this is a buffer for printing on a screen
  lcd.clear(); //clear the display
  lcd.printIn("Sekunde: "); //Print Sekunde -> Seconds: in english
  int sekunde1 = vnos_stevila(); //get a first digit of seconds and store it in variable sekunde1
  lcd.cursorTo(2,0); //Move a cursor to second row, first column
  itoa(sekunde1,buffer,10); //Convert integer sekunde1 to char and store it in the buffer
  lcd.printIn(buffer); //Print the buffer
  int sekunde2 = vnos_stevila(); //get the second digit of seconds and store it in variable sekunde2
  itoa(sekunde2,buffer,10);
  lcd.cursorTo(1,0);
  lcd.printIn("               "); //Clear the first line of the screen
  lcd.cursorTo(1,0);
  lcd.printIn("Minute: "); //Print Minute -> Minutes in english
  lcd.cursorTo(2,1);
  lcd.printIn(buffer);
  lcd.printIn(":");
  int minute1 = vnos_stevila();
  itoa(minute1,buffer,10);
  lcd.cursorTo(2,3);
  lcd.printIn(buffer);
  int minute2 = vnos_stevila();
  itoa(minute2,buffer,10);
  lcd.cursorTo(2,4);
  lcd.printIn(buffer);
  lcd.printIn(":");
  lcd.cursorTo(1,0);
  lcd.printIn("               ");
  lcd.cursorTo(1,0);
  lcd.printIn("Ure: "); //Print ure -> Hours in english
  int ure1 = vnos_stevila();
  itoa(ure1,buffer,10);
  lcd.cursorTo(2,6);
  lcd.printIn(buffer);
  int ure2 = vnos_stevila();
  itoa(ure2,buffer,10);
  lcd.cursorTo(2,7);
  lcd.printIn(buffer);
  delay(3000); // Wait 3 seconds
  
  lcd.clear();
  
  lcd.printIn("Dan:"); //Print dan <- Day in english
  int dan1 = vnos_stevila();
  itoa(dan1,buffer,10);
  lcd.cursorTo(2,0);
  lcd.printIn(buffer);
  int dan2 = vnos_stevila();
  itoa(dan2,buffer,10);
  lcd.cursorTo(2,1);
  lcd.printIn(buffer);
  lcd.printIn(".");
  lcd.cursorTo(1,0);
  lcd.printIn("               ");
  lcd.cursorTo(1,0);
  lcd.printIn("Mesec: "); //print mesec ->  month in english
  int mesec1 = vnos_stevila();
  itoa(mesec1,buffer,10);
  lcd.cursorTo(2,3);
  lcd.printIn(buffer);
  int mesec2 = vnos_stevila();
  itoa(mesec2,buffer,10);
  lcd.cursorTo(2,4);
  lcd.printIn(buffer);
  lcd.printIn(".");
  lcd.cursorTo(1,0);
  lcd.printIn("               ");
  lcd.cursorTo(1,0);
  lcd.printIn("Leto: "); //Print leto -> year in english
  int leto1 = vnos_stevila();
  itoa(leto1,buffer,10);
  lcd.cursorTo(2,6);
  lcd.printIn(buffer);
  int leto2 = vnos_stevila();
  itoa(leto2,buffer,10);
  lcd.cursorTo(2,7);
  lcd.printIn(buffer);
  int leto3 = vnos_stevila();
  itoa(leto3,buffer,10);
  lcd.cursorTo(2,8);
  lcd.printIn(buffer);
  int leto4 = vnos_stevila();
  itoa(leto4,buffer,10);
  lcd.cursorTo(2,9);
  lcd.printIn(buffer);
  delay(3000);
  
  char sekunde3[6]; //Create a char array for seconds
  char sekunde4[2];
  char minute3[6];
  char minute4[2];
  char ure3[6];
  char ure4[2];
  char dan3[6];
  char dan4[2];
  char mesec3[6];
  char mesec4[2];
  char leto5[12];
  char leto6[2];
  char leto7[2];
  char leto8[2];
  itoa(sekunde1,sekunde3,10); //Converts sekunde1 to char and store them in sekunde3
  itoa(sekunde2,sekunde4,10);
  itoa(minute1,minute3,10);
  itoa(minute2,minute4,10);
  itoa(ure1,ure3,10);
  itoa(ure2,ure4,10);
  itoa(dan1,dan3,10);
  itoa(dan2,dan4,10);
  itoa(mesec1,mesec3,10);
  itoa(mesec2,mesec4,10);
  itoa(leto1,leto5,10);
  itoa(leto2,leto6,10);
  itoa(leto3,leto7,10);
  itoa(leto4,leto8,10);
  strcat(sekunde3,sekunde4); //Combines two digits of seconds and stores them in sekunde3
  strcat(minute3,minute4);
  strcat(ure3,ure4);
  strcat(dan3,dan4);
  strcat(mesec3,mesec4);
  strcat(leto5,leto6);
  strcat(leto5,leto7);
  strcat(leto5,leto8);
  
  //Displays this:
  // HH:MM:SS
  // DD.MM.YYYY
  lcd.clear();
  lcd.cursorTo(1,6);
  lcd.printIn(ure3);
  lcd.printIn(":");
  lcd.printIn(minute3);
  lcd.printIn(":");
  lcd.printIn(sekunde3);
  lcd.cursorTo(2,6);
  lcd.printIn(dan3);
  lcd.printIn(".");
  lcd.printIn(mesec3);
  lcd.printIn(".");
  lcd.printIn(leto5);
  delay(5000);
  

  int ure = atoi(ure3); //converts char back to integer
  int minute = atoi(minute3);
  int sekunde = atoi(sekunde3);
  int dan = atoi(dan3);
  int mesec = atoi(mesec3);
  int leto = atoi(leto5);
  
  DateTime.sync(DateTime.makeTime(sekunde, minute, ure, dan, mesec, leto));  //sets the time
  ura_nastavljena = true; //The time is now set
   
}

The ura_nastavljena part just indicates that the clock has been set so my code doesn't ask me to set the time again. You can use that or delete it.

And here is the code for numeric input using one potenciometer and one button:

int vnos_stevila()
{
  while(1) //Create a loop
  {
      int vrni = 0; //Number to return
      int dobi = analogRead(1); //Get a value from potenciometer on analog pin 1
      int gumbi = 0; //Here is stored a value from a button

      
      if (dobi <=102) //If input from a potenciometer is between 0 and 102 then variable vrni is 0
      {
          vrni = 0;
      }
      else if (dobi <= 204)
      {
          vrni = 1;
      }
      else if (dobi <= 306)
      {
          vrni = 2;
      }
      else if (dobi <= 408)
      {
          vrni = 3;
      }
      else if (dobi <= 510)
      {
          vrni = 4;
      }
      else if (dobi <= 612)
      {
          vrni = 5;
      }
      else if (dobi <= 714)
      {
          vrni = 6;
      }
      else if (dobi <= 816)
      {
          vrni = 7;
      }
      else if (dobi <= 918)
      {
          vrni = 8;
      }
      else if (dobi <= 1023)
      {
          vrni = 9;
      }

      char znak[2]; //declare a variable znak
      itoa(vrni, znak, 10); //convert a variable vrni to char and store it in znak
      lcd.cursorTo(2,14); //Move screen cursor to second row, 14 column
      delay(100); //wait
      lcd.printIn(">"); //A little marker for nicer input
      lcd.printIn(znak); //Print the current value
      gumbi = digitalRead(gumb); //Read the value from a button
      
      if (gumbi == 1) //If button was pressed, return the current value
      {
          return vrni;
      }
  }
}

Variable names are in slovenian language but the comments are in english so probably you can understand it. The code is VERY unoptimised and takes a lot of RAM. But it works for me! I am using LCD4Bit library to write on the screen.

the only question now is -> Will this library display the right time for a whole month? +/- 5min

char buffer[[glow]2[/glow]]; //this is a buffer for printing on a screen
itoa(sekunde1,[glow]buffer[/glow],10);

Dangerous! You don't give enough space in your character buffer to fit the number. If the number of seconds is 10, the buffer needs at least 3 bytes of space, the '1', the '0', and the NUL terminator. If you have numbers larger than 99 (like your year "ledo"), or smaller than 0, you need even more space.

Buffer can only store numbers up to 9. No more! The same goes for the others. leto5 -> combines 4 digits and is 12 places long.

roli, you can avoid the problem halley mentions and simplify your code if you use chars directly instead of converting to a string.

Here is the numeric input routine simplified to return a char from '0' to '9'

#define POT_PIN 1 // pot on analog pin 1
#define BUTTON_PIN 2 // button on digital pin 2

char getNumber(){  
 //returns a char from '0' to '9' based on position of pot when button is pushed 
  while(1)   {
      char ret = '0'; //Number to return
      int value = analogRead(POT_PIN); //Get a value from potentiometer on given analog pin 
      ret = (value / 102) + '0';
      lcd.cursorTo(2,14); //Move screen cursor to second row, 14 column
      delay(100); //wait
      lcd.printIn(">"); //A little marker for nicer input
      lcd.printIn(ret); //Print the current value
      if(digitalRead(BUTTON_PIN)== HIGH)
            return ret;   
  }
}

to use this function you would do something like:

  lcd.clear(); //clear the display
  lcd.printIn("Seconds: ");
  char seconds = numberEntry(); //get a first digit of seconds
  lcd.cursorTo(2,0); //Move a cursor to second row, first column
  lcd.printIn(seconds); //Print the char returned from numberEntry

I thought about that but I like numeric input better. Maybe I will need to use numbers again in the same sketch so this is done intentionaly.

Still your way is simpler.

No problem, with a minor change you can do something like this to return an integer

int getNumber(){  
 //returns a number from 0 to 9 based on position of pot when button is pushed 
  while(1)   {
      int ret; //Number to return
      int value = analogRead(POT_PIN); //Get a value from potentiometer on given analog pin 
        ret = (value / 102) + '0';
      lcd.cursorTo(2,14); //Move screen cursor to second row, 14 column
      delay(100); //wait
      lcd.printIn(">"); //A little marker for nicer input
      lcd.printIn(ret); //Print the current value
      if(digitalRead(BUTTON_PIN)== HIGH)
            return ret;   
  }
}

and this will convert the integer to a char abd print that to the lcd

  lcd.clear(); //clear the display
  lcd.printIn("Seconds: ");
  char seconds = numberEntry() + '0'; 
  lcd.cursorTo(2,0); //Move a cursor to second row, first column
  lcd.printIn(seconds);