{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# 5. Programming Arduino\n", "\n", "
" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "In this lesson, we will take a whirlwind tour through the syntax you need as you write sketches. This lesson is long, and I thought about breaking it up, but I think it will be helpful to have a single quick reference to go back to, in addition to the exceedingly useful [Arduino language reference](https://www.arduino.cc/reference/). \n", "\n", "When you finish this lesson, it is important to proceed without much delay to the next lesson, where you will put some of the aspects of Arduino programming learned here to use." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Review of last lessons\n", "\n", "You will remember in the previous lessons that we have already established a few key syntactical rules.\n", "\n", "1. All variables have to have a **type declaration**. So far, we have only seen `int` data types, some of which we declared as `const`, meaning that the value of the variable cannot change.\n", "2. All functions have to have a type declaration for their return value. We have seen `void`, but we could have `int` or other data types we will introduce here.\n", "3. All commands end in a semicolon.\n", "4. Every Arduino sketch has a `setup()` and a `loop()` function. The `setup()` function is run upon upload of the compiled sketch and upon reset, and the `loop()` function is then run over and over again.\n", "5. The core Arduino libraries have built-in functions and variables. For variables, we have seen `INPUT`, `OUTPUT`, `HIGH`, and `LOW`. We actually also saw `LED_BUILTIN` in the [setup lesson](../00/configuring_your_computer.ipynb).\n", "6. Comments start with `//` or appear between `/*` and `*/`.\n", "\n", "We will now proceed to learn about programming the Arduino microcontroller." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## A general note about programming in Arduino: keep it simple\n", "\n", "You may have experience coding in C++ and have used all of its rich object orientation in your code. You may have constructed complicated, but powerful data types. You can do a lot of that with Arduino, but I have found that it is easier not to. The main reason is that you have only 2 kB of RAM to work with. This means that if you are doing to do something like dynamic memory allocation, which you would do in almost any C++ program, you should try to accomplish the same task in ARduino with static arrays. Unforeseen problems, such as memory fragmentation, can rear their ugly heads.\n", "\n", "It is safe to use pointers and work with them, e.g., to make two-dimensional arrays, but we will not discuss them here. Nonetheless, be careful when doing so.\n", "\n", "Since we ultimately will be using the Arduino Uno to run and instrument and collect and send data, we will be connecting it to your computer. You computer is *much* more powerful that the Arduino Uno (that's why it probably costs two orders of magnitude more). Furthermore, you can program whatever manipulations you need to do to the data in Python, which, being a high-level interpreted language, is much easier to quickly write functional code with than C++.\n", "\n", "With that in mind, let us proceed to learn about programming Arduino." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Data types\n", "\n", "As I have mentioned, every variable in an Arduino sketch has a type, and that type must be declared when the variable first appears. It is ok to declare it before you use it. That is, this is ok:\n", "\n", "```arduino\n", "int j;\n", "\n", "j = 0;\n", "```\n", "\n", "as is this:\n", "\n", "```arduino\n", "int j = 0;\n", "```\n", "\n", "They give the same result." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Scalar data types\n", "\n", "- `bool`: A `bool` stores a single bit of information. It can take values of 0 or 1. In your sketches, though, use the Boolean constants `true` and `false` for the values of a `bool`.\n", "- `byte`: A byte is an unsigned 8-bit integer. It can take values from 0 to 255; that is 0 to 2⁸ – 1.\n", "- `int`: An `int` in an Arduino sketch is a signed 16-bit integer. That means that the values of an `int` range from –32,768 to 32,767; that is –2⁻¹⁵ to 2¹⁵ – 1. The `int` is by far the most-used variable type. Note that the 10-bit ADC converts voltages to 10-bit integers that range from 0 to 1023. You can safely store these as `int`s. If you use an external 16-bit ADC, because an `int` cannot store 16-bit numbers, you will have to use an `unsigned int`.\n", "- `unsigned int`: An `unsigned int` is also a 16-bit integer, but negative numbers are not allowed. Therefore `unsigned int`s can range from zero to 65,535; that is 0 to 2¹⁶ – 1, which means you an store a 16-bit integer with it.\n", "- `word`: A `word` is equivalent to `unsigned int`. Many programmers suggest using `word` instead of `unsigned int` for clarity, but I do not have a strong opinion on this.\n", "- `long`: A `long` is a signed 32-bit integer. They range from –2,147,483,648 to 2,147,483,647; that is –2⁻³¹ to 2³¹ – 1. To denote an integer as a `long`, it must be followed by an `L`. For example to store the number 3252 in a variable named `shoulderToShoulder` as a long, you would do `long shoulderToShoulder = 3252L`.\n", "- `unsigned long`: A `unsigned long` is an unsigned 32-bit integer. They range from 0 to 4,294,967,295; that is 0 to 2³² – 1. An `unsigned long` must also be followed by an `L` when written out as a number. `unsigned long`s are very often used when comparing times, since the values returned by the `millis()` and `micros()` functions (described below) are `unsigned long`s.\n", "- `size_t`: This is a special data type used to represent the size of a variable (or any object, really) in bytes.\n", "- `float`: A `float` in an Arduino sketch is a 32-bit [floating point number](https://en.wikipedia.org/wiki/Floating-point_arithmetic). A `float` can take values between –3.4028235×10³⁸ and 3.4028235×10³⁸. It provides six or seven digits of precision.\n", "\n", "Note that on an Ardunio Uno, there is no `double` data type. Note also that the data type `short` is equivalent to `int`." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Arrays\n", "\n", "As I mentioned above, we will not discuss complicated array structures. For this class, simple static one-dimensional arrays will suffice." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### Declaring arrays\n", "\n", "There is no `array` data type. Rather, an array is an ordered collection of elements of a single data type. An array is declared with the data type of its elements. To declare an array of 5 `int`s, the syntax is\n", "\n", "```arduino\n", "int myArray[5];\n", "```" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### Indexing an array\n", "\n", "To access the elements of an array, I use indexing with brackets. **Indexing in C++ is 0-based.**\n", "\n", "```arduino\n", "int myArray[4];\n", "\n", "myArray[0] = 3;\n", "myArray[1] = 2;\n", "myArray[2] = 5;\n", "myArray[3] = 2;\n", "```\n", "\n", "If I asked for `myArray[4]`, which does not exist, the compiler will not give an error, and I'll get weird results when I run the code. It is therefore very important that you are careful not to overrun an array." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### Directly creating an array\n", "\n", "Alternatively, I can create an array using braces.\n", "\n", "```arduino\n", "int myArray[4] = {3, 2, 5, 2};\n", "```\n", "\n", "When creating an array in this case, I do not need to specify how many entries; the compiler will infer it.\n", "\n", "```arduino\n", "int myArray[] = {3, 2, 5, 2};\n", "```" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### Determining the number of elements in an array\n", "\n", "Later on in a program, I might like to know how many entries are in an array. There is no built-in function to do that. But you can use the `sizeof()` function, which returns the number of bytes that an object occupies in memory. Since every entry in an array is of the same type, you can use the `sizeof()` function to get the number of entries by dividing the size of the array by the size of an entry.\n", "\n", "```arduino\n", "int lenArray = sizeof(myArray) / sizeof(myArray[0]);\n", "```" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### Mutating arrays\n", "\n", "Because I do not have `const` in front of the declaration, I can change the values of entries in the array.\n", "\n", "```arduino\n", "int myArray[4] = {3, 2, 5, 2};\n", "\n", "myArray[3] = 3;\n", "\n", "// myArray is now {3, 2, 5, 3}\n", "```" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### Using entries of an array in a calculation\n", "\n", "I can also access entries of an array with indexing and use their values.\n", "\n", "```arduino\n", "int myArray[4] = {3, 2, 5, 2};\n", "\n", "int mySum = myArray[0] + myArray[1] + myArray[2] + myArray[3];\n", "\n", "// mySum stores the value 12.\n", "```\n", "\n", "I can also pluck values out of an array and store them." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Character and string data types\n", "\n", "- `char`: A single character, like `'A'` is stored as a `char`. When defining a `char`, it is in single quotes, e.g., `char myGradeInBE189 = 'A';`.\n", "- `string`: A `string` is an array of `char`s. They are constructed using double quotes. `char myString[] = \"Hello, world.\"` `string`s are **null-terminated**, which means that the last element of the array of characters is a special character called a **null character**. This character is `\\0`. It is important because it lets functions that work with strings know where the string ends." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### The String class\n", "\n", "While I gave a warning about using C++'s object orientation, the core libraries have some handy classes that you can make use of. The `String` class is particularly useful.\n", "\n", "To construct a `String` instance, you use `String()` as a function. You have to make sure to declare your variable to be of a `String` type.\n", "\n", "```arduino\n", "String myString = String(\"Hello, world.\");\n", "```\n", "\n", "The variable `myString` now has many methods to use. Here are a few:\n", "\n", "```arduino\n", "String myString = String(\"Hello, world.\");\n", "\n", "// Gives 13\n", "int lenString = myString.length();\n", "\n", "// Converts to upper case in place.\n", "myString.toUpperCase();\n", "\n", "// Gives 5\n", "int commaIndex = myString.indexOf(',');\n", "```\n", "\n", "You can also use operators with the string.\n", "```arduino\n", "String myString = String(\"Hello, world.\");\n", "\n", "// You can use + to concatenate with instantiating\n", "String greeting = String(\"Hello, world.\" + \" Pleased to meet you.\");\n", "\n", "// Or after instantiation\n", "String greeting = String(myString + \" Pleased to meet you.\");\n", "```\n", "\n", "You can also convert a number to a string, and a string to a number.\n", "\n", "```arduino\n", "// Convert an integer\n", "String intAsString = String(3252);\n", "\n", "// And bring it back to an integer\n", "int favoriteInt = intAsString.toInt();\n", "\n", "// If you convert a float, the second argument is how many decimal places to keep.\n", "// This gives \"3.14\".\n", "String floatAsString = String(3.14159, 2);\n", "\n", "// You can convert back to a float. This will give 3.14.\n", "float pi = floatAsString.toFloat();\n", "```\n", "\n", "Unless you are RAM constrained, you should just use `String` objects when handling strings. They have a bigger footprint in RAM, but the benefits are substantial." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Type conversion\n", "\n", "You can change types of a variable using **casting**. To cast, place the data type you want to convert to in parentheses before the variable you are converting. Here are a few examples.\n", "\n", "```arduino\n", "int myInt = 176;\n", "float myFloat = 2.718;\n", "\n", "// Convert an int to a byte. Be sure it's ≤ 255\n", "byte intAsByte = (byte) myInt;\n", "\n", "// Convert an int to a float\n", "float intAsFloat = (float) myInt;\n", "\n", "// Convert a float to an int (gives 2; chops off decimal)\n", "int floatAsInt = (int) myFloat;\n", "```" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Operators\n", "\n", "Now that we have a handle on data types, we can look into operators. " ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Arithmetic operators\n", "\n", "We have already seen the **assignment operator**, `=`, and it works as you might intuit. Other arithmetic operators are:\n", "\n", "- `+`: Addition. It is overloaded for `String` objects, doing concatenation instead.\n", "- `-`: Subtraction.\n", "- `*`: Multiplication.\n", "- `/`: Division\n", "- `%`: Mod. `6 % 3` gives `0`. `6 % 4` gives 2.\n", "\n", "Note that there is no floor division. This can be accomplished with casting, e.g., `(int) 6 / 4` will give `1`.\n", "\n", "There is also no raise-to-power operator. This is achieved using the `pow()` function." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Comparison operators\n", "\n", "These are the same as in Python and give a `bool`, either `true` or `false`, as a result.\n", "\n", "- `==`: Equal to.\n", "- `!=`: Not equal to.\n", "- `<`: Less than.\n", "- `>`: Greater than.\n", "- `<=`: Less than or equal to.\n", "- `>=`: Greater than or equal to." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Boolean operators\n", "\n", "The three Boolean operators are:\n", "\n", "- `&&`: AND\n", "- `||`: OR\n", "- `!`: NOT\n", "\n", "Here are some examples.\n", "\n", "```arduino\n", "// Gives true\n", "4 < 6 && 7 < 93\n", "\n", "// Gives true\n", "4 < 6 || 7 < 93\n", "\n", "// Gives false\n", "4 < 6 && 7 > 93\n", "\n", "// Gives true\n", "4 < 6 || 7 > 93\n", "\n", "// Gives false\n", "!(4 < 6 || 7 > 93)\n", "```" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Compound operators\n", "\n", "**Compound operators** are used to change the values of variables in place. The operators are best explained by considering equivalent expressions.\n", "\n", "|compound operator expression | equivalent expression |\n", "|:--------|:------|\n", "| `x += 1` | `x = x + 1` |\n", "| `x++` | `x = x + 1` |\n", "| `x -= 1` | `x = x - 1` |\n", "| `x--` | `x = x - 1` |\n", "| `x *= 2` | `x = x * 2` |\n", "| `x /= 2` | `x = x / 2` |\n", "| `x %= 2` | `x = x % 2` |" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Bitwise operators\n", "\n", "Bitwise operations work on numbers at the level of their binary representations. While I have not used these operators very often in my various hacking pursuits, they do come up fairly often in programming devices, especially in the context of communications where data are sent and received as bits and bytes.\n", "\n", "I think the operators are best explored by example. To keep the binary representations short, we will use `byte`s instead of `int`s. Say we have a `byte` variable `01001101`. This corresponds to the decimal number 77. The number `10001110` is 142. Let us now consider some bitwise operators on these two numbers to see how they work. It helps to look at these two binary numbers on top of each other to make easy comparisons\n", "\n", " x = 77: 01001101\n", " y = 142: 10001110\n", " \n", "In what follows, assume that we have already executed the code\n", "\n", "```arduino\n", "byte x = 77;\n", "byte y = 142;\n", "```\n", " \n", "- `&`: Bitwise AND. Two numbers with the same number of bits (e.g., both `int`s, both `byte`s, both `long int`s, etc.) are compared. The result has a `1` in a given bit position if both numbers have a `1` in that position. So, `x & y` gives `12`, which has a binary representation of `00001100`.\n", "- `|`: Bitwise OR. Two numbers with the same number of bits are compared. The result has a `1` in a given bit position if either of the numbers has a `1` in that position. So, `x | y` gives `207`, which has a binary representation of `11001111`.\n", "- `^`: Bitwise XOR. Two numbers with the same number of bits are compared. The result has a `1` in a given bit position if the two numbers have different numbers in that position. So, `x ^ y` gives `195`, which has a binary representation of `11000011`.\n", "\n", "We will not consider operations that work on the binary representation of a single number.\n", "\n", "- `~`: Bitwise NOT. I call this operator a bit-flipper, since it flips the bits of a number, changing a 1 to a 0 and a 0 to a 1. `~x` gives `-78`. Wait.... WHAT!? It turns out that the `~` operator does not work on `byte`s, but on `int`s. The compiler will case the `byte` variable as an `int` in order to perform the `~` operation. Remember that an `int` is a *signed* integer, meaning that one of the bits is used to indicate the sign of the number. By convention, that is the first bit, the so-called **highest bit**. The variable `x` as an `int` has representation `0000000001001101`. The highest bit is the sign, which is zero in this case, indicating a positive number. Applying bitwise NOT gives `-78`, which has a binary representation of `1111111110110010`. For any `int` `x`, `~x` is equivalent go `-x - 1`.\n", "- `<<`: Left bitshift. This operation slides the `1`s and `0`s leftward a set number of steps, padding the right bits with zeros and discarding bits that get shifted off to the left. `x << 3` will shift the bits three places to the left and gives `616`. Wait..... WHAT AGAIN!? The result of a bitshift operation is an `int`. So, this bitshift results in `0000001001101000`, which has a decimal value of 616. Conversely, `x << 13` gives `-24576`, which has a binary representation of `1010000000000000`. Note that the second operand (in our case, we used `3` and `13`) must be less than or equal to 32.\n", "- `>>`: Right bitshift. This operations slides `1`s and `0`s rightward a set number of steps, discarding bits that are shifted off to the right. *Be careful*, the bits that are padded to the left are whatever the highest bit is if you are using an `int`. That means that negative integers are padded with `1`s and positive integers are padded with `0`s. This method of padding is called **sign extension**. So, `x >> 3` gives 9, which has a binary representation of `0000000001001`. Conversely, consider a right bitshift on `-77`, which has a binary representation of `1111111110110011`. `-77 >> 3` gives `-10`, which has a binary representation of `1111111111110110`." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Conditionals\n", "\n", "We have now seen the various data types and operations we can do with them. Let us now turn our attention to control flow, starting with conditionals. " ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### if statements\n", "\n", "An `if` statement has the following syntax.\n", "\n", "```arduino\n", "if (expression_that_evaluates_to_a_bool) {\n", " // Expressions that are evaluated in the case of true\n", "}\n", "else {\n", " // Expressions that are evaluated in the case of false\n", "}\n", "```\n", "\n", "The else clause may be omitted. You may also chain `if` statements together.\n", "\n", "```arduino\n", "if (expression_that_evaluates_to_a_bool) {\n", " // Expressions that are evaluated in the case of true\n", "}\n", "else if (another_expression_that_evaluates_to_a_bool) {\n", " // Expressions that are evaluated in the case of true for another expression\n", "}\n", "else {\n", " // Expressions that are evaluated in the case of falses for all if's\n", "}\n", "```\n", "\n", "You can have as many `else if` blocks as you like." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### switch cases\n", "\n", "We can also use **switch-cases** as conditionals. Let's say we have a `char` variable called `var` that can take on 26 values, `'A'`, `'B'`, `'C'`, etc. We want to do specific tasks when the value is `'A'`, `'B'`, or `'C'`, and a different task if it is any other letter. A switch-case accomplishes this.\n", "\n", "```arduino\n", "switch(var) {\n", " case 'A':\n", " // Do what I want for 'A'\n", " break;\n", " case 'B':\n", " // Do what I want for 'B'\n", " break;\n", " case 'C':\n", " // Do what I want for 'B'\n", " break;\n", " default:\n", " // Whatever I want to do for the others\n", " break;\n", "}\n", "```\n", "\n", "A few notes.\n", "\n", "1. Note the keyword `break`. It is necessary in the switch-case and it stops evaluation of the switch case. `break` is also used to break out of loops, which we will soon see.\n", "2. The cases can be either `char`s or `int`s. \n", "3. You can omit the `default` case if you like. \n", "4. The above will give the same result as:\n", "\n", "```arduino\n", "if (var == 'A') {\n", " // Do what I want for 'A'\n", "}\n", "else if (var == 'B') {\n", " // Do what I want for 'B'\n", "}\n", "else if (var == 'C') {\n", " // Do what I want for 'C'\n", "}\n", "else {\n", " // Whatever I want to do for the others\n", "}\n", "```\n", "\n", "Switch-cases are typically preferred when evaluating fixed data values, whereas if statements are preferred when evaluating expressions that give a Boolean." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Iteration\n", "\n", "There are three structures for iteration, a for loop, a while loop, and a do-while loop." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### for loops\n", "\n", "A for loop is used to do a task over and over again a set number of times. A for loop looks like this:\n", "\n", "```arduino\n", "for (initialization; condition_to_keep_going; increment) {\n", " // Stuff you want to do over and over\n", "}\n", "```\n", "\n", "The initialization happens when the loop is first entered. Usually, it initializes a counter that you will increment in a for loop. The condition is tested at the beginning of each iteration through the loop. If the expression for the condition must give `true` or `false`. If it gives `false`, iteration is terminated. Finally, the increment statement is run after each cycle of the loop.\n", "\n", "For example, to make an LED flash exactly ten times, you might do this.\n", "\n", "```arduino\n", "for (int i = 0; i < 10; i++) {\n", " digitalWrite(ledPin, HIGH);\n", " delay(250);\n", " digitalWrite(ledPin, LOW);\n", " delay(250);\n", "}\n", "```\n", "\n", "Note that if the body of the loop is a single line, it can come after the `for` statement and end with a semicolon. For example, if we wanted to do something silly, like a series of delays, we could do:\n", "\n", "```arduino\n", "for (int i = 0; i < 10; i++) delay(250);\n", "```" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### while loops\n", "\n", "A while loop is used when you want to do a task over and over again until a condition is met. Its syntax is:\n", "\n", "```arduino\n", "while (condition_to_keep_going) {\n", " // Do want you want to do\n", "}\n", "```\n", "\n", "At the start of each iteration, the condition is checked. If it evaluates `false`, iteration is terminated. Inside the block of the while loop, it is important that the condition changes, otherwise the while loop will never stop. The ten-flashes of an LED written using a while loop looks like this.\n", "\n", "```arduino\n", "int i = 0;\n", "\n", "while (i < 10) {\n", " digitalWrite(ledPin, HIGH);\n", " delay(250);\n", " digitalWrite(ledPin, LOW);\n", " delay(250);\n", " i++;\n", "}\n", "```\n", "\n", "Similar to for loops, one-liner bodies can come directly after the `while` statement, with the braces being dispensable." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### do-while loops\n", "\n", "A do-while loop is just like a while loop, except the condition is evaluated at the end of the loop. This means that the body of the loop is evaluated at least once, on the first iteration. The syntax is:\n", "\n", "```arduino\n", "do {\n", " // Do want you want to do\n", "} while (condition_to_keep_going);\n", "```\n", "\n", "Here is the flash-the-LED-ten-times code as a do-while loop.\n", "\n", "```arduino\n", "int i = 0;\n", "\n", "do {\n", " digitalWrite(ledPin, HIGH);\n", " delay(250);\n", " digitalWrite(ledPin, LOW);\n", " delay(250);\n", " i++;\n", "} while (i < 10);\n", "```" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Breaking and continuing\n", "\n", "In any of the three types of loops, the `break` keyword will stop iteration and break out of the loop, heading to the next part of the program. If the `continue` keyword is encountered within the body of a loop, the rest of the body is ignored and then iteration continues." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Functions\n", "\n", "As with design of devices, it is useful to practice [modular design](https://en.wikipedia.org/wiki/Modular_programming) in the design of software. If you have a task that will be done more than once in a sketch, or that you might use in other sketches, you should write it as a function.\n", "\n", "It is easiest to see how functions are defined by looking at one. Here is a function to flash an LED *n* times.\n", "\n", "```arduino\n", "void flashLED(int ledPin, int n) {\n", " /*\n", " * Flash an LED controlled via `ledPin` `n` times.\n", " */\n", " \n", " for (int i = 0; i < 10; i++) {\n", " digitalWrite(ledPin, HIGH);\n", " delay(250);\n", " digitalWrite(ledPin, LOW);\n", " delay(250);\n", " }\n", " \n", "}\n", "```\n", "\n", "And here is another function that give the sum or an array of integers.\n", "\n", "```arduino\n", "int intSum(int ar[], int lenArray) {\n", " /*\n", " * Compute the sum of an array of integers. Doesn't check\n", " * if the sum overruns the maximum value of an int.\n", " */\n", " int sum = 0;\n", " \n", " for (int i = 0; i < lenArray; i++) {\n", " sum += ar[i];\n", " }\n", "\n", " return sum;\n", "}\n", "```\n", "\n", "Referring to the above two functions, here are some syntactical rules for functions.\n", "\n", "1. The definition of the function must start with the data type of what the function returns. If it returns nothing, use `void`.\n", "2. Each argument of the function needs to have its type declared in the function declaration.\n", "3. The body of the function follows the definition statement and is contained in braces.\n", "4. It is good practice to start your function body with comments saying what it does.\n", "5. If a function returns something, this is accomplished with a `return` statement.\n", "6. Variables used within functions need to be declared with type declarations. By default, the scope of these variables is limited to the function in which they are declared." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Onwards!\n", "\n", "There are many many more features to C++, and therefore many more ways you can program Arduino. However, the basics here are sufficient to build quite powerful programs and rapidly increase the speed of your prototypes.\n", "\n", "As always, just reading this will not make these ideas stick. You need to practice. I advise you to proceed directly to the next lesson." ] } ], "metadata": { "kernelspec": { "display_name": "Python 3", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.8.8" } }, "nbformat": 4, "nbformat_minor": 4 }