Arduino ClocK Project : Arduino Projects

 in this tutorial we're going to create adigital clock we have a mode-button where you can set if you want to changethe hours, the minutes and the seconds and as you can see I change it with aset-button and if we wait for 5 seconds and do nothing the clock will resume its normal operation I've split this tutorial in two parts we start with a very easy clock where the green button adjusts the hours and theblue button adjusts the minutes in the second.

 more advanced part, we're going tocreate the menu you just saw on top of this clock there's a tiny animationand I'm also show you how to create this in the description of this video you find a chapter list so you can jump to the chapter of yourpreference However, I advise you to follow the complete tutorial so you can learn from my mistakes and build this clock step-by-step for this tutorial you'll need several componentsan Arduino, a breadboard an OLED display,

 two push buttons and 9 jumper wires male-to-male in the description of this video you find linksto web shop selling these components every project starts with a plan and I also receive questions like:how can I do this project I don't know where to start I want to build this and that and I know what I want but I don't know how tosplit it up and create this project on my Arduino so therefore I have a smallpresentation to show you how

 I created this clock if you don't like this, then you can in the description find all the chapters with timestamps and you can directly skip to building the circuit however I advise you to watch this tinypresentation because you can learn how to structure your project our clock's main function is to display time we want to display hours, minutes and maybe seconds but we also need to adjust the time so we want to adjust the hoursminutes and even seconds so how can we do this? we can use a single button andthis button increases a minute every time it's being pressed but there's a tiny problem with this imagine the clock is just 1 minute behind then you have topress once and you're done but what if it is running 1 minute too fast? then you have to press it 720 timesif it's a 12-hour clock and even 1440 times ifthis is a 24-hour clock so that's not very useful so we can add another buttonso we have two buttons an hours button, which change the hours and a minute button which change the minutes we might even have to have to add a third buttonbecause

 we also like to reset the seconds there is no use to setting the secondsto a certain position like 39 so you want to reset it to zero the moment your seconds need to hit zero after you thought about these solutions then you have to think in components so we'd like to display the time therefore we need a display and we need two buttons: one for the hoursand one for the minutes and maybe a third one if you want to reset the seconds then you have to think about how this could look when you design your clock so, this might be a clock it shows the time we have our hours button and our minutes button and on the top you see two bars that's an animation 

and that's whatwe're going to make I've split this up in 5 steps first we're going to build a clock with delay() then we're going to build a clock using millis() then we're going to add an animation then we're going to add a debounce to the buttonsI'll explain in that chapter what that means and last we're going to addinterrupts to the buttons in the second part of this tutorialwe're going to look into the clock as you saw just saw in the demonstration our first step is to add the OLEDdisplay to the center of our breadboard make sure there is enough space to addtwo buttons later also keep in mind during this tutorial, that your pinlayout of the OLED display might differ for example the "serial data pin" and the "serial clock pin" might be on a different position it doesn't matter for your clockbut you have to keep in mind to use the correct pins when you'reconnecting these to your Arduino our next step is to add two buttons make sure that they overlap this tiny gap in the middleof your breadboard we're now going to make our ground connections all pins in this blue line are connectedwith each other so we're going to connect the right pin of the green and the blue button to this rail via this wire and the other black wire our display has a GND connection which is also connected to the same horizontal rail on our breadboard We're now going to connect the wires to our Arduino the first wire is the ground which goes from here from the - rail to the ground onour Arduino the red wire goes to the 5V of the Arduino it is connected to the VCC of our display the yellow wire is the serial clock which goes to A5 on the Arduino and the serial data which goes to A4 on the Arduino the last step is to connect the blue button via the blue wire to pin number 2 and the green button via the white wire to pin number 3 on the Arduino now that we finished our circuit we can now have a look at the code if we look at the librarieswe're only using one that's the U8g2 library so I'm going to tools -> manage libraries then we're going to search for U8g2 and then you see here U8g2 by Oliver I already have installed this library but you can install it if you haven't already then we continue, 

we have 3 different variables the maximum number of hours is 24, actually 23: 0 to 24 so 24 values so a byte is sufficient to store these the same goes for minutes and theseconds then we have two constants defined:two integers for the PIN_BUTTON_HOURS and PIN_BUTTON_MINUTES and then we also have two states so the state for the button hours and for the minutes button and they're both HIGH and as I showed you here in this note it actually is a counter intuitive thingbecause you think when I press the button it's HIGH and when I release thebutton it's LOW but we're using this input pull up here on line 62 I'll show you that in a minute but then because of the pull up when there is nobutton pressed the value is HIGH and when you press it becomes LOW then we have here on line 54a timeString with 9 positions and that's basically used to storethe string which we are going to show on the screen and that's something I show you as well when we're going to the printing / drawing function here we define our screen for the U8g2 library,

 with all the pins and this is for my SSD1306 display but if you have a different display onthis website from Olli Kraus you can see exactly which one you need then we continue to the setup()where we set the PIN_BUTTON_HOURS which we have defined over herewhich in pin number 3 and we enable the input pull-upso that's the pull-up resistor which is built-in in your Arduino the same for the minutes then we use the U8g2 object and say "setFont" so we change the default font of the U8g2 library into "logisoso28" and that font exactly fits into my screen you can you can look at the U8g2 website for other fonts but this one with the size of 28 fits perfectly when we're showing the time then we tell U8g2 that we're ready with the configuration and it can begin in the loop() we check if the button has been pressed so we store the currentstate of the button of the hour button in with the digitalRead and store it inthe buttonHourState and we check if it's LOW if it's LOW we increase the number of hours same for the minutes, so if the buttonMinutsState is LOW then we increase the minutes and then we have several checksbecause if we have more than 59 seconds it means 1 minute has been passed so on line 85,

 we reset the number of seconds and increase the minutes the same we do for the the minutes and the same do we do for the hoursto see if a day has elapsed the trick is that we first needto check the seconds, then the minutes then the hours, if you do it the otherway around it doesn't work very well because if we increase here the minuteswe need to check if we already go past the 59 and if you do theopposite then you can have 60 seconds then we tell U8g2 to draw the first pagethat's the way U8g2 works and then you have a do-while loop and it repeatsuntil there is no next page anymore on line 107 we see something new it's sprint_P() maybe you know, sprintf() is forformatted strings to print but the trick here with the underscore P is that we use program memory instead of RAM RAM is a very sparse thing on the Arduino so if you can use program memory we reduce the load on the RAM well what we do is when you see PSTR that means Pointer to STRing so what we do is this string we are converting it to a pointer and we store the formatted string into the variable timeString this looks a little bit odd but what it is is that we say here:two decimals then we use the colon and then we use %02d so here there is no zeroand here is %02d that means that we're adding a leading zero so itbecomes 01, 02, 03 till we are at 10 and the same goes here for the seconds sohere we define how our string looks on the screen and we store it into the timeStringthen we draw the string on the screen so we print it on x position 0y position 45 and we're drawing the timeString then we wait for a second andincrease the seconds and then the whole loop starts again I'm now going to upload this code to my Arduinoand show you what it looks like I've uploaded code to my Arduino and as you can seethe clock is working so let's adjust the hours by pressing the green button that's not very easy to do and if I press the minute button it's also very hardto increase the minutes by one so what is causing this? well the reason for this is we are using delay delay doesn't wait for several milliseconds delay just pauses the whole processorfor several milliseconds so what's so what's happening is that because we're pausing the whole processor for one second it is fairly hard to detect if a button is pressed you have to exactly press the button atthe right moment in order to increase the hours or the minutes that's not very useful for our clock so we're going to solve this by using millis() so let's have a look at a millis() code well, 

the begin is all the same but here on line 58 there is a new variable I've created an "unsigned long" in which I store the current millis so the amount of milliseconds elapsed since the Arduino was started then we have an another variablethat's the elapsedTimeUpdateMillis basically what it does is to storethe amount of time elapsed since the last time the screen was updated then we have an unsigned long: lastTimeUpdateMillis and that's the timestamp when wedid the last update of our screen then we have the constructor for the U8g2which is the same as in the previous example the setup() is the same but in the loop() there's something new here on line 83 we update the currentMillis variablewith the current amount of millis elapsed you can also take into account thatmillis() itself also takes some time and I looked it up and I found this website on line 82 and they showed that it takes 1.812 micro seconds so that's 0.001812 milli seconds I'll leave it for nowbut you can take it into into account if you want to then we're going to calculate the amount of time elapsed since the last time update on the screen so we take the current timestamp and subtractthe last time we updated our screen then we check if the buttons are pressed we check if there are minutesand hours and seconds which we need to update but for the millis line 118 is interestingbecause there is no delay() so we need to check if there is enoughtime passed so here we check if the elapsed time between two updates is more than 1000ms if so, 

we increase it with one and then we update the lastTimeUpdateMillis with the current timestamp but there's something which I'd like to explain to you first I thought that this would be suffice so I just stored the current timestamp and I'm done but what I noticed is that sometimes it takesmore than 1000ms to update the screen so what happens is that it's not exactly on the millisecond cycling of the loop() function so if the loop execution takes exactly 100ms then on 1000 is not larger than 1000 so then you have like 100ms in  the next iterationwhich makes it 1100 and then you can't do anything with that 100ms which you are to late so let's say I have 1200ms in my elapsedTimeUpdateMillis so this if statement is TRUEso update the seconds updated with the timestampso far so good but I'm already missing 200ms because I updated timestamp with the currentTime so that is 1200 but this was saving my trouble with the time drift because I now subtract the elapsedTimeUpdateMillis so in this example 1200 minus the 1000 which is 200 so what happens is that the lastUpdateMilliswill be the correct timestamp so it only takes 800ms for the next secondto update and saves us a lot of time drift so you have to maybe re-read this and just read the code a little bit slower for yourself to understand this but basically what we do is we want to avoid time drift as much as possible because it will slow down of speed upthe clock this is all the same as we had in the previous example so I'm now going to upload this codeto my Arduino and show you what it looks like I've uploaded the millis() sketch and we're now going to see what happensif you press the button for the hours so I can now easily adjust the hours and alsothe minutes are working so now we're going one step further and we're goingto add animation to our clock the animation is quite simple webasically draw a bar and this bar shows you the percentage of the secondselapsed so we need to add another variable and that's here on line 65and it's the percentage of second elapsed that's zero and the nice thing about this animation is that it needs to be updated as fast as possible because if we wait for one full second then every time a second has elapsed so thisvalue is zero so you won't see any bar graph so what I did: I added here twolines, sorry no I'm too fast, here on line 130 we calculate the percentage ofseconds elapsed so we take the elapsedTimeUpdateMillis and divide it by 1000.0 why this point 0? well then it becomes a floatingpoint and with the division you want to have a floating point as a result then we use this percentage because the percentage it will be 1 for a 100% 0.5 for 50% so we can use that to draw a bar and our screen is 128pxwidth so we have 128 values: 0-127 so that's the complete width of the screen so we first draw this box on line 137 which is on x0 y0 then we have a width and the height so the width is 127 minus 127 multiplied by our percentage and the height of the bar is 2 the second bar is drawn at a Y of 3 so theheight was 2 from the first one so there's one pixel line as a separatorand we do now the 127 times the percentage of seconds elapsedwith a height of 2 so basically they are the opposite ofeach other all the other lines are still the same so I'm now going to showyou how this animation looks on your Arduino as you can see our animation isworking you see the yellow bars on top moving from left to rightalso the hour button is still working and the minute button works as well there is one tiny thing what we like to fix if I hold down for example the minute buttonthe screen is kind of flickering the reason for this is that the update speedof the minutes depends on the speed of the Arduino we're going to solve this by a so calleddebounce and I'm going to show you how this works so let's add some debounce to our buttonsand with debounce we're kind of controlling the way the button respondsindependent of the speed of the Arduino so what we did was we defined a constanthere which is the DEBOUNCE_TIME a hundred means that a button will betriggered at most every 100ms so even if I press it twice during 100msthe button will only be triggered once so for every button we need to define the elapsed button millis and the previous button millis and we have that for the hours and herefor the minutes so what we check is, we store in this variable how much time has elapsed since the last time I pressed the button and this is the timestamp for the last time the button was pressed and these are both unsigned longsince you might want to adjust the time while the clock has been runningfor many times so then integer is definitely not enough so then we're going to our code where we do the calculation so this is still thesame we store millis() in the currentMillis but here we calculatethe elapsed time update, 

button hour millis and the button minute millis because if the elapsed time is larger than the button debounce time then wecan check if the button has been pressed if not, we don't have to check it becausewe can't trigger a button two times within the debounce time so then we read our button state but we also update the previousButtonHoursMillis with thecurrent timestamp and the same goes for the minutes over here then we again check if seconds is larger than 59 minutes, hours, 

all the same also here thepercentage calculation is all the same so nothing changes atexcept that we now checks if the elapsedButtonMillis is larger than theBUTTON_DEBOUNCE_TIME so I'm now going to upload this code to my Arduinoand show you how this works I've uploaded my debounce sketch to the our Dino and whenI hold my in minute button you see that the minutes will increase at a steadyspeed this is because we added the debounce to our minute increase buttonwe're now going a step further by using interrupts so let's have a look at interrupts maybeyou've already followed one of my tutorials on buttons and interrupts butI'm going to briefly introduce this to you again so one of the things we wantto do with interrupts is attach them to our pins and that's something we do overhere on line 84 so we have an interrupt and that means that we don't have tocheck all the time if a button is pressed what happens is that theinterrupt as a name says will interrupt the program on a certain condition sowhat we say here is we say falling and that means that when we press the buttonthe interrupt will be triggered and the interrupt is actually a function so thefunction hours both impressed interrupts will be triggered if the pin buttonhours will be falling you also have rising that's when thebutton is released and you have also change with chains is another thing wewant because if you press the button it will be triggered and then when yourelease the button it will be triggered again so you can never increase by oneit will always be triggered twice so then we have some weird flags over hereand that's because when I ran into us when I started my Rd now it wasn'tshowing all zeros what I was showing was 140 hours and 140 minutes and it turnedout that there were still some interrupt triggers left in the queue and thereforeon startup they were triggered but the problem was that I don't want them to betriggered only when I press the button and the trick was that you can clear thecue when using these command commands here on line 95 and 96 keep in mind thatonly Rd know you know there are only two pins which allow interrupts and that'sbeen - and pin three so if you use for example pin nine and ten you can't useinterrupts on these pins if you have a different type of Rd know for exampleOmega has a lot more which interrupts so keep that in mindbecause otherwise it can take a while until you understand you figure out thatthere is no interrupt on the pins you're using so I split it up my code a littlebit as you can see here also with a function draw screen on the end and drawscreen does nothing else than all the draw methods we already had but for ushere these are interesting this is the our button pressed interrupt so it willbe triggered when we press that button and this is the same code as we had in aprevious example but now moved to a function this is for the example butnormally you want to make your interrupt function as small as possible sobasically what you want is increase the hours and only increase the minutes andall the checks you want outside of the function of your interrupt but for thistutorial purpose I just put it over here so you better understand what's going onso I'm now going to upload these codes to the Arduino and show you how thebutton works with interrupts so this is our running sketch on your Dino with ourinterrupt code as you can see I can still change the hours and the minutesone big difference with the last sketch is that I can when I press and hold downthe minutes button it only increases once this is because the interrupt istriggered but you have to release the button until you can trigger it again ina spring feast sketch the triggering was read in the loop so it checkscontinuously whether or not you have pressed the button this concludes thefirst clock we're now going to continue with the second clock where we're goingto use the mode and set buttons in the second part we're going to make aclock which is using a mode and set button the advantage of this is thatit's a very versatile you can add multiple modes without having to addanother button so how does this mode button works well the clock starts bydisplaying the time and when you press the button you can adjust the hours thenthe minutes you can reset the seconds and if you press the mode button againit starts by displaying the time when you press the button again it goes tohours minutes etc

 the set button changes time depending on the mode you're inso in the hours mode you can change the hours in the minutes mode you can changethe minutes and in the second mode you can reset the seconds so this is what itlooks like you have an animation running like in the previous clock you have atime you have a mode you have a set button but that's one different thingyou have a position marker this position marker indicates what you are changingso here you are changing the hours the minutes or the seconds in the next stepswe're going to implement first a mode set clock without interrupts andsecondly we're going to create a clock with interrupts I'm going to show youhow we can do this so we're going to create a clock whichhas a mode button and a set button the structure is basically the same as aprevious clock but there are some differences for example I've renamed allthe our buttons to the mode button and all the minutes buttons to the setbutton so we also have new D bounds here I've separated the mode and a set buttonwith different debounce times and here you also see some constants defining themodes so I have a mode to show the time and mode to set the seconds the minutesand the hours so in the background I'm using just numbers for this but it's alot easier to read the code when there is this name instead of saying mode iszero you have no clue but 0s so we need a variable to store the current nodethat's here on line 78 I don't use it int because about is sufficient we onlyhave four numbers to stores 0 1 2 & 3.

 so this setup remains the same and here online 100 we read the state of the pin button mode and check if this one is lowand then we activate the button mode handler function and the same goes forthis set button then we call the set handler we check the time that's anotherfunction and the check time is here just to check if there's a minute elapsed anhour elapsed or a day elapsed and here is something new because here we checkif the current modish show time and if so then we increase the seconds andincrease seconds is here at the bottom we check if the time has elapsed andthen we update the previous time millets etc I've told this in the previousexample so then we if it's not in the show time mode so basically we'resetting a value for the hours the minutes or the seconds then it justupdates the previous time update nearly with the current releaseit draws the screen so let's have a look at these handlers well for the motor isvery simple what we do we if the demands time has elapsed of course we incrementthe current mode so if you are in multi row which is showing the time you doplus plus which is the same as plus one so then we are having the set hours etcbut there is no fourth mode the highest mode you can have is mode number threeso if we reach the four because the previous was three so now with currentmode is four then we reset it back to zero and in that way you can press themode button all the time and just iterate over the four modes we're havingthe set button does something more because the set button works dependingon the modes you're in so what we do is we check if the current mode is setseconds and if so we reset the seconds but if the current mode is minutes thenwe increase the minutes and if the career mode is hours we increase thehours if you want to set an alarm for example you create a custom mode forthat then you can add another if checking if the mode is set alarm orstopwatch or whatever so let's have a look at the draw screen function herebecause I've changed something as well if the current mode is not show timethat means were setting the hours the minutes or the seconds so what we do weneed to draw a triangle and a triangle indicates if we're setting the hoursminutes or seconds so if you're setting for example the minutes there's a tinytriangle on top of the minute number so you know you're changing that value soyou see a lot of numbers here and I'm going to explain to you what they meanso first here this is the first number this is the x position and the xposition is the current it's minus one sorry for emote numberone it's zero and in mode number three it's two and we're doing this becauseI've splitted the screen in three parts.

 so I want depending on the mode draw thetriangle on a third of the screen so here I'm multiplying the current modeminus one times 43 so if I'm in mode one minus one is zero times 43 plus five isfive and the thing is that this 43 is a third of 128 and I can choose floatnumbers so I made it this way and five is some kind of Martian I don't want thetriangles to exactly be one third of the screen I wanted one third of the screenminus five pixels on both sides the Y position is zero so that's a four firstmost left point of the triangle but what we then do is we take the current modeand here we did minus one here we don't the x 43 minus five so that's our topright point of the triangle and it's on Y position zero so now actually we'vedrawn if you draw a line between those two points we draw a horizontal line soif you look a little bit further then you see here the current mode minus onetimes 43 so this is the same as over here but I add 21 and why do I add 21because we if we divide 43 divided by 2 then you get a floating point number andthat's not what we want so I create an integer and that's the center betweenour first two points but instead of using an Y of zero I use a Y of five sonow we have a triangle with two points one point in the center which is 5pixels offset from the to what you can do is fill her aroundwith these numbers to see how this draw triangle exactly works because now I'mtelling you it in the code and it's very theoretical but if you change thenumbers you'll see for yourself what happens that's basically the whole codefor this clock so I'm going to upload this to me our Dino and I show you whatit looks like so our mode and set code is running onyour Dino with the milk button I can change between hoursminutes and seconds so let's start by adjusting the hours so I select hoursand I can increase it with my set button the same goes for the minutes and I canalso reset the seconds when I press the button the mode button again it goesback to time and you see the seconds are increasing so our clock is running againI'm now going to show you how to implement this clock with usinginterrupts and we're even going to use a timeout so we're going one step further andwe're going to use the interrupts and it timeouts it's not very hard because wealready made the first clock which and interrupts so what changed is that herewe have now interrupts clear flags as you can see so we clear the queue againas in the previous example and we add touch to interrupts here and when themode is pressed we call the function mode button pressed interrupts and forthe set button the set button pressed interrupts so if we have a look at thecode of these interrupts of interrupts functions you see here for the motepressed interrupts we say button mode press is true and here you see buttonset press is true I like to keep these as light as possible and with that Imean as dump as possible so this one is only setting a variable to true andthat's basically it you want to keep your interrupts functions as clear cleanas possible but there's this special thing here the remote press is a specialvariable if you scroll a little bit up here you see bitter mode press per todisable Yin but here you see any word of volatile and volatile

 means that you canuse it in the loop function and in the interrupts if I didn't add volatile tothis variable what could happen is that a function in the loop is actuallymodifying little more pressed and at the same time I press the button whichraises an interest and then you can you can have some kind of what they callrace conditions and stuff and does solve with volatile if you want to know moreabout volatile google it there's a lot of information out there so I kept itquite dump because here I check if the built-in mode press is true and if soI'm calling the mode button handler so in my previous clock I had all this codeinside the interrupt which isn't the best way to do so butwas easy for the tutorial but now we're going to ride more clean coats so andmoved it into these functions and as you can see this is exactly the same code aswe had before except for this line because I set button mode pressed backto false and the same goes with the set button here button set pressed goes backto false so there's one more thing and that is the time out so Whitney time outwe're going to show the time if we don't do something for quite some time andthat time is defined over here in line 53 is the most set time out so basicallywe wait 500 milliseconds of 5 seconds and if you don't do anything for 5seconds while setting the hours the minutes or the seconds it will return todisplaying the time so how does this workwell we already kept for the D balance the time since I want to show you thetimestamp since we pressed the button for the last timeso what

 I do here it's actually very easy on line 125 here we check in twoparts if the in lapse button mode Milly's is larger than this five secondsthen this 5000 and the same here for the set button so if we haven't pressed themode button and the set button for the period of time the fighting mode settimeout and then the current mode becomes shim mode show time so it showsthe time you can fiddle around with this as well because you can also say wellyou have to wait for 10 seconds and then I want to show editing as setting thehours you can change it to whatever you want but that's how it this works soactually it's very easy because we already kept the time when we press thebutton so you just have to see if it's want you then our timeout so that isbasically the code I'm now going to send this to my Arduino and show you how thetimeout looks when it's running on our Denaso our code is running again on the Arduino and nothing has changed you canstill select the different motifs so I can adjust the hours the minutes resetthe seconds but there's one big difference if I'm going to edit the timeand wait for 5 seconds then you'll see is resume showing the time automaticallyand this is exactly as we configured in our code we define that if a certainamount of milliseconds it laughs it will go back to its default mode which isshowing the time this concludes the tutorial on thisdigital clock you have learned why you shouldn't use delay and how you can useMilly's to solve the problems with delay how to add your own animation how to usedebounce on the buttons how to use interrupts and how you can use theseveral modes so you only need to use two buttons you can easily extend thisclock by adding new modes for example for alarm or stopwatch you can also usea real-time clock to make the clock more accurate there are many things that youcan think of and just I encourage you to experiment with this clock if you haveany questions feel free to drop them in the comments and in the description ofthis video you'll find a link to the course material the circuit schema and ashopping list with all the parts used in this tutorial I see you in the nextvideo