Components and supplies
Tactile Switch, Top Actuated
Arduino Nano R3
Alphanumeric LCD, 16 x 2
Trimmer Potentiometer, 10 kohm
Jumper wires
Project description
Code
Clock programme
arduino
Accurate clock with date just using and Arduino
Processing timer testing script
processing
This is the script for Processing that will read the milliseconds sent from the Arduino and compare it to the elapsed milliseconds in processing.
Arduino timer program
arduino
This program sends the number of elapsed milliseconds to the serial port evert 2 seconds.
Processing timer testing script
processing
This is the script for Processing that will read the milliseconds sent from the Arduino and compare it to the elapsed milliseconds in processing.
Clock programme
arduino
Accurate clock with date just using and Arduino
Arduino timer program
arduino
This program sends the number of elapsed milliseconds to the serial port evert 2 seconds.
Downloadable files
Clock LCD 16x2 Breadboard
Clock LCD 16x2 Breadboard
Clock LCD 16x2 Breadboard
Clock LCD 16x2 Breadboard
Clock LCD 16x2 Schematic
Clock LCD 16x2 Schematic
Comments
Only logged in users can leave comments
PietBos
8 months ago
Abandoned the project, so nou further use
itsfirepepper
a year ago
this is a perfect design and I love it because I don't have a RTC and I don't plan to get any anytime soon
orenji_san
2 years ago
How are the 6 parts of the code sent to the Arduino? are all joined in to a single file and sent that way?
Anonymous user
2 years ago
not sure if i've understood this or not. are you using the pc clock to correct the arduino time?
paulsb
2 years ago
Hi, No. The link to the PC is only an initial process to calculate the amount by which the Arduino clock is out. Either running fast or slow. That value is entered as the initial setting of the speedCorrection variable. The clock then runs independently making this speed correct adjustment each hour.
Anonymous user
2 years ago
Hi, I Have Successfully Adjusted The Time And Date But Can't Adjust The Year. Please Help Me Out. I Am Making This In TinkerCAD. (I Am Also Running A LED Dot Matrix Clock So I Can't Make It Now)
paulsb
2 years ago
Hi, Difficult to advise without more information. When you say you cannot set the year, what is happening? Are you just not seeing the option or is it showing and you cannot change it? Did you type in the code or copy and paste it? I would check the code to make sure there is not an error in it. Paul
Anonymous user
2 years ago
Umm, I Simulated It, I Felt Lazy To Make It In Real Life. ( I Copy Pasted The Code In TinkerCAD)
Anonymous user
2 years ago
Hi, which parts of code i do need to replace if I have LCD shield with KEYPAD. ? I was desperately looked for the watch like this for several years. And I still have 3 spare butons, the 6th button RESET is not defined here. Buttons defined: (where i would like to have your 3 butons). pls help :) int rk=analogRead(0); //UNO //DUE if(rk<50) {MINUTE_BUTTON;} //50 //75 else if(rk<195) {HOUR_BUTTON;} //195 //295 else if(rk<380) { ;} //380 //575 else if(rk<555) {MODE_BUTTON;} //555 //840 else if(rk<790) { ;} //790 //1023 //RESET NOT DEFINED
paulsb
2 years ago
Hi Sorry I am not really sure what you are asking. If it is to code the buttons then I think all you need do is replace the test for WHICHEVER_BUTTON == LOW with a test to achieve recognition of your button. E.g. for MODE_BUTTON replace if (digitalRead(MODE_BUTTON) == LOW) { ... } with if ((rk < 555) && (rk > 379)){ ... } But I have not used this display so I cannot check if that is right. Paul
Anonymous user
2 years ago
greetings sir, I really appreciate your projects, how can I add AM or PM function automatically in this clock could you tell me, please ??
paulsb
2 years ago
Hi Sorry I have not been on here for a while. To show AM/PM you just need to check if iHours is > 12 in ShowTime(). If it is then deduct 12 from it and show it as pm, otherwise show it as am. Here is the replacement ShowTime() code that does this. void ShowTime(unsigned long value) { // Alternative to show am/pm // Update display once a second // or when rolls over midnight String ampm; if ((value > lastTime + 1000) || (value < lastTime)) { lastTime = value; unsigned long iHours; unsigned long iMinutes; unsigned long iSeconds; SplitTime(value, iHours, iMinutes, iSeconds); // Display the time on line 0 lcd.setCursor(0, 0); if (iHours > 12) { iHours = iHours - 12; ampm = "pm"; } else { ampm = "am"; } lcd.print("Time: " + FormatNumber(iHours) + ":" + FormatNumber(iMinutes) + ":" + FormatNumber(iSeconds) + ampm); } }
Anonymous user
2 years ago
I'm new to this and have made an alteration to the ShowTime function to convert the output to 12hr time. While experienced folk could probably acheive this with less code, my solution seems to work fine. Replace the ShowTime() function with the following. void ShowTime(unsigned long value) { // Update display once a second // or when rolls over midnight if ((value > lastTime + 1000) || (value < lastTime)) { String amPm; lastTime = value; unsigned long iHours; unsigned long iMinutes; unsigned long iSeconds; unsigned long theHour; SplitTime(value, iHours, iMinutes, iSeconds); switch (iHours) { case 0: // It's 12 oclock am theHour = 12; amPm = "am"; break; case 1: // It's 1 oclock am theHour = 1; amPm = "am"; break; case 2: // It's 2 oclock am theHour = 2; amPm = "am"; break; case 3: // It's 3 oclock am theHour = 3; amPm = "am"; break; case 4: // It's 4 oclock am theHour = 4; amPm = "am"; break; case 5: // It's 5 oclock am theHour = 5; amPm = "am"; break; case 6: // It's 6 oclock am theHour = 6; amPm = "am"; break; case 7: // It's 7 oclock am theHour = 7; amPm = "am"; break; case 8: // It's 8 oclock am theHour = 8; amPm = "am"; break; case 9: // It's 9 oclock am theHour = 9; amPm = "am"; break; case 10: // It's 10 oclock am theHour = 10; amPm = "am"; break; case 11: // It's 11 oclock am theHour = 11; amPm = "am"; break; case 12: // It's 12 oclock am theHour = 12; amPm = "pm"; break; case 13: // It's 1 oclock pm theHour = 1; amPm = "pm"; break; case 14: // It's 2 oclock pm theHour = 2; amPm = "pm"; break; case 15: // It's 3 oclock pm theHour = 3; amPm = "pm"; break; case 16: // It's 4 oclock pm theHour = 4; amPm = "pm"; break; case 17: // It's 5 oclock pm theHour = 5; amPm = "pm"; break; case 18: // It's 6 oclock pm theHour = 6; amPm = "pm"; break; case 19: // It's 7 oclock pm theHour = 7; amPm = "pm"; break; case 20: // It's 8 oclock pm theHour = 8; amPm = "pm"; break; case 21: // It's 9 oclock pm theHour = 9; amPm = "pm"; break; case 22: // It's 10 oclock pm theHour = 10; amPm = "pm"; break; case 23: // It's 11 oclock pm theHour = 11; amPm = "pm"; break; } // Display the time on line 0 lcd.setCursor(0, 0); lcd.print("Time: " + FormatNumber(theHour) + ":" + FormatNumber(iMinutes) + ":" + FormatNumber(iSeconds)+ "" + amPm); } } I hope this works for you.
Anonymous user
2 years ago
This is very impressive. Thanks for sharing. I presumed (wrongly) that the time lost would be random.
paulsb
2 years ago
Thanks. I have now had the clock running for 2 weeks and it has gained 1 second, taking the reading at the same time each day so at the same point after the speed adjustment is made. I feel his definitely confirms that the internal clock is consistent. I am going to change the speed adjustment by 3 milliseconds to compensates for the gain and hopefully increase the accuracy,
Anonymous user
2 years ago
Hey I was wondering if you could make the SCHEMATICS usable to Arduino Uno R3. You said in components and supplies you could use any Arduino. Thank You So Much
paulsb
2 years ago
Hi. The Uno R3 has a similar pin configuration to the Nano and the labels are the same. Look at the circuit diagram to see the pins that the wires are connected to and simply connect to the same pins on the UNO. Hope this helps.
frenchy22
2 years ago
Hello, Very nice project, but I think that, instead of replacing the millis() function by an interrupt and of rewriting the delay() function, it is possible to take into account the rolling out of the millis() function every 50 days by the following code : [code] unsigned long actualTime, lastTime, elapsedTime; ... actualTime=millis(); if (actualTime < lastTime) // The millis counter has rolled out elapsedTime=0xFFFFFFFFul-lastTime+actualTime; else elapsedTime=actualTime-lastTime; [/code] And you reset the delay when you want by copying actualTime into lastTime.
paulsb
2 years ago
Hi, Many thanks for your suggestions.
paulsb
2 years ago
HI, I have looked further into your suggestion and the issue is the clock speed adjustment and the setting of the actual time. As you cannot amend Mills() you would need to accumulate the speed adjustment to reflect the variation from true milliseconds elapsed. This would eventually exceed the maximum value for the variable - mind you after a very very very long time. As millis() only counts the milliseconds since power up, you would also need to keep track of the time after midnight that the system was powered up to show the real time represented by the elapsed millis() and adjust this when set time is used. This adjustment could possibly be merged with the cumulative speed adjustment, but it becomes messy. I therefore feel that using the interrupt and our own counter is cleaner and simpler.
Anonymous user
2 years ago
How connect the LCD with i2c Connection?
paulsb
2 years ago
Hi, I have not used an LCD with an i2c connection, however there are a number of tutorials showing how to use it with an Arduino. I believe you need to connected the SDA and SCL connections to pins A4 and A5 and use the following libraries: Wire.h LiquidCrystal_I2C.h You also have to find out the address that the LCD is using - again see the tutorials (Common addresses are 0x3F and 0x27.), and initialise it with the correct address, eg for 0x3F: LiquidCrystal_I2C lcd ( 0x3F , 16 , 2 ) ; You may also need to make minor changes to the lcd commands.
Anonymous user
2 years ago
Like you said "it appears that the inaccuracy is consistent" , I can assure you that you are correct. I have a similar clock setup running for 7 years ( Big 7 seg display with arduino). Ever after software correction for lost time, it slows down 10 minutes every 6 months.
Nelson_Lee
2 years ago
Hello. Thanks for sharing your project. I have been studying your code because I wanted to make a project that needs to perform some tasks some days in a week at set times. I am stuck the part of you calculating the Julian date. Can you please share the source or explain how you get the formula of the conversion? I tried googling but what I managed to find doesn't seem to match up to your formula.
Anonymous user
3 years ago
greetings sir, I really appreciate your projects, how can I add AM or PM function automatically in this clock could you tell me, please ??
paulsb
2 years ago
Hi Sorry I have not been on here for a while. To show AM/PM you just need to check if iHours is > 12 in ShowTime(). If it is then deduct 12 from it and show it as pm, otherwise show it as am. Here is the replacement ShowTime() code that does this. void ShowTime(unsigned long value) { // Alternative to show am/pm // Update display once a second // or when rolls over midnight String ampm; if ((value > lastTime + 1000) || (value < lastTime)) { lastTime = value; unsigned long iHours; unsigned long iMinutes; unsigned long iSeconds; SplitTime(value, iHours, iMinutes, iSeconds); // Display the time on line 0 lcd.setCursor(0, 0); if (iHours > 12) { iHours = iHours - 12; ampm = "pm"; } else { ampm = "am"; } lcd.print("Time: " + FormatNumber(iHours) + ":" + FormatNumber(iMinutes) + ":" + FormatNumber(iSeconds) + ampm); } }
willois
2 years ago
I'm new to this and have made an alteration to the ShowTime function to convert the output to 12hr time. While experienced folk could probably acheive this with less code, my solution seems to work fine. Replace the ShowTime() function with the following. void ShowTime(unsigned long value) { // Update display once a second // or when rolls over midnight if ((value > lastTime + 1000) || (value < lastTime)) { String amPm; lastTime = value; unsigned long iHours; unsigned long iMinutes; unsigned long iSeconds; unsigned long theHour; SplitTime(value, iHours, iMinutes, iSeconds); switch (iHours) { case 0: // It's 12 oclock am theHour = 12; amPm = "am"; break; case 1: // It's 1 oclock am theHour = 1; amPm = "am"; break; case 2: // It's 2 oclock am theHour = 2; amPm = "am"; break; case 3: // It's 3 oclock am theHour = 3; amPm = "am"; break; case 4: // It's 4 oclock am theHour = 4; amPm = "am"; break; case 5: // It's 5 oclock am theHour = 5; amPm = "am"; break; case 6: // It's 6 oclock am theHour = 6; amPm = "am"; break; case 7: // It's 7 oclock am theHour = 7; amPm = "am"; break; case 8: // It's 8 oclock am theHour = 8; amPm = "am"; break; case 9: // It's 9 oclock am theHour = 9; amPm = "am"; break; case 10: // It's 10 oclock am theHour = 10; amPm = "am"; break; case 11: // It's 11 oclock am theHour = 11; amPm = "am"; break; case 12: // It's 12 oclock am theHour = 12; amPm = "pm"; break; case 13: // It's 1 oclock pm theHour = 1; amPm = "pm"; break; case 14: // It's 2 oclock pm theHour = 2; amPm = "pm"; break; case 15: // It's 3 oclock pm theHour = 3; amPm = "pm"; break; case 16: // It's 4 oclock pm theHour = 4; amPm = "pm"; break; case 17: // It's 5 oclock pm theHour = 5; amPm = "pm"; break; case 18: // It's 6 oclock pm theHour = 6; amPm = "pm"; break; case 19: // It's 7 oclock pm theHour = 7; amPm = "pm"; break; case 20: // It's 8 oclock pm theHour = 8; amPm = "pm"; break; case 21: // It's 9 oclock pm theHour = 9; amPm = "pm"; break; case 22: // It's 10 oclock pm theHour = 10; amPm = "pm"; break; case 23: // It's 11 oclock pm theHour = 11; amPm = "pm"; break; } // Display the time on line 0 lcd.setCursor(0, 0); lcd.print("Time: " + FormatNumber(theHour) + ":" + FormatNumber(iMinutes) + ":" + FormatNumber(iSeconds)+ "" + amPm); } } I hope this works for you.
Anonymous user
4 years ago
Hi, which parts of code i do need to replace if I have LCD shield with KEYPAD. ? I was desperately looked for the watch like this for several years. And I still have 3 spare butons, the 6th button RESET is not defined here. Buttons defined: (where i would like to have your 3 butons). pls help :) int rk=analogRead(0); //UNO //DUE if(rk<50) {MINUTE_BUTTON;} //50 //75 else if(rk<195) {HOUR_BUTTON;} //195 //295 else if(rk<380) { ;} //380 //575 else if(rk<555) {MODE_BUTTON;} //555 //840 else if(rk<790) { ;} //790 //1023 //RESET NOT DEFINED
paulsb
2 years ago
Hi Sorry I am not really sure what you are asking. If it is to code the buttons then I think all you need do is replace the test for WHICHEVER_BUTTON == LOW with a test to achieve recognition of your button. E.g. for MODE_BUTTON replace if (digitalRead(MODE_BUTTON) == LOW) { ... } with if ((rk < 555) && (rk > 379)){ ... } But I have not used this display so I cannot check if that is right. Paul
Anonymous user
4 years ago
not sure if i've understood this or not. are you using the pc clock to correct the arduino time?
paulsb
2 years ago
Hi, No. The link to the PC is only an initial process to calculate the amount by which the Arduino clock is out. Either running fast or slow. That value is entered as the initial setting of the speedCorrection variable. The clock then runs independently making this speed correct adjustment each hour.
KetanMiyatra
4 years ago
How connect the LCD with i2c Connection?
paulsb
2 years ago
Hi, I have not used an LCD with an i2c connection, however there are a number of tutorials showing how to use it with an Arduino. I believe you need to connected the SDA and SCL connections to pins A4 and A5 and use the following libraries: Wire.h LiquidCrystal_I2C.h You also have to find out the address that the LCD is using - again see the tutorials (Common addresses are 0x3F and 0x27.), and initialise it with the correct address, eg for 0x3F: LiquidCrystal_I2C lcd ( 0x3F , 16 , 2 ) ; You may also need to make minor changes to the lcd commands.
Anonymous user
4 years ago
Hey I was wondering if you could make the SCHEMATICS usable to Arduino Uno R3. You said in components and supplies you could use any Arduino. Thank You So Much
paulsb
2 years ago
Hi. The Uno R3 has a similar pin configuration to the Nano and the labels are the same. Look at the circuit diagram to see the pins that the wires are connected to and simply connect to the same pins on the UNO. Hope this helps.
Anonymous user
4 years ago
This is very impressive. Thanks for sharing. I presumed (wrongly) that the time lost would be random.
paulsb
2 years ago
Thanks. I have now had the clock running for 2 weeks and it has gained 1 second, taking the reading at the same time each day so at the same point after the speed adjustment is made. I feel his definitely confirms that the internal clock is consistent. I am going to change the speed adjustment by 3 milliseconds to compensates for the gain and hopefully increase the accuracy,
Anonymous user
4 years ago
Hi, I Have Successfully Adjusted The Time And Date But Can't Adjust The Year. Please Help Me Out. I Am Making This In TinkerCAD. (I Am Also Running A LED Dot Matrix Clock So I Can't Make It Now)
Anonymous user
2 years ago
Umm, I Simulated It, I Felt Lazy To Make It In Real Life. ( I Copy Pasted The Code In TinkerCAD)
paulsb
2 years ago
Hi, Difficult to advise without more information. When you say you cannot set the year, what is happening? Are you just not seeing the option or is it showing and you cannot change it? Did you type in the code or copy and paste it? I would check the code to make sure there is not an error in it. Paul
frenchy22
4 years ago
Hello, Very nice project, but I think that, instead of replacing the millis() function by an interrupt and of rewriting the delay() function, it is possible to take into account the rolling out of the millis() function every 50 days by the following code : [code] unsigned long actualTime, lastTime, elapsedTime; ... actualTime=millis(); if (actualTime < lastTime) // The millis counter has rolled out elapsedTime=0xFFFFFFFFul-lastTime+actualTime; else elapsedTime=actualTime-lastTime; [/code] And you reset the delay when you want by copying actualTime into lastTime.
paulsb
2 years ago
Hi, Many thanks for your suggestions.
paulsb
2 years ago
HI, I have looked further into your suggestion and the issue is the clock speed adjustment and the setting of the actual time. As you cannot amend Mills() you would need to accumulate the speed adjustment to reflect the variation from true milliseconds elapsed. This would eventually exceed the maximum value for the variable - mind you after a very very very long time. As millis() only counts the milliseconds since power up, you would also need to keep track of the time after midnight that the system was powered up to show the real time represented by the elapsed millis() and adjust this when set time is used. This adjustment could possibly be merged with the cumulative speed adjustment, but it becomes messy. I therefore feel that using the interrupt and our own counter is cleaner and simpler.
Anonymous user
4 years ago
Like you said "it appears that the inaccuracy is consistent" , I can assure you that you are correct. I have a similar clock setup running for 7 years ( Big 7 seg display with arduino). Ever after software correction for lost time, it slows down 10 minutes every 6 months.
paulsb
4 Followers
•8 Projects
32
45
bossje
9 months ago
Do you have a solution for leap years?