Digital clock on LCD 16x2

Hello everyone, I’m new to programmation and I am trying to implement a digital clock to be displaid on a 16x2 LCD without making use of a Real Time Clock module.

The program is intended to get the time by comparing the output of millis() (ie the time in ms since last reset) with an initial time set by the user.
The user should be able to set the time by pressing SELECT. When this is done, I want the hours to increment or decrement when PLUS or MINUS are pressed. Pressing OK should then move on to the minutes and then the seconds. When the seconds are done and OK is pressed, the program should store the output of millis() to get the “date” of the setup (relative to last reset). Adding the difference between the output of millis() at any time and the setup “date” to the initial time defined by the user would then give the actual time.

However, there are quite a lot of bugs in my code (which you can find attached to this post). As I can’t tell to what extend they are related with each other, I put a list of symptoms in the description that I have observed when testing my code.

I suspect a problem of variable type considering the recurrence of 255 (maximum for unsigned 8bit number) among the problems that I am facing.
I also think that their must be some timing issues in my SetTime() method.
Now, I’m a begginer and coding without being able to debug is just like hell to me :sob:

Could you please have a look at it and help me understanding what I’m doing wrong ?

DigitalClock.ino (6.89 KB)

I am trying to implement a digital clock to be displaid on a 16x2 LCD without making use of a Real Time Clock module.

Before you go much further you need to consider whether the accuracy provided by the millis() function is good enough for you project.

You will learn a lot implementing a clock using the Arduino but I would hate for you to put in all the effort required only to be disappointed by its accuracy.

/Users/john/Documents/Downloads/DigitalClock/DigitalClock.ino: In function 'char sep()':
/Users/john/Documents/Downloads/DigitalClock/DigitalClock.ino:158:1: warning: no return statement in function returning non-void [-Wreturn-type]

You mean "void sep()".

Your "Time" and 'initialTime" arrays are unsigned int and your constants are int (3600, 60) so the math is done in integers even when you store the result in an unsigned long. Try changing your constants to unsigned long: 3600UL, 60UL.

Expect your clock to be off roughly five minutes a day. The 16 MHz resonator is not as accurate as a quartz crystal.

Since Time and initialTime are arrays with three elements, in SetTime() you probably mean
for (int i=0; i<=2; i++)
or perhaps
for (int i=0; i<3; i++)
but not
for (int i=0; i<=3; i++)

Thanks for your help !

So I’ve changed sep() to void, made the for loop in SetTime run only three times and created unsigned long variables to store my constants (3600, 60 and 1000). You can find the modified code attached to this post.

And now… it’s still very strange. When the clock is set to 00:00:00, the display goes like this : 255:00:00 => 255:255:00 => 255:255:255 => 04:26:14255 => 04:26:15255… (keeps counting time as if it were 04:26:15).

The strangest thing is that if I wait a little bit after uploading my sketch and reset the board, it starts displaying the time normally. However, reseting two times in a row causes the same display as described above.

I’ve tried to add a 2 seconds delay in the setup and change the initial value of setupTime consequently but it is not much better.

When SELECT is pressed, it starts decrementing each section one by one (hours, minutes, seconds and hours again…). If the hours section for example is still 00, it will display 555. This causes the same kind of bug as described above.
If PLUS is then pressed, it increments by one and decrement by one right away each section in the same loop patern. OK still seems to get out of SetTime as the clock starts incrementing the seconds again.

I don’t get how that’s even possible since SetTime() shouldn’t do anything but updating the initial time and wait for OK to be pressed as long as neither PLUS nor MINUS are being used. I would expect it just to stop at the last time displaid and wait for instruction.

DigitalClock.ino (7.05 KB)

You changed the code so please repost the changed code (in code tags)

Sorry, I forgot to attach it. here it is.

DigitalClock.ino (5.22 KB)

I don't know where the "255"s and other strange numbers are coming from, but I can see that you could get a discontinuity, or sudden jump, in the time displayed.

I note that you initialise setupTime to 2000, and setupTime is used in seconds():

s = s+((millis()-setupTime)/UL1000); //add number of seconds since last setup

If you start calling seconds() before millis() reaches 2000, you will get a sudden jump in the time displayed at the point where millis() hits 2000. That could explain why adding a delay to setup() makes a difference - you could be avoiding the point where millis() is less than 2000. There are ways to avoid that without delaying setup() but if you intend to run your clock for an extended length of time, consider what will happen when millis() eventually wraps back to zero).

A couple of observations:

In the GetTime() processing, you call seconds() three times, once for the hours, once for the minutes and then again for the seconds. The value returned by the call to millis() that is done each time in seconds() might change at any point during this, which could cause you to get inconsistent hour minute and second values. Given that you would very quickly overwrite these values, you wouldn't even notice, but it is was up to me, I would avoid that sort of issue by arranging it to call seconds() only once and use the value returned to calculate the hours minutes and seconds.

I note you use mostly global variables in your functions. I would make more use of locals.