Arduino OLED Clock Project (tutorial for beginners, u8g2, Arduino UNO, OLED display, SH1107,SSD1306)

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
okay so in this video I'm gonna show you how to create this analog clock using the Arduino Uno and this OLED display and as you can read it down here this display is a size 178 by 128 pixels and because it's using the ice core c connection I'm only using four wires to connect the display to the Arduino but more about that later for now I want to start with some kind of design and for a project like this I usually start in some kind of graphic editor for example photo P which is a free online editing tool similar to photoshop and then select the pencil tool and start drawing some pixels but I will not do this today because I want everything to be drawn using the standard graphic Primitives like lines pixels and circles and we will not be using any images in our project with one exception and that is showing the logo of sponsor of today's video which is PCB way and not only you can get pcbs but also other Manufacturing Services like 3D printing or CNC Machining all for a very good price actually if you use the link down in the description of today's video you can get 10 pcbs for free only paying for shipping so thank you PCB way and let's get back to our project so as I've told you already we don't need to draw any images today so we can skip this step and instead talk about how to draw those Primitives or how to actually calculate the positions of those Primitives let's say that this is our display and we want to draw one pixel for example the one on top this one and so the way you draw it is we Define the position being the X position which is the vertical distance and the Y position which is the horizontal distance but we can also think about this point in relationship to the origin which might be placed in the middle and instead of using the X and Y position we can Define the angle to the origin so some kind of angle and the distance to the origin and that's quite useful because if you think about all those little points they have the same distance to the center to the origin only the angle is changing and since we want to draw 60 different points around the whole circle we can easily calculate that the angle increment is 6 degrees however we cannot tell Arduino to draw the pixel on the position angle and distance we still need to provide the x and y values and since the X and Y is called the Cartesian coordinate system and the angle and the distance is called the polar coordinate system we need to convert from the polar coordinate system into the Cartesian coordin system and for that there is this formula so the x equals R times cosine of the angle so the r is the distance and Y equals R times sine of the angle let's jump to the walkway which is a free online Arduino emulator and let's try to draw something on the display and this is the simplest possible sketch for using the uadg to library which is the library that we are using for drawing on the display we first set the correct display which is this one and unfortunately for the simulation the only display that we can use is this 128 by 64 pixel so it's half the resolution of our final display so at some point we will only see half of our design but I guess that's better than not seeing anything then inside a setup we need to call the uh G2 begin function and then inside the loop we need to call this while loop and that's because we are using number one in the Constructor which means update the display by pages so we need to First draw the first page function and then do the drawing inside this Loop and then call the while next page to go over all the pages if you are not sure what all this means I would suggest you to watch my other videos where I go into quite a lot of details on how to set up a project using the Arduino Uno and the OLED display let's draw our pixel by calling the draw pixel function which only requires the X and Y position so I'll just copy draw pixel into our Loop and say u8 G2 dot draw pixel on some position for example 64 32 which will be the in the middle of the screen and it might also be a good idea to color set the draw color function to set the color to be white so I'll just copy this one and again say uh G2 that set draw color to one which is a white color and do this before drawing the pixel and now it's a return simulation I should see a very tiny pixel in the middle of the screen which seems to be the case let's set the position using the polar coordinate system that is using the angle and the distance the radius and for that I will create two more variables one will be the X position and that will be as the Wikipedia says cosine of the angle let's just say the angle is 0 times the radius for example 30 pixels and the angle is to be provided in a radiant so I'll convert it from degrees to radians using the radiance function and I'll do the similar thing for the Y position so the Y Position will be the sine function of the angle times the radius yes nobody's expects that the origin is on the left top but we don't have the origin in the middle so I'll add the 64 which is the half of the width and for the two for the Y which is half of the height of the display and then of course I will draw the pixel on the position X position and Y position and now we have the pixel displayed on a different position but it will be nice if the zero positions or zero angle Position will be up on top and for that they can try to switch the cosine and the sine function so for X let's use sine function and for a while let's use cosine function instead and now we are getting somewhere because now the pixel is on the bottom but we still want it on the top so what we can do is we can switch the cosine function to minus cosine and indeed now the pixel is on the top let's draw more of those pixels for example 60 to be one for every second so I'll do this inside a loop saying for integer y equals zero while the I is smaller than 60 I will increase it by one let's move the draw color outside of our Loop and for the angle let's use I times 6 because 300 by 60 divided by 60 is of course 6 obviously if you do limit the resolution it might be hard to create a nice looking Circle but maybe rounding those values from flows to integer might help a little bit okay so maybe this looks a little bit better from now on let's treat our project as if we were using the final display which is 128 by 128 pixels but obviously since this display is only 128 by 64 pixels we will only SD Hull of the screen but that should be probably fine so we'll start with drawing this circle in the final size and for that I will create two more variables first of this will be the center X position that will be the center of the screen in this case 64 pixels and Center wide and that will be the y center of the screen again it will also be 64 pixels and let's actually create a new function for drawing all those individual dials and let's call it draw background we don't need to provide any parameters I will just copy this section into our drawbackground function and inside a loop I will call the drawbackground function so drop background without any parameters and I want to change the function slightly first thing is use the center X for the X origin and Central Y for the Y origin and let's make the circle much bigger for example setting the radius to 60 pixels the biggest value that they can use is 64 but I want to draw one more circle around the whole display so let's just keep it a little bit smaller and as expected we see the top half of our clock display so let's actually draw this full screen circle around the whole display and for that we will use the draw Circle function now the important part is that the diameter of the circle is 2 times radius plus 1 so we cannot use 64 for the radius because it will end up the circle being 1 pixel outside of our screen so I'll copy this example paste it in here into our draw background function set the exposition to be Center X and Y position to be Central Y and since we cannot use 64 for the radius we will go with 63 instead and now we have the circle and those individual dials obviously we still only see half of the screen so let's test it on the real Arduino and the real display for that let's copy the code run the Arduino IDE and paste the code in here if you haven't used the u8 G2 library before you have to go to libraries type in u8 G2 and click the install button then of course select the core board which in my case is the Arduino Uno and we also need to set the correct display because the one that we are using is not this SSD 1306 it's actually the sh1107 so let's jump into the UAG documentation and search for sh1107 which will be 128 by 128 pixels and we are looking for the its core c connection so this down here seems to be the ice core c connection I want the hardware its core c connection and this one means draw by individual Pages which is the same case as we are using in our sketch so we'll just copy this piece of code into the Arduino IDE comment down this one and set this to also be the u8 G2 a rotation should be r0 and I don't have any reset button or clock and data because I'm using the default its course D line so I can just delete those part and comment out this comment let's upload this to Arduino and see what happens and we see the circle and the individual dots but somehow this is not on the correct position it looks like everything is offset to the right side by some number of pixels and upon some searching I did found out that it has to be set in the library code inside the uh G20 Library installation folder you have to search for the sh1107.c file and then search for the default X offset and as you can see in here it's being set to 96 pixels because most likely the creator of the library was using a display that has this set to 96 but our display is most likely zero so I'll change it to 0 and maybe in other places as well because I'm not quite sure which Constructor I'm using so just to be sure I will say to zero here and here as well and that should be enough so I will save the file go to the Arduino IDE and try to upload it one more time and indeed now the circle is being centered on the display and everything looks like it should be looking so let's move to the next part we will finish the background first with those digits and bigger tick marks and then move to the fun stuff which will be drawing those individual needles those individual hands it might also be a good idea to copy the Constructor of the final display into our walkway sketch and comment it out for the walkway project the next step is drawing those big tick marks and since we already know how to draw those small dots it will will be very simple we just need to calculate the position of the starting point and the ending point and then draw the line in between those two points let's do exactly that so inside our code I'll expand our drawbackground function with drawing the big tick marks and what I'll also do is I'll Define the exposition and do y position outside of the drawing because I want to reuse those variables for also for the tick marks and I'll create two more variables one will be the exposition 2 and the Y position 2 and I can probably also copy this whole for Loop but I will make some slight changes the first thing is that I want to draw elastic marks so also the eye only up to 12 which means that I need to set the angle as I times 30 and let's also set the radius to be slightly smaller for example 54 pixels and also calculate the second set of points that will be exposition to 2 and Y position 2 and the only change it will do is to set your smaller radius for example 46 and then instead of drawing the pixel we want to draw a line so in the documentation I will search for the drawing function and just copy this example and it's as simple as it could be drawing the iron from the X and Y position to the inner X and Y position so so copy this one into our code and draw it from the exposition and Y position to X position 2 and Y position 2 and hopefully that should be enough to draw our thick marks which seems to be the case however I don't want to draw all the tick marks because if I open the preview you can see that the tick marks are not being displayed on all the positions because I want to show some labels and the counter I goes from 0 up to 11 so I can use the modular function with the divisor of 3 and that will give me number 0 1 2 0 1 2 and so on and I don't want to draw tick marks when the modulus equals zero so let's add a simple if statement saying that if the module of the value I so I module 3 doesn't equal 0 in that case I will draw the tick marks and we can at least see the logic marks is indeed not being drawn on the position of number 12. so let's actually add those labels now to draw some label we need some kind of font and there are actually so many fans to choose from for the uag2 library that you can spend hours just deciding which might be dried fund I went with the font called uadg2 font 8x13 note b stands for bold and the n stands for numbers only you can select also the r which is the reduced fund or the F which stands for full fund so in our code I will call the set fan function with the name of the fund and after that we will use a function called the drawstring which will draw a string on a certain position so I'll just copy this into our code and change the text to B12 and then copy and paste this code three more times because I want to also draw number three six and nine now for actual positions you can of course use some functions to calculate properly the center of the text I'll just hardcore this value because I already know what those values should be so all that's left to do is to restart the simulation and hopefully see those widgets and I think that this might be enough for the background part let's just quickly see how it looks on the real display and I think it looks quite nice so let's move to drawing those individual needles those individual hands and we will start with the second hand because this one is the easiest one to draw we only need to know the positions of the two points this one being the first point and the second one being this point and then draw a line in between those two points so it will be very similar to drawing those individual tick marks but in addition we will also draw this small circle on the position of the second Point Let's create a new function called Draw and Fin and this time I will need some values I will need the hand angle I also need to know the length of the hand and I need to split it into two different values one will be the hand length long and the second one will be the line length short and I'll actually borrow a lot of pieces from the previous code for drawing the background so all those variables should be there as well and I want to also calculate those in the very similar manner so I'll just copy this piece of code for calculating those positions based on the angle but this time the angle will be defined by the hand angle so I'll just use the hand angle in all four lines one radius will be the hand length long and the second one will be the hand length short and I also want the second point to be rotated by 180 degrees to be on the opposite side of the center and then use the very same function to draw a line which in this case will be the second hand now before adding the circle let's just quickly test this and for that we need to call this function with some variables so I'll just copy this and drawn fin for the angle they just use for example 45 and for the sizes I've used 56 and 24 and we see something that looks like a second hand let's change the angle to at 180 degrees so you can see the second half of the needle because for that one we want to draw this small circle so inside a function for drawing the hand I will just copy this draw Circle function and the position will be the exposition 2 and Y position 2 and radius will be something very small for example only three however because we draw the circle and the line from the same point you can see it looks quite different from our preview where there was no intersection and we can fix this in a few different ways I think that the quickest one will be to draw another black circle that will cover the line so before drawing this circle let's draw a filled Circle which is called the draw disk I will use the same parameters but before drawing the circle I want to change the color to be like so I'll call this uadg draw color function and set the value to 0 for the black color and then change it back to 1 for the white color for drawing the outline and now it looks much better and this is how the second hand looks on the real display so we can move on to drawing the other hands being the hour hand and the minute hand and those are probably the most complicated part of the project and that's simply because you cannot draw a rotated rounded rectangle with some built-in function so we have to split the needle into individual Graphics Primitives that we can actually draw with the uid g2 function and if you take a closer look this looks like a circle as well as this part looks like a circle and we know how to draw filled circles early so we just need to get those two points and roll those two circles and we can actually use this point to draw the line to the origin that will form at least the basics of the needle let's copy the whole draw and fin function and our enemies to draw and bold and we need one more property which will be the radius of those circles so let's just call those hand dot size and we need to make a few changes so we don't need to add 182 the second angle because everything should be on the same side and instead of drawing the line from the first position to the second position we will draw a line from the center so Center X and Center y to the exposition and Y position and then draw a field circle on the first position so draw disk on the position X Exposition and Y position with the radius being the handy dot size and one more disk on the second position so Exposition 2 and Y position 2 with the same radius let's quickly try to draw the needle to see how it looks like I will hide the second hand and draw the hand bolt this might be for example the minute hand angle will be 45 and for the sizes I believe I used 48 and 15 with the diameter of the circle being 2. let's restart the simulation and we see part of our needle and we actually don't need to draw the line all the way to the second point we can end on the first point instead so something like this should be enough now in between those two circles it might make sense to draw a rotated rectangle but that's something that we cannot draw using the uid2 library but what we can draw is a filter triangle using the draw triangle function where you specify three points and it will draw a triangle so in our case we'll draw a first rectangle like this so from those three points we'll connect those three points and the second triangle like this and while we know was the center position of this circle we don't know what are the positions of those two points but that could be easily calculated we just need to take the center of the circle which will be this point and then calculate the new Point based on the angle so this will be the angle of the hand we will just add 90 to it so it will be the new angle and the radius which will be the size of the circle itself and this will give us a new point and instead of calculating this as the absolute position let's store this as the offset as the X and Y offset from the center of the circle I will add two more variables one will be the triangle X offset and the second one will of course be triangle y offset and calculate those two offsets so the triangle X offset will be calculated as the sine function of the angle in radians and that will be the end angle Plus 90 degrees and the radius will be the hand to that size and then I will round everything the wires will be very similar except now of course we will use the minus cosine function with the same parameter so the angle is hand angle Plus 90 and the size is handled that size so now we take one position for example the X position and the Y position and apply the X and Y after set which will give us this point and then we will subtract the X and Y offset which will give us this point now we'll take the second position which is exposition 2 and Y position 2 and for example at the same X and Y offset and we will get the third point which should be enough to draw the triangle so this will be triangle from this point to that point to this point and then we will do the same thing exactly of course use the second position let's copy the draw triangle function from the uh G2 documentation and plug in the right values so again we'll start with Exposition plus the X offset then the Y position plus the Y offset the second point is very similar except now we are subtracting this offset and default value is also similar but now we are adding this offset but using a second point which is exposition 2 and Y position 2 and as I restart the simulation we see something that resembles a triangle so let's draw a second one this time the first two points will be based on the second position so Exposition 2 and the last point will be Exposition y position 2 and the last point will be y position and the last point should be minus the offset and now we have something that looks like the needle from our preview now for some of those angles it looks better for the R1 so for example if I change it to 15 those triangles look more connected to the circles compared to seeing the needle in the 45 degree angle but I still think that it looks nice and this is how the minute hand looks on the real display there is one last thing left to draw and that's this circle in the middle and for that we'll reuse the code for drawing the second hand so in the main loop I will just paste this code but I will draw both the disk and the circle on the position center X and Center Y and make this slightly bigger so for example 4 pixels in the diameter and you can see that the half of the circle covering the end is there so we have all the drawing functions but we are not drawing all the individual hands so let's do that now I will create three new variables being the time seconds then of course timer minutes and also time hours and then inside our main Loop let's increase the time seconds and if the time seconds is bigger or equals 60 we will set it back to zero but also increase time minutes and similarly if the timer minutes is bigger or equal 60 we will set it to zero and we will increase time hours and finally if the time hours is bigger or equal to 12 we will reset it back to zero then inside the draw function we will draw the second hand where the angle will be time seconds multiplied by 6 and then the minute hand the time will be timer minutes multiplied Again by 6 and finally the other hand the time will be time hours but this time it will be multiplied by 30 because we only have 12 hours in a 360 Circle and the size of the Hour end to be slightly smaller for example 32 pixels and inside your starter simulation you should see the animated analog clock with the second hand of course sticking way too fast but that's mainly for testing purposes so I think it looks great let's see how it runs and looks on the real Arduino with a bigger display and it looks even better you will also notice that it's slightly slower and that's because now we have to update 128 by 150 pixels compared to half the resolution inside the vocal emulator so it just takes a little bit more time obviously it's also showing some random time and the second hand is not ticking every second but that's something for the next time to fix I hope you've learned something new today if you have any questions or comments please put those out in the comment section thank you very much for watching and I hope to see you next time thanks and bye
Info
Channel: upir
Views: 31,982
Rating: undefined out of 5
Keywords: arduino, microbit, ui, gui, ui design, arduino display, oled lcd, gauges, gauge, digital gauge, dashboard, car cluster, digital car cluster, digital dashboard, esp32, raspberry pi, round display, animation, tutorial, diy, cluster design, pixel, microbit makecode, arduino ui, custom display, custom car cluster
Id: srgsBWHSNSQ
Channel Id: undefined
Length: 20min 28sec (1228 seconds)
Published: Wed Jul 05 2023
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.