Functions are an important part of your code. A function is a group of statements that run to perform a task. It could be as short as reading a sensor and returning the value, or something much more complex. A function will run when it is told to, and upon completion, will return to the main body of the code from where it left off. Arduino uses two functions for every sketch, which are setup and loop, as we've discussed previously. There are four main aspects of a function to consider. We have the function return type, the function name, function parameters, and function body. An important note about functions is that they can receive data from the rest of the program, and they can also pass data back to the program.
The first part of the function is the return type, which defines the type of data that it returns to the program. We'll use the function void loop as an example. Alright, so the first part of the function is the word void. This means that it returns no value to the rest of the program. Perhaps you've heard of the term returns void before, it applies to this as well. If the function returned an integer value, then it would be int loop instead of void loop. The function name is fairly self-explanatory. You call the function, or run it, by calling its name, in the same way that you can refer to a variable, and then you pass the required data to it. The loop function runs automatically, so you don't need to call it, but if you were to create a different function, it would only run when you called it in your loop, or setup.
So you can see here the name, we have void loop, and that would be the unique name of our function. The function parameters are the data that is passed to your function. After the function name, there are two brackets that contain the data being passed to the function. Now again, if you look at void loop, you can see that there's actually nothing inside the brackets, and that means it doesn't have any parameters which can be passed data to it. It's something of a lone wolf function, it just operates by itself and does its thing. To create parameters for a function, you specify the type of data, and the name of the parameter. So let's take a look at how we can use these concepts to create our own functions in our code to make it much more sophisticated and clean.
Now the example we're going to be looking at today is a hypotenuse calculator, and if this throws back unfortunate memories of boring maths lessons, I'm sorry, but it's actually quite fun. We're going to be using the simple concept that you can find the hypotenuse, or the long diagonal side of a right angle triangle, using a squared, where a is one side, plus b squared, which is the other side, is equal to c squared. So therefore the square root of a squared plus b squared will give us our hypotenuse. So let's take a look at the program. We've got no local variables, no pin definitions, this is entirely software based. So we're initializing the serial port to use the serial terminal, and we've got some local variables here in our void loop. We've got int a, int b, and float result.
Now this is important because whilst a and b are perfectly fine as standard integers, the result of performing different functions on these integers could return a float value. So first up then we've got serial print, and this is some instructions so that we can create a nice user interface. Enter a side value, where you would go through and enter a side value. And we're using something a little bit different in the terminal. We're going to be actually receiving data from this terminal, from the serial port, and then bringing it back to our Arduino, which we haven't looked at before. And we'll take a more extensive look at the UI port and the serial functionality in the next chapter. But for now it's a really cool implementation. Enter a side value. So it's waiting for a response, and we're using while ! serial. available, two brackets.
Now what this means is we're running an infinite loop, well not an infinite loop, but a continuous loop, while ever there is no serial data available. Pretty much it will check there's a serial buffer for any incoming data, and if that's empty, it'll just stick on that loop. And what this means is it's waiting for a response, it's waiting for some input. When it receives some input of any kind, it runs the function readSerial, and we're saying that A is equal to the return result of readSerial. So that is how we call a function. Now let's scroll down to the function readSerial. You can see that readSerial is an integer type function. We have int readSerial, and this is because the values that we're going to be returning are going to be integer type values. We're only inserting whole numbers into the serial port.
So it returns an integer type value, and we can run it. It doesn't take any parameters, it takes no arguments from the main thing, and it's an important point to note that the difference between an argument and a parameter, you might have heard the words being used interchangeably, and you can, but they're actually slightly different. In readSerial, if we wanted to create some parameters, we could use int g, or int x, or int someValue, and that would create a new parameter, int someValue, which is like a variable, a local variable we can refer to in the function, and that is the parameter. But then when we call readSerial, we need to pass it some data. So if we put 10 in the brackets, that is an argument. We're using 10 as an argument, and it passes 10 through to the function, and then, oh, the first parameter there is someValue, so therefore int someValue is going to be equal to 10 for this function.
We'll remove that anyway and crack on. So the first thing we do is we create a local variable, as you can see with int i, and we're making it equal to the return of a serial function called passInt. What this does is it takes the incoming data from the serial monitor, which isn't just a standard integer type. By default, it uses the ASCII table, so in fact, the letter A corresponds to an integer value, and a number corresponds to an integer value, but they don't correspond to the same thing, so we need to turn it into an integer first, which is where passInt comes in handy. Then we're going to be calculating the sides of a triangle. So we need to make sure it is actually a valid side. We don't want to have a negative side or a zero-length side because that is just conceptual, and it doesn't actually achieve the outcome of creating a hypotenuse calculator.
So if I is greater, sorry, if I is less than 1, which means if it's zero or a negative number, we return, and we return nothing, which means it simply exits the function and goes back to what it was doing. It says, oh, no, sorry, try again. Very good. So we can now have some sort of filter for incorrect data. Then, if it's not equal to 1, if it's not less than 1, if it's a valid integer, we go through and use serial print line, so we put a space, and then we use serial passInt again, and what this does is it clears the buffer. So we now have i. We've captured that incoming data. We've put a new line just for some styling purposes, and then we've used passInt again, but we haven't put anything equal to it, and this essentially just flushes out the serial buffer and makes sure that there's no extra remnants remaining that we haven't captured.
We just want that first number. It's very good, and then we return. We use return i. So we exit the function and return i, and here a is then going to be equal to i, so a has captured that incoming variable. Then we do the same thing. We print enter the other side value, so we now have two sides. We can calculate it. Same thing. We wait for some data. Then b is equal to i, so we now have two values, a and b, for our two sides, and then you see we run a new function called findSide, and here we are passing it some data. We've got two arguments here, a and b, and we're passing those to the function parameters. We go down to findSide, and it creates int x and int y, so a comes into and is equal to int x, and int y is equal to that because you've got to remember that int a and int b are just local variables within void loops.
So if we just use them in findSide, it wouldn't know what they are because they're not in that scope, so we pass them on to int x and int y, which are local, and then we calculate c, which is equal to a squared plus b squared, and we take the square root of that, and we find c. Fantastic. Again, a floating-type number, float hypotenuse, is equal to the square root of x times x, or x squared, plus y times y, or y squared, and then we print out the result. Really, really cool. We've got two different functions that we're using here, so let's take a look and upload it to our board. It's a really fun little hypotenuse calculator. So the serial monitor here will say, enter a side value. Let's enter 9, perhaps, and hit enter to send it. Wait for a moment. Yep, gives us 9. Enter the other side values. Let's... 5. The other side can be equal to 5.
Then it works that out, and it says, all right, 9 squared plus 5 squared, take the square root of that, and the hypotenuse length would be equal to 10.3 units. Really cool. We could use... Perhaps we'll use 3... and 4. And this is a classic example of using Pythagoras' theorem. 3 squared is 9, 4 squared is 16, and you add those together and you get 25, which is a perfect example because the square root of that goes down to 5, which is a nice whole number. And there you can see we've used two different functions to create a fun little hypotenuse calculator. So you can see how powerful functions are. You can use them to easily enhance your Arduino project or even a C or another programming language that you're creating that project with. And you could, of course, take the contents of readSerial and the contents of findSide and copy it into your code twice, three times, whatever it is, but that's just unnecessary waste.
It takes up all that extra room in your memory where you could just create a nice little function. It creates a modular piece of code, so if you have another project you're working on, similar to the debounce example that we used earlier, you could put all of that inside a function. Then you have this nice module of code you can copy and paste into different projects as you need. So that concludes the function on using logic statements and making decisions, and we've looked at logic statements and maths and functions. You can group all of those together to create some really powerful routines for your project. So stay tuned for our next chapter where we're going to be looking at operators and writing to the EEPROM and enhancing our understanding of using the serial board.
Makers love reviews as much as you do, please follow this link to review the products you have purchased.