So far we have written programs as a long string of code, pretty much all in the void loop. As we begin to need to develop more complicated code, putting all the programming in the void loop can become unmanageable. It is easy to lose track of what we are doing. For more complicated programs, we want to break the problem up into manageable chunks of code. This is called modular program. We develop small modules that do specific tasks, and then our void loop simply calls these modules. The modules are called “Functions” in arduino.
Lets consider an example. Lets say we want to write an arduino program that prompts the user for the number of grades he has. Then it averages the grades, prints the grades and then prints the average. The following program would do this job, with all the code in the void loop:
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 | int numGrades; int j; float grades[15]; float bucket; float av; void setup() { // put your setup code here, to run once: Serial.begin(9600); } void loop() { Serial.println("How Many Grades? "); while (Serial.available()==0){ } numGrades=Serial.parseInt(); for (j=1; j<=numGrades; j=j+1) { Serial.println("Please Input a Grade"); while (Serial.available()==0){ } grades[j]=Serial.parseFloat(); } for (j=1; j<=numGrades; j=j+1){ bucket=bucket+grades[j]; } av=bucket/numGrades; bucket=0; Serial.println("Your Grades are: "); for (j=1; j<=numGrades; j=j+1){ Serial.println(grades[j]); } Serial.println(""); Serial.print("Your Average is: "); Serial.println(av); Serial.println(""); } |
You can see that the void loop is getting pretty complicated, and it would be easy to begin to lose track of what is going on. If we think about what we are trying to do, lets try to break it down more logically. These are the logical tasks we need to do:
Input Grades
Average Grades
Print Grades and Average
I think that is the logical way to break the program down. Hence, we need three modules or functions, which we could define as follows:
inputGrades();
avGrades();
printGrades();
We could call these three functions in the void loop. then down below the void loop we would need to define, or teach arduino what each of these functions do. In effect, the code in the example above is put down in three logical blocks, which we call functions. Notice that when we do that, the functions must be defined AFTER the void loop. That means it is done after the closing curly bracket for the void loop. Using functions, we can rewrite the program above as follows:
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 37 38 39 40 41 42 43 44 45 46 47 48 49 50 | int numGrades; int j; float grades[15]; float bucket; float av; void setup() { // put your setup code here, to run once: Serial.begin(9600); } void loop() { inputGrades(); avGrades(); printGrades(); } void inputGrades(){ Serial.println("How Many Grades? "); while (Serial.available()==0){ } numGrades=Serial.parseInt(); for (j=1; j<=numGrades; j=j+1) { Serial.println("Please Input a Grade"); while (Serial.available()==0){ } grades[j]=Serial.parseFloat(); } } void avGrades(){ for (j=1; j<=numGrades; j=j+1){ bucket=bucket+grades[j]; } av=bucket/numGrades; bucket=0; } void printGrades(){ Serial.println("Your Grades are: "); for (j=1; j<=numGrades; j=j+1){ Serial.println(grades[j]); } Serial.println(""); Serial.print("Your Average is: "); Serial.println(av); Serial.println(""); } |
Notice now that the void loop is very simple to understand, since each function is logically named. Also, if we look down at the function definition, it is clear what each chunk of code does. In this example, we are using global variables, so each function, and the void loop are all working with the same set of variables. In future lessons we will look at the use of local variables, and then how that would affect the structure of our functions.