Pages: [1]   Go Down
Author Topic: LCD clock demo, No RTC, Serial time set, LCD code help/suggestions please.  (Read 1094 times)
0 Members and 1 Guest are viewing this topic.
Illinois, USA
Offline Offline
Full Member
***
Karma: 0
Posts: 114
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I'm trying to create a simple clock displaying HH:MM:SS, DD/MM/YYYY, on a I2C LCD display, with an Uno, without an RTC.  With the time of day/date (Unix time)being set with a  command sent from a PC via serial port (Arduino USB cable) once to set time and start the lcd display.

Surprisingly I have not found an exact example sketch, but I did find the below sketch from here http://arduino.cc/forum/index.php?topic=12003.0 that I have modified.  I have changed serial outputs to the LCD, and it sort of operates, with the exception of my bad LCD display control.

I'd like to eliminate the clear() and delay() that causes the display to flash, rather than give the illusion of changing the 'seconds' digit only.  Code follows.

Code:
#include <LiquidCrystal_I2C.h>
#include <Wire.h>

/*
 * TimeSerial sketch
 * example code illustrating Time library set through serial port messages.
 * Messages consist of the letter T followed by ten digit time
 * (as seconds since Jan 1 1970)
 * You can send the text on the next line using Serial Monitor to set the
 * clock to noon Jan 1 2011:
 * T1293883200
 * A Processing example sketch to automatically send the messages is
 * included in the Time library download
 */
#include <Time.h>

#define TIME_MSG_LEN  11   // time sync consists of a HEADER followed by ten
                           // ascii digits
#define TIME_HEADER  'T'   // Header tag for serial time sync message

LiquidCrystal_I2C lcd(0x27,20,4);

void setup()  {
  Serial.begin(9600);
  Serial.println("Waiting for time sync message");
  lcd.init();
   // lcd.backlight();
    lcd.setCursor(0, 0);
}

void loop(){
  if(Serial.available() )
  {
    processSyncMessage();
  }
  if(timeStatus()!= timeNotSet)
  {
    // here if the time has been set
    digitalClockDisplay();
  }
  delay(1000);
}

void digitalClockDisplay(){ //Need to correct LCD flash & only update seconds
  lcd.print(hour());
  lcd.print(":");
  printDigits(minute());
  lcd.print(minute());
  lcd.print(":");
  printDigits(second());
  lcd.print(second());
  lcd.print(" ");  //Was Serial.print(" ");
  lcd.print(month());
  lcd.print("/");
  lcd.print(day());
  lcd.print("/");
  lcd.print(year());
  delay(500);  // Causes LCD flash
  lcd.clear();
}

void printDigits(int digits){ // Still prints serial not a problem.
  // utility function for digital clock display: prints preceding colon & leading 0
  Serial.print(":");
  if(digits < 10)
    Serial.print('0');
  Serial.print(digits);
}

void processSyncMessage() {
  // if time sync available from serial port, update time and return true
  // time message consists of a header and ten ascii digits
  while(Serial.available() >=  TIME_MSG_LEN ){  
    char c = Serial.read() ;
    Serial.print(c);
    if( c == TIME_HEADER ) {
      time_t pctime = 0;
      for(int i=0; i < TIME_MSG_LEN -1; i++){
        c = Serial.read();
        if( isDigit(c)) {
          pctime = (10 * pctime) + (c - '0') ; // convert digits to a number
        }
      }
      setTime(pctime);   // Sync clock to the time received on serial port
    }
  }
}    

Any suggestions greatly appreciated.
« Last Edit: March 21, 2013, 10:19:29 am by Ashton » Logged

0
Offline Offline
Jr. Member
**
Karma: 2
Posts: 66
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Use couple of variables to store hour, minute, second etc. displayed on LCD. In digitalClockDisplay() add couple of conditions to see what was changed. Example:

if( secondDisplayedOnLcd != second() )
{
  secondDisplayedOnLcd = second();
  lcd.setCursor( proper coordinates for second portion of time on LCD );
  lcd.print( secondDisplayedOnLcd );
}

This way you will update only changed information on LCD - no need for delay() neither clear() in digitalClockDisplay().

Plus, in loop(), you should call digitalClockDisplay() in non-blocking manner. See example sketch for LED flasher without delay() to get idea.
« Last Edit: March 21, 2013, 10:16:58 am by qwertysimo » Logged

Illinois, USA
Offline Offline
Full Member
***
Karma: 0
Posts: 114
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I'll working on converting to variables before sending to the display.

But one question, I may have observed that without the clear(), the displayed characters just create one long string, instead of refreshing the string on LCD Line #1.  This continues to Line #3, then to 2, and 4.  Am I wrong? or should there be a command/character to prevent it from scrolling? 

Just a thought while I do the variables...  Thanks.
Logged

texas
Offline Offline
God Member
*****
Karma: 27
Posts: 862
old, but not dead
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

That's not going to keep time very well.  The delay(1000) assumes that everything else takes 0 time execute, which is silly of course.  Here is a better way to do it:

Code:
unsigned long int rolltime = millis() + 1000;
void loop() {

  //  do a signed comparison to handle rollover properly
  while((long)(millis() - rolltime) >= 0) {

    // While we are waiting, buffer any characters being typed  EXAMPLE ONLY

    if(Serial.available() > 0) {
      inChar = Serial.read();

      if(inChar == '\n') {
        inBuf[i] = '\0';
        i++;
        stringDone = 1;
      } else {
        inBuf[i] = inChar;
        if(i < 20)
          i++;
      } // end if
    } // end if
  } // end while

//  This is where you would tick your time fields and update the display
  
  // set next time to update display
  rolltime += 1000;
} //end loop()

Logged

Experience, it's what you get when you were expecting something else.

0
Offline Offline
Jr. Member
**
Karma: 2
Posts: 66
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

But one question, I may have observed that without the clear(), the displayed characters just create one long string, instead of refreshing the string on LCD Line #1.  This continues to Line #3, then to 2, and 4.  Am I wrong? or should there be a command/character to prevent it from scrolling?
Without clear(), lcd.print will print character on last used position. You shoud use lcd.setCursor( 0, 0 ) if you want to start refreshing LCD line #1.
Logged

Pages: [1]   Go Up
Jump to: