How To Create A Function In Arduino
Overview of this Chapter
- 1What are Functions and Why do we need them?
- 2Creating our own Function(s)
- 3Passing a Value to a Function
- 4Returning a Value from a Function
- 5Functions calling Themselves (Recursion)
A complete overview of this course can be found here: Course Overview.
What are Functions and Why do we need them?
Theoretically we do not really need functions … however, without functions our code would become super long and completely unreadable. Not to mention; we'd have to write a lot more code.
We have already worked with 2 functions that are required for your Arduino: "setup()" and "loop()".
But what are functions and why do we need them? Or better said: why do we like them?
A function (also called: subroutine) can be seen as a set of instructions, grouped together, with a specific task in mind.
We can create a function to keep our code more readable, or because we'd like to use that particular task in several locations of our program(s).
It's called "subroutine" in some languages, because that's what it is; see it as a little program on it's own. And as with a regular program, a function can therefor also have other functions defined inside it, and that brings us to another issue to pay attention to: A function has a scope, just like with variables – the "area" in which it can be seen and used!
I realize this is a little bit much to grasp right away, but it is something to keep in mind.
We can define functions that does return a result (value) or does not return a result.
The latter, not returning a result, is called a "procedure" in other programming languages. The language C however calls both just a "function".
A function, is a group of instructions for a specific task.
When do we define our function?
- When code is repeated more than once in my program
- If my code becomes more readable with functions
- If my code becomesmore manageable with functions
- If we'd like to re-use a piece of code for example in other programs
Let's look at an example of what a function could be – just to grasp the concept.
Say we have a dog, which needs walking 4 times a day: At 8 AM, 12 PM, 5 PM, and at 9 PM.
The task of walking the dog involves:
– Put on a coat
– Put on the leash of the dog
– Go outside
– Walk through the park for 15 minutes
– Go back inside
– Take off the leash of the dog
– Take off your coat.
Now let's assume our program handles our day when it comes to walking the dog:
if 8 AM then
– Put on a coat
– Put on the leash of the dog
– Go outside
– Walk through the park for 15 minutes
– Go back inside
– Take off the leash of the dog
– Take off your coat.
if 12 PM then
– Put on a coat
– Put on the leash of the dog
– Go outside
– Walk through the park for 15 minutes
– Go back inside
– Take off the leash of the dog
– Take off your coat.
if 5 PM then
– Put on a coat
– Put on the leash of the dog
– Go outside
– Walk through the park for 15 minutes
– Go back inside
– Take off the leash of the dog
– Take off your coat.
if 9 PM then
– Put on a coat
– Put on the leash of the dog
– Go outside
– Walk through the park for 15 minutes
– Go back inside
– Take off the leash of the dog
– Take off your coat.
Our program is pretty long, right? And a lot of repeating code as well …
We could create a function, let's call it "WalkTheDog()", and define it as follows.
WalkTheDog():
– Put on a coat
– Put on the leash of the dog
– Go outside
– Walk through the park for 15 minutes
– Go back inside
– Take off the leash of the dog
– Take off your coat.
Now our program would look much simpler:
if 8 AM then
WalkTheDog()
if 12 PM then
WalkTheDog()
if 5 PM then
WalkTheDog()
if 9 PM then
WalkTheDog()
You see, that not only our code has gotten much shorter, but it also has becomemuch more readable – the "function" is called as if it was a regular statement. We in fact expanded our "language".
In most scenario's, using your own functions will also result in a smaller compiled program for your Arduino or computer, therefor being more efficient with memory needed on your Arduino (or computer).
But functions have also the advantage that if you made a mistake in your steps of walking the dog, that you only have to modify your code in one spot: the function – which makes your code more manageable. For example, if we forgot to add "Unlock the door" as a step. We just edit the function WalkTheDog() instead of having to edit the code in 4 different spots in the previous code.
Now if we have a function that is more of a generic use, we can even put them in what is called a library and re-use the function in our other programs. But more about "libraries" in a next part.
Please keep in mind that:
- A function is like a little program on it's own … inside a program
- A function can have functions inside it …
- A function has a "scope" – like we have seen with variables and constants.
Ad Blocking Detected
Please consider disabling your ad blocker for our website.
We rely on these ads to be able to run our website.
You can of course support us in other ways (see Support Us on the left).
Creating our own Function(s)
It's pretty easy to define our own functions in the language C which we use for Arduino programming. The basic structure looks like this:
datatype FunctionName ( FunctionParameters ) {
// function code
}
I hope you remember some of the DataTypes we have mentioned in Part 3 – DataTypes. If not, don't worry, you can look back if you'd like, but I will also mention some of the details here.
The datatype is defining what kind of data is being returned from the function and unfortunately, not all datatypes are all that suitable for use as a return value for functions. Definitely avoid arrays!
The most common datatypes for a return value areboolean, int, char, floatandvoid (other types will work as well, like double, long and the "unsigned" types).
Obviously, our function needs a FunctionName, and we need to follow the same naming rules as with variables and constants:
Function name:
- Should start with a letter (a, b, …, z, A, B, … , Z) or underscore ( _ )
- Can containletters
- Can contain underscore(s)
- Can contain numbers
- CAN NOT contain special characters, symbols or spaces
- is case sensitive!
The Function Parameters are zero or more values that we want to pass to the function. The number of values and the datatype of these values however is fixed and defined in our function definition!
In some C dialects you will need to "declare" (announce) or "define" a function before it's being used in the code. The compiler needs to "know" it exists before it can use it. This appears not to be the case with C on the Arduino, which is why it will not be addressed here.
We have used function parameters before, even though you might not have been fully aware. It's those values we pass between brackets, for example in this line: Serial.print ( "Hello" ) ;
Here we call the function "print()" from the object "Serial" and we pass the parameter "Hello" (a string). More about objects later.
The following code block, between accolades, is something we have seen before as well in for example the "if" function and the different loop kinds ("for", "while" and "do … while …").
This code block groups the instructions for our function.
Let's start with a simple function:
1
2
3
void SayHello( ) {
Serial.println ( "Hello" ) ;
}
This function, called "SayHello()", takes no parameters since there is nothing between the () brackets.
It also does not return a value, since we used the special datatype "void" – which means "nothing, thin air, nada".
The "body" of the function (the code block), holds the instructions for this function, and it just outputs "Hello".
An example of how we'd use this:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
void setup( ) {
// set the speed for the serial monitor:
Serial.begin ( 9600 ) ;for ( int A= 1 ; A<= 5 ; A++ ) {
SayHello( ) ;
}
}void loop( ) {
// leave empty for now
}void SayHello( ) {
Serial.println ( "Hello" ) ;
}
Most of this should look familiar, I'd hope anyway …
At the end of the code you see how we defined our "SayHello()" function.
In the "for"-loop you see how we call our function 5 times, which results in an output like this:
Hello
Hello
Hello
Hello
Hello
Easy right?
Passing a Value to a Function
This was a rather simple example, let's look at an example where we actually pass a parameter, where we use a previous example of turning on 5 lights with a "for"-loop.
For this we create a new function, called "DoLights", to which we want to pass the light number of the light that needs to be switched on.
We already know that this number is a whole number of datatype "int" (see also the definition of "A" in the "for"-loop).
We also know that it will not return any values, which then get's us this function:
void DoLights( int LightNumber) {
Serial.print ( "Switch lights on for light " ) ;
Serial.println (LightNumber) ;
}
The parameter "LightNumber" is defined as an "int". You can see that there is a the definition of the variable "LightNumber" inside the function called "DoLights". When we pass a value for that parameter, the value will be copied into that "new" variable.
Keeping "scope" in mind, "LightNumber" obviously only exists in the function "DoLights".
Calling our function (line 6) is just the same as the previous example, this time however we pass the value of the variable "A". The value of "A" is being copied into the variable "LightNumber" – remember that it's COPIED.
All this combined:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
void setup( ) {
// set the speed for the serial monitor:
Serial.begin ( 9600 ) ;for ( int A= 1 ; A<= 5 ; A++ ) {
DoLights(A) ;
}
}void loop( ) {
// leave empty for now
}void DoLights( int LightNumber) {
Serial.print ( "Switch lights on for light " ) ;
Serial.println (LightNumber) ;
}
You see how the variable "LightNumber" is being used in the function?
But this was just an example on how to pass just one value. How does this work if we need to pass multiple values?
As an illustration, we will add a boolean value which we'd like to pass to our function. If this value istrue then the lights should go ON, if it'sfalse the lights should go off.
To do this we need to separate the two values and for this we use a comma ( , ).
Parameters in a function are separated by a comma,
both when defining the function and when calling the function.
As with any value we'd like to pass, we again need to define it's datatype (boolean) and name (LightOn).
I've added an "if" statement, so that the function can accommodate for switching the lights ON or OFF – another cool feature of functions; we can write them in such a way that they can work for more than one scenario.
All this combined:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
void setup( ) {
// set the speed for the serial monitor:
Serial.begin ( 9600 ) ;for ( int A= 1 ; A<= 5 ; A++ ) {
DoLights(A, true ) ;
}for ( int A= 1 ; A<= 5 ; A++ ) {
DoLights(A, false ) ;
}
}void loop( ) {
// leave empty for now
}void DoLights( int LightNumber, boolean LightOn) {
if (LightOn) {
Serial.print ( "Switch lights ON for light " ) ;
}
else
{
Serial.print ( "Switch lights OFF for light " ) ;
}Serial.println (LightNumber) ;
}
As you can see, we first run a "for"-loop, of 5 iterations, switching the 5 lights ON.
The values we pass are separated by a comma as well!
In the next "for"-loop, also 5 iterations, we switch the lights OFF.
Your output should look like this:
Switch lights ON for light 1
Switch lights ON for light 2
Switch lights ON for light 3
Switch lights ON for light 4
Switch lights ON for light 5
Switch lights OFF for light 1
Switch lights OFF for light 2
Switch lights OFF for light 3
Switch lights OFF for light 4
Switch lights OFF for light 5
Now obviously, the examples here are not really good ones when it comes to begin more efficient. But when you start creating your first, larger, programs, you will see how functions are an asset for a programmer.
Ad Blocking Detected
Please consider disabling your ad blocker for our website.
We rely on these ads to be able to run our website.
You can of course support us in other ways (see Support Us on the left).
Returning a Value from a Function
So we know that a function can "receive" values by using parameters. Now what if we want the function to return an answer or result – for example from a complex calculation?
Remember we used "void" with our previous function definitions? That's where we define what the returning result will be.
In the function itself however, we do need to actually "return" that type of value, and we use the function "return" for that.
If you define a function which will return a defined datatype, then you will need to use the "return" statement to return a value, which has to be of the same datatype as the defined return value datatype of your function …
An example could be made with one of the previous examples where we calculated "AllMyMoney" by adding what is in our wallet and what is in the bank. A pretty trivial situation, since we can calculate this already more efficient without creating a function, but it's a good illustration. Obviously, once you start writing you own programs, these functions will contain much more and more complex code than this.
So we created a function "CalculateMyMoney", which takes two parameters. I intentionally named them differently again, to illustrate that the values of the 2 variables (PocketMoney and Savings) are being COPIED to the variables names we defined in the function. It would have been fine to give the parameter variable names the same names, if you recall the "scope" of variables: the variables in the function are not the same variables as the ones outside of the function.
In the function we add these 2 values and return the result "Total". This "return" value is then assigned to the variable "AllMyMoney".
Go ahead and try this code.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
void setup( ) {
// set the speed for the serial monitor:
Serial.begin ( 9600 ) ;// define our variables
int PocketMoney;
int Savings;
int AllMyMoney;// assign the values
PocketMoney = 4 ;
Savings = 12 ;
AllMyMoney = CalculateMyMoney(PocketMoney, Savings) ;// print the values to the serial monitor
Serial.print ( "PocketMoney = " ) ;
Serial.println (PocketMoney) ;Serial.print ( "Savings = " ) ;
Serial.println (Savings) ;Serial.print ( "AllMyMoney = " ) ;
Serial.println (AllMyMoney) ;
}void loop( ) {
// leave empty for now
}int CalculateMyMoney( int Wallet, int Bank) {
int Total;Total = Wallet + Bank;
return Total;
}
A function with a returning value, could be seen as a variable. So where ever we can use a value, or a variable, we could also use the function that returns a value, which I'll illustrate in this slightly modified version. Look at line 21 … we've just placed the function call right there as a "parameter" for the " Serial.println ( ) " … and that works! So we do not need to first assign a returning value to a variable.
If you need the result of a function more often, then storing it in a variable makes perfect sense. After all: calling the function will exectute it's code again, which would be redundant if we would need the same answer more than once.
A function with return value, can take the place of a regular value or variable …
Each time we call a function, it's code will be executed. So if you need the result more than once, consider storing the value in a variable instead of calling the function repeatedly.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
void setup( ) {
// set the speed for the serial monitor:
Serial.begin ( 9600 ) ;// define our variables
int PocketMoney;
int Savings;// assign the values
PocketMoney = 4 ;
Savings = 12 ;// print the values to the serial monitor
Serial.print ( "PocketMoney = " ) ;
Serial.println (PocketMoney) ;Serial.print ( "Savings = " ) ;
Serial.println (Savings) ;Serial.print ( "AllMyMoney = " ) ;
Serial.println ( CalculateMyMoney(PocketMoney, Savings) ) ;
}void loop( ) {
// leave empty for now
}int CalculateMyMoney( int Wallet, int Bank) {
int Total;Total = Wallet + Bank;
return Total;
}
At this point I strongly recommend playing with functions. Make up a function yourself, with or without return value, and do some experimenting.
Functions calling Themselves (Recursion)
This paragraph maybe be too complicated for beginners – feel free to skip it if you feel it's too much for you.
A function can actually call itself, this is called "Recursion".
You must be thinking that we ended up in crazy town – well, do not worry if recursion is a little bit too much for you. It is a little much for any beginner and even some experienced programmers.
So for this course we will leave it be for what it is: something you will not be using until you get more experienced with programming.
Recursion can be a very powerful tool, to write a limited amount of code yet produce stunning results. For example certain graphics can be generated with recursion like the tree below or the so called Sierpinski triangle. (image source: Wikipedia – Tree byBrentsmith101, Sierpinski byWereon).
These a drawn by utilizing Recursion.
Recursive Tree
Sierpinski Triangle – Triangle in triangle
If you're interested anyway … here a quick and simple example that is less complicated as the two images above.
Let's say we want to add all whole numbers, for all numbers between 1 and 5. So we want to know how much 1+2+3+4+5 is (15).
Obviously we can do this very simple by either entering that manually, or by using a "for"-loop, but today we want to be difficult so we use this scenario as our recursion example.
We are going to create a function that starts at "5" and adds the number below that (4), then add the number below that (3), etc etc. until we added 1.
1
2
3
4
5
6
int AddOneLess( int Number) {
if (Number== 0 )
return Number;
else
return Number+AddOneLess(Number- 1 ) ;
}
So what this function does is, take the "Number" value. If this number is zero, then return zero. If the number is not zero, then take that number and call the "AddOneLess" function for the number minus 1.
Weird right?
In other words: this function will start with a given number, and keeps adding each time the previous number until it reached zero (0).
Let me display this differently by using this example code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
void setup( ) {
// set the speed for the serial monitor:
Serial.begin ( 9600 ) ;Serial.println (AddOneLess( 5 ) ) ;
}void loop( ) {
// leave empty for now
}int AddOneLess( int Number) {
if (Number== 0 )
return Number;
else
return Number+AddOneLess(Number- 1 ) ;
}
First we call AddOneLess(5).
The value of "Number" is not zero, so we do 5 + "AddOneLess(5-1)", and there is NO return value yet since we now went into the AddOneLess(5-1) function call.
This second call, is where the value of "Number" is 4, and still not zero so we add 4 + "AddOneLess(4-1)" and we're calling AddOneLess again, so no return value yet.
This results in the third call where the value of "Number" is 3 and still not zero so we add 3 + "AddOneLess(3-1)" – no return value yet.
This results in the fourth call where the value of "Number" is 2 and still not zero so we add 2 + "AddOneLess(2-1)" – no return value yet.
This results in the fifth call where the value of "Number" is 1 and still not zero so we add 1 + "AddOneLess(1-1)" – no return value yet.
The sixth call however the value of "Number" is 0 (zero), so we return "zero".
However ,… we return zero in the "scope" of the fifth call, we went one step back, where the value of "Number" is 1, and where we say: return the value of "Number" and the return value of calling "AddOneLess(1-1)".
So the fifth call returns 1 (value of "Number") + 0 (return value of AddOneLess(1-1) ) = 1.
Now we return to the scope of the fourth call, where "Number" had the value 2, and which returns the value of "Number" + the return value of "AddOneLess(2-1)", so: 2 + 1 = 3.
Returning to the scope of the third call, "Number" has a value of 3, and the return value = 3 + 3 (return from "AddOneLess(3-1)") = 6.
When getting back to the second call, "Number" has a value of 4, so the return value = 4 + 6 = 10;
And coming back to the original call, "Number" is 5, and the return of the "AddOneLess(5-1)" has become 10. So this call returns 5 + 10 = 15.
Nice and confusing right?
Maybe it makes more sense to show it this way:
1
2
3
4
5
6
7
8
9
10
11
12
13
1st call: AddOneLess(5) // in the setup() function
2nd call: AddOneLess(4) // in the AddOneLess(5) function call
3rd call: AddOneLess(3) // in the AddOneLess(4) function call
4th call: AddOneLess(2) // in the AddOneLess(3) function call
5th call: AddOneLess(1) // in the AddOneLess(2) function call
6th call: AddOneLess(0) // in the AddOneLess(1) function call, Number will now be zero!
5th call: Return = Number + result 6th call = 1 + 0 = 1
4th call: Return = Number + result 5th call = 2 + 1 = 3
3th call: Return = Number + result 4th call = 3 + 3 = 6
2nd call: Return = Number + result 3th call = 4 + 6 = 10
1st call: Return = Number + result 5th call = 5 + 10 = 15Final return: = 15
I know this is complicated to grasp for the first time, so no worries if this is way over your head. I really had to think hard about even putting this explanation in here, but for all completeness I've added it anyway. Just remember that a function can call itself and that it will not interfere with previous calls. Each function call will get it's own "scope".
Just a rule of thumb to keep in mind when using recursion: Always make sure there is an "exit" condition in the function so the function does not keep going forever and crash your Arduino or computer … after all, for each call a scope is being stored in memory and your Arduino does have a limited amount of that.
When creating Recursive functions:
ALWAYS make sure the function has an "exit" condition to leave the function.
If you have questions, just ask them below in the comment section, and keep in mind: There are no stupid questions! We all had to start at some point!
Next chapter: Arduino Programming for Beginners – Part 7: Strings
How To Create A Function In Arduino
Source: https://www.tweaking4all.com/hardware/arduino/arduino-programming-course/arduino-programming-part-6/
Posted by: tatesincom.blogspot.com

0 Response to "How To Create A Function In Arduino"
Post a Comment