Arduino clock bug

I have recently gotten my clock sketch to work. It looks great and I like it. However, there is a small bug that I don't know how to fix and cannot find any info on what may be going on. The clock is in 24hr format and includes the hours, minutes, and seconds. When the time gets to 11:59:59, it rolls over to 0:00:00. But it leaves the last digit from the previous time resulting in 0:00:009. The 9 does not go away until the hours reach two digits again. I am at a loss.

Any ideas?

That is possinly because you don't force the display of two 0 for the hours value 0? (I.e. 00)

So you had 11:59:59 which is 8 characters and you go to 0:00:00 which is 7 and you don't erase the 8th char when displaying the new time

[b]
11:59:5[color=red]9[/color]
0:00:00[color=red]9[/color]
[/b]

bigone5500:
I have recently gotten my clock sketch to work. It looks great and I like it. However, there is a small bug that I don't know how to fix and cannot find any info on what may be going on.

....

Any ideas?

It is a good idea to post your code so we can see where the problem lies.

Code would always help but in that case I'm 99% sure my answer #1 is the root cause

This is what I have done:

I changed the sketch from this:

void printTime(int character, int line, tmElements_t tm)
{
  String seconds, minutes;
  lcd.setCursor(character, line);
  lcd.print(tm.Hour);
  lcd.print(":");
  if (tm.Minute < 10)
  {
    minutes = "0" + String(tm.Minute);
    lcd.print(minutes);
  } else
  {
    lcd.print(tm.Minute);
  }
  lcd.print(":");
  if (tm.Second < 10)
  {
    seconds = "0" + String(tm.Second);
    lcd.print(seconds);
  } else
  {
    lcd.print(tm.Second);
  }
}

To this:

void printTime(int character, int line, tmElements_t tm)
{
  String seconds, minutes, hours;
  lcd.setCursor(character, line);
  if (tm.Hour < 10)
  {
    hours = "0" + String(tm.Hour);
    lcd.print(hours);
  }
  else
  {
    lcd.print(tm.Hour);
  }
  lcd.print(":");
  if (tm.Minute < 10)
  {
    minutes = "0" + String(tm.Minute);
    lcd.print(minutes);
  }
  else
  {
    lcd.print(tm.Minute);
  }
  lcd.print(":");
  if (tm.Second < 10)
  {
    seconds = "0" + String(tm.Second);
    lcd.print(seconds);
  }
  else
  {
    lcd.print(tm.Second);
  }
}

I will see if it works after noon time.

The above code change indeed fixed my issue with the extra digit when going from 2-digit hours to single digit.

Or you could add a space at the end if you want the hours to be only on 1 digit when possible i.e. Display 7:36:45 instead of 07:36:45 which does not look as nice

J-M-L:
Or you could add a space at the end if you want the hours to be only on 1 digit when possible i.e. Display 7:36:45 instead of 07:36:45 which does not look as nice

That would indeed make it look nicer. I may try that. Thanks.

I have a fully functional date and time clock now. It is a 12 hour clock which can be converted back to 24 hour easily. I have also (on my own!!!), figured out how to indicate AM or PM. I wanted to share it with the forum in return for helping me.

#include <LiquidCrystal_I2C.h>
#include <DS1307RTC.h>
#include <Wire.h>

LiquidCrystal_I2C lcd(0x27, 20, 4);  // Set the LCD I2C address

byte verticalLine[8] = {
  B00100,
  B00100,
  B00100,
  B00100,
  B00100,
  B00100,
  B00100,
  B00100
};

byte char2[8] = {
  B00000,
  B00000,
  B00000,
  B11100,
  B00100,
  B00100,
  B00100,
  B00100
};

byte char1[8] = {
  0b00000,
  0b00000,
  0b00000,
  0b00111,
  0b00100,
  0b00100,
  0b00100,
  0b00100
};

byte char3[8] = {
  0b00100,
  0b00100,
  0b00100,
  0b00111,
  0b00000,
  0b00000,
  0b00000,
  0b00000
};

byte char4[8] = {
  0b00100,
  0b00100,
  0b00100,
  0b11100,
  0b00000,
  0b00000,
  0b00000,
  0b00000
};

void setup()
{
  lcd.begin();

  createCustomCharacters();

  printFrame();
}


void loop()
{
  tmElements_t tm;

  if (RTC.read(tm)) {
    printDate(5, 1, tm);
    printTime(5, 2, tm);
  }
  else
  {
    if (RTC.chipPresent())
    {

    } else {

    }
    delay(9000);
  }
  delay(1000);
}

void printTime(int character, int line, tmElements_t tm)
{
  String seconds, minutes, hours;
  lcd.setCursor(character, line);
  if (tm.Hour < 10)
  {
    hours = "0" + String(tm.Hour);
    lcd.print(hours);
  }
  else
  {
    lcd.print(tm.Hour - 12);
  }
  lcd.print(":");
  if (tm.Minute < 10)
  {
    minutes = "0" + String(tm.Minute);
    lcd.print(minutes);
  }
  else
  {
    lcd.print(tm.Minute);
  }
  lcd.print(":");
  if (tm.Second < 10)
  {
    seconds = "0" + String(tm.Second);
    lcd.print(seconds);
  }
  else
  {
    lcd.print(tm.Second);
  }
  String am, pm;
  lcd.setCursor(13, 2);
  if (tm.Hour >= 10)
  {
    lcd.print("PM");
  }
  else
  {
    lcd.print("AM");
  }
}

void printDate(int character, int line, tmElements_t tm)
{
  lcd.setCursor(character, line);
  lcd.print(tm.Month);
  lcd.print("/");
  lcd.print(tm.Day);
  lcd.print("/");
  lcd.print(tmYearToCalendar(tm.Year));
}

void printFrame()
{
  lcd.setCursor(1, 0);
  lcd.print("------------------");
  lcd.setCursor(1, 3);
  lcd.print("------------------");
  lcd.setCursor(0, 1);
  lcd.write(byte(0));
  lcd.setCursor(0, 2);
  lcd.write(byte(0));
  lcd.setCursor(19, 1);
  lcd.write(byte(0));
  lcd.setCursor(19, 2);
  lcd.write(byte(0));
  lcd.setCursor(0, 0);
  lcd.write(byte(1));
  lcd.setCursor(19, 0);
  lcd.write(byte(2));
  lcd.setCursor(0, 3);
  lcd.write(byte(3));
  lcd.setCursor(19, 3);
  lcd.write(byte(4));
}

void createCustomCharacters()
{
  lcd.createChar(0, verticalLine);
  lcd.createChar(1, char1);
  lcd.createChar(2, char2);
  lcd.createChar(3, char3);
  lcd.createChar(4, char4);
}

Great Job!

One small suggestion for you would be to eschew the String class. Using it for concatenation can shoot holes in your RAM and eventually cause a crash. String is great on PCs with tons of RAM and garbage collection to clean up the holes it leaves. But on a microcontroller it is a thing to be avoided. It's never too soon to learn to use char arrays instead.

So I got home earlier and looked at my clock. When transitioning from PM to AM, all is well. So I got home at about 4PM and the clock has a trailing 9 on the seconds position....ARRRRRGGGHHHH!!!!!!

Back to the sketching board.

edit I have added a space after tm.Second on line 135. I will post back with my findings tomorrow.

  if (tm.Hour < 10)
  {
    hours = "0" + String(tm.Hour);
    lcd.print(hours);
  }
  else
  {
    lcd.print(tm.Hour - 12);
  }

That can’t be right.
What happens when tm.Hour is 10? Or 11? Or 12? Or 13?

As for formatting numbers, you would probably find the sprintf() function helpful.
More information here: sprintf | Liudr's Blog

So I added a space after the tm.Seconds. That didn't work either. I will try some other things and see what I can figure out.

Stay tuned.

why the *$€! do you use the String class when it’s absolutely totally unnecessary?

what about trying out this code for your printTime() function (did not test it)

void printTime(int character, int line, tmElements_t &tm)
{
  lcd.setCursor(character, line);

  if (tm.Hour > 12) {
    if (tm.Hour < 22) lcd.print(F("0"));
    lcd.print(tm.Hour - 12);
  } else {
    if (tm.Hour < 10) lcd.print(F("0"));
    lcd.print(tm.Hour);
  }

  lcd.print(":");

  if (tm.Minute < 10) lcd.print(F("0"));
  lcd.print(tm.Minute);

  lcd.print(":");

  if (tm.Second < 10) lcd.print(F("0"));
  lcd.print(tm.Second);

  if (tm.Hour >= 12) lcd.print(F(" PM  "));
  else lcd.print(F(" AM  "));
}

J-M-L:
why the *$€! do you use the String class when it’s absolutely totally unnecessary?

what about trying out this code for your printTime() function (did not test it)

void printTime(int character, int line, tmElements_t &tm)

{
  lcd.setCursor(character, line);

if (tm.Hour > 12) {
    if (tm.Hour < 22) lcd.print(F(“0”));
    lcd.print(tm.Hour - 12);
  } else {
    if (tm.Hour < 10) lcd.print(F(“0”));
    lcd.print(tm.Hour);
  }

lcd.print(":");

if (tm.Minute < 10) lcd.print(F(“0”));
  lcd.print(tm.Minute);

lcd.print(":");

if (tm.Second < 10) lcd.print(F(“0”));
  lcd.print(tm.Second);

if (tm.Hour >= 12) lcd.print(F(" PM  “));
  else lcd.print(F(” AM  "));
}

I used the string class due to the fact that the original author used it. It’s the only thing I knew to use.

You guys need to keep in mind that I am very new to this so the WTF are you doing this for comments are unnecessary. I do appreciate the help very much.

bigone5500:
WTF are you doing this for comments are unnecessary.

Comments about a fairly serious problem in your program are unnecessary? That will make it hard to help you.

aarg:
Comments about a fairly serious problem in your program are unnecessary? That will make it hard to help you.

That's not what I meant. It's the way it was worded and the way I perceived the reply. I took it as a crude comment such as I should have known better. That's all.

The sprintf() function seems like exactly the right tool for the job for you.
Please see my reply #11.

It is indeed good advice to avoid the String class.
There do exist functions for manipulating arrays of characters for use as strings (note the small s). Such functions are extremely useful in situations where you want to avoid the actual String class.

We tend to say things as we think about it... don't take it personally :slight_smile:

I disagree sprintf() is really useful in that case since you don't need to build up a string at all. Just print things as they come. Using sprintf() or sscanf() takes up lots of program space so use it carefully

J-M-L:
We tend to say things as we think about it... don't take it personally :slight_smile:

I disagree sprintf() is really useful in that case since you don't need to build up a string at all. Just print things as they come. Using sprintf() or sscanf() takes up lots of program space so use it carefully

It's all good brother! I'm having mental overload with all these suggestions really. My last change to the sketch ended up all fouled up. at 12PM, it said it was -2:00...what???

I am using the last code suggested to see if things work out well.