Language Reference Flashcards
(134 cards)
setup()
The setup() function is called when a sketch starts. Use it to initialize variables, pin modes, start using libraries, etc. The setup function will only run once, after each powerup or reset of the Arduino board.
Example
int buttonPin = 3; void setup() { Serial.begin(9600); pinMode(buttonPin, INPUT); } void loop() { // ... }
loop()
After creating a setup() function, which initializes and sets the initial values, the loop() function does precisely what its name suggests, and loops consecutively, allowing your program to change and respond. Use it to actively control the Arduino board.
Example
const int buttonPin = 3; // setup initializes serial and the button pin void setup() { Serial.begin(9600); pinMode(buttonPin, INPUT); } // loop checks the button pin each time, // and will send serial if it is pressed void loop() { if (digitalRead(buttonPin) == HIGH) Serial.write('H'); else Serial.write('L'); delay(1000); }
if
if (conditional) and ==, !=, <, > (comparison operators)
if
, which is used in conjunction with a comparison operator, tests whether a certain condition has been reached, such as an input being above a certain number. The format for an if test is:
if (someVariable \> 50) { // do something here }
The program tests to see if someVariable is greater than 50. If it is, the program takes a particular action. Put another way, if the statement in parentheses is true, the statements inside the brackets are run. If not, the program skips over the code.
The brackets may be omitted after an if statement. If this is done, the next line (defined by the semicolon) becomes the only conditional statement.
if (x \> 120) digitalWrite(LEDpin, HIGH); if (x \> 120) digitalWrite(LEDpin, HIGH); if (x \> 120){ digitalWrite(LEDpin, HIGH); } if (x \> 120){ digitalWrite(LEDpin1, HIGH); digitalWrite(LEDpin2, HIGH); } // all are correct
The statements being evaluated inside the parentheses require the use of one or more operators:
Comparison Operators:
x == y (x is equal to y) x != y (x is not equal to y) x \< y (x is less than y) x \> y (x is greater than y) x \<= y (x is less than or equal to y) x \>= y (x is greater than or equal to y)
Warning:
Beware of accidentally using the single equal sign (e.g. if (x = 10)
). The single equal sign is the assignment operator, and sets x to 10 (puts the value 10 into the variable x). Instead use the double equal sign (e.g.if (x == 10)
), which is the comparison operator, and tests whether x is equal to 10 or not. The latter statement is only true if x equals 10, but the former statement will always be true.
This is because C evaluates the statement if (x=10)
as follows: 10 is assigned to x (remember that the single equal sign is the assignment operator), so x now contains 10. Then the ‘if’ conditional evaluates 10, which always evaluates to TRUE, since any non-zero number evaluates to TRUE. Consequently, if (x = 10)
will always evaluate to TRUE, which is not the desired result when using an ‘if’ statement. Additionally, the variable x will be set to 10, which is also not a desired action.
if can also be part of a branching control structure using the if…else] construction.
if/else
if/else allows greater control over the flow of code than the basic if statement, by allowing multiple tests to be grouped together. For example, an analog input could be tested and one action taken if the input was less than 500, and another action taken if the input was 500 or greater. The code would look like this:
if (pinFiveInput \< 500) { // action A } else { // action B }
else can proceed another if test, so that multiple, mutually exclusive tests can be run at the same time.
Each test will proceed to the next one until a true test is encountered. When a true test is found, its associated block of code is run, and the program then skips to the line following the entire if/else construction. If no test proves to be true, the default else block is executed, if one is present, and sets the default behavior.
Note that an else if block may be used with or without a terminating else block and vice versa. An unlimited number of such else if branches is allowed.
if (pinFiveInput \< 500) { // do Thing A } else if (pinFiveInput \>= 1000) { // do Thing B } else { // do Thing C }
Another way to express branching, mutually exclusive tests, is with the switch case statement.
for
The for statement is used to repeat a block of statements enclosed in curly braces. An increment counter is usually used to increment and terminate the loop. The for statement is useful for any repetitive operation, and is often used in combination with arrays to operate on collections of data/pins.
There are three parts to the for loop header:
for (initialization; condition; increment) {
//statement(s);
}
The initialization happens first and exactly once. Each time through the loop, the condition is tested; if it’s true, the statement block, and the increment is executed, then the condition is tested again. When the condition becomes false, the loop ends.
Example
// Dim an LED using a PWM pin int PWMpin = 10; // LED in series with 470 ohm resistor on pin 10 void setup() { // no setup needed } void loop() { for (int i=0; i \<= 255; i++){ analogWrite(PWMpin, i); delay(10); } }
Coding Tips
The C for loop is much more flexible than for loops found in some other computer languages, including BASIC. Any or all of the three header elements may be omitted, although the semicolons are required. Also the statements for initialization, condition, and increment can be any valid C statements with unrelated variables, and use any C datatypes including floats. These types of unusual for statements may provide solutions to some rare programming problems.
For example, using a multiplication in the increment line will generate a logarithmic progression:
for(int x = 2; x \< 100; x = x \* 1.5){ println(x); }
Generates: 2,3,4,6,9,13,19,28,42,63,94
Another example, fade an LED up and down with one for loop:
void loop() { int x = 1; for (int i = 0; i \> -1; i = i + x){ analogWrite(PWMpin, i); if (i == 255) x = -1; // switch direction at peak delay(10); } }
switch case
Like if statements, switch…case controls the flow of programs by allowing programmers to specify different code that should be executed in various conditions. In particular, a switch statement compares the value of a variable to the values specified in case statements. When a case statement is found whose value matches that of the variable, the code in that case statement is run.
The break keyword exits the switch statement, and is typically used at the end of each case. Without a break statement, the switch statement will continue executing the following expressions (“falling-through”) until a break, or the end of the switch statement is reached.
Example
switch (var) { case 1: //do something when var equals 1 break; case 2: //do something when var equals 2 break; default: // if nothing else matches, do the default // default is optional break; }
Syntax
switch (var) { case label: // statements break; case label: // statements break; default: // statements break; }
Parameters
var: the variable whose value to compare to the various cases
label: a value to compare the variable to
while
while loops will loop continuously, and infinitely, until the expression inside the parenthesis, () becomes false. Something must change the tested variable, or the while loop will never exit. This could be in your code, such as an incremented variable, or an external condition, such as testing a sensor.
Syntax
while(expression){ // statement(s) }
Parameters
expression - a (boolean) C statement that evaluates to true or false
Example
var = 0; while(var \< 200){ // do something repetitive 200 times var++; }
do
The do loop works in the same manner as the while loop, with the exception that the condition is tested at the end of the loop, so the do loop will always run at least once.
do { // statement block } while (test condition);
Example
do { delay(50); // wait for sensors to stabilize x = readSensors(); // check the sensors } while (x \< 100);
break
break is used to exit from a do, for, or while loop, bypassing the normal loop condition. It is also used to exit from aswitch statement.
Example
for (x = 0; x < 255; x ++)
{
analogWrite(PWMpin, x);
sens = analogRead(sensorPin);
if (sens > threshold){ // bail out on sensor detect
x = 0;
break;
}
delay(50);
}
continue
The continue statement skips the rest of the current iteration of a loop (do, for, or while). It continues by checking the conditional expression of the loop, and proceeding with any subsequent iterations.
Example
for (x = 0; x < 255; x ++)
{
if (x > 40 && x < 120){ // create jump in values
continue;
}
analogWrite(PWMpin, x);
delay(50);
}
return
Terminate a function and return a value from a function to the calling function, if desired.
Syntax:
return;
return value; // both forms are valid
Parameters
value: any variable or constant type
Examples:
A function to compare a sensor input to a threshold
int checkSensor(){ if (analogRead(0) \> 400) { return 1; else{ return 0; } }
The return keyword is handy to test a section of code without having to “comment out” large sections of possibly buggy code.
void loop(){ // brilliant code idea to test here return; // the rest of a dysfunctional sketch here // this code will never be executed }
goto
Transfers program flow to a labeled point in the program
Syntax
label:
goto label; // sends program flow to the label
Tip
The use of goto is discouraged in C programming, and some authors of C programming books claim that the gotostatement is never necessary, but used judiciously, it can simplify certain programs. The reason that many programmers frown upon the use of goto is that with the unrestrained use of goto statements, it is easy to create a program with undefined program flow, which can never be debugged.
With that said, there are instances where a goto statement can come in handy, and simplify coding. One of these situations is to break out of deeply nested for loops, or if logic blocks, on a certain condition.
Example
for(byte r = 0; r \< 255; r++){ for(byte g = 255; g \> -1; g--){ for(byte b = 0; b \< 255; b++){ if (analogRead(0) \> 250){ goto bailout;} // more statements ... } } } bailout:
; (semicolon)
; semicolon
Used to end a statement.
Example
int a = 13;
Tip
Forgetting to end a line in a semicolon will result in a compiler error. The error text may be obvious, and refer to a missing semicolon, or it may not. If an impenetrable or seemingly illogical compiler error comes up, one of the first things to check is a missing semicolon, in the immediate vicinity, preceding the line at which the compiler complained.
{ } (Curly Braces)
{} Curly Braces
Curly braces (also referred to as just “braces” or as “curly brackets”) are a major part of the C programming language. They are used in several different constructs, outlined below, and this can sometimes be confusing for beginners.
An opening curly brace “{“ must always be followed by a closing curly brace “}”. This is a condition that is often referred to as the braces being balanced. The Arduino IDE (integrated development environment) includes a convenient feature to check the balance of curly braces. Just select a brace, or even click the insertion point immediately following a brace, and its logical companion will be highlighted.
At present this feature is slightly buggy as the IDE will often find (incorrectly) a brace in text that has been “commented out.”
Beginning programmers, and programmers coming to C from the BASIC language often find using braces confusing or daunting. After all, the same curly braces replace the RETURN statement in a subroutine (function), the ENDIF statement in a conditional and the NEXT statement in a FOR loop.
Because the use of the curly brace is so varied, it is good programming practice to type the closing brace immediately after typing the opening brace when inserting a construct which requires curly braces. Then insert some carriage returns between your braces and begin inserting statements. Your braces, and your attitude, will never become unbalanced.
Unbalanced braces can often lead to cryptic, impenetrable compiler errors that can sometimes be hard to track down in a large program. Because of their varied usages, braces are also incredibly important to the syntax of a program and moving a brace one or two lines will often dramatically affect the meaning of a program.
The main uses of curly braces
Functions
void myfunction(datatype argument){ statements(s) }
Loops
while (boolean expression) { statement(s) } do { statement(s) } while (boolean expression); for (initialisation; termination condition; incrementing expr) { statement(s) }
Conditional statements
if (boolean expression) { statement(s) } else if (boolean expression) { statement(s) } else { statement(s) }
// (Single Line Comment)
Comments are lines in the program that are used to inform yourself or others about the way the program works. They are ignored by the compiler, and not exported to the processor, so they don’t take up any space on the Atmega chip.
Comments only purpose are to help you understand (or remember) how your program works or to inform others how your program works. There are two different ways of marking a line as a comment:
Example
x = 5; // This is a single line comment. Anything after the slashes is a comment // to the end of the line /\* this is multiline comment - use it to comment out whole blocks of code if (gwb == 0){ // single line comment is OK inside a multiline comment x = 3; /\* but not another multiline comment - this is invalid \*/ } // don't forget the "closing" comment - they have to be balanced! \*/
Tip
When experimenting with code, “commenting out” parts of your program is a convenient way to remove lines that may be buggy. This leaves the lines in the code, but turns them into comments, so the compiler just ignores them. This can be especially useful when trying to locate a problem, or when a program refuses to compile and the compiler error is cryptic or unhelpful.
/* */ (Multi Line Comment)
Comments are lines in the program that are used to inform yourself or others about the way the program works. They are ignored by the compiler, and not exported to the processor, so they don’t take up any space on the Atmega chip.
Comments only purpose are to help you understand (or remember) how your program works or to inform others how your program works. There are two different ways of marking a line as a comment:
Example
x = 5; // This is a single line comment. Anything after the slashes is a comment // to the end of the line /\* this is multiline comment - use it to comment out whole blocks of code if (gwb == 0){ // single line comment is OK inside a multiline comment x = 3; /\* but not another multiline comment - this is invalid \*/ } // don't forget the "closing" comment - they have to be balanced! \*/
Tip
When experimenting with code, “commenting out” parts of your program is a convenient way to remove lines that may be buggy. This leaves the lines in the code, but turns them into comments, so the compiler just ignores them. This can be especially useful when trying to locate a problem, or when a program refuses to compile and the compiler error is cryptic or unhelpful.
define
#define
is a useful C component that allows the programmer to give a name to a constant value before the program is compiled. Defined constants in arduino don’t take up any program memory space on the chip. The compiler will replace references to these constants with the defined value at compile time.
This can have some unwanted side effects though, if for example, a constant name that had been #defined is included in some other constant or variable name. In that case the text would be replaced by the #defined number (or text).
In general, the const keyword is preferred for defining constants and should be used instead of #define.
Arduino defines have the same syntax as C defines:
Syntax
#define constantName value
Note that the # is necessary.
Example
#define ledPin 3 // The compiler will replace any mention of ledPin with the value 3 at compile time.
Tip
There is no semicolon after the #define statement. If you include one, the compiler will throw cryptic errors further down the page.
#define ledPin 3; // this is an error
Similarly, including an equal sign after the #define statement will also generate a cryptic compiler error further down the page.
#define ledPin = 3 // this is also an error
See
include
include is used to include outside libraries in your sketch. This gives the programmer access to a large group of standard C libraries (groups of pre-made functions), and also libraries written especially for Arduino.
The main reference page for AVR C libraries (AVR is a reference to the Atmel chips on which the Arduino is based) is here.
Note that #include, similar to #define, has no semicolon terminator, and the compiler will yield cryptic error messages if you add one.
Example
This example includes a library that is used to put data into the program space flash instead of ram. This saves the ram space for dynamic memory needs and makes large lookup tables more practical.
#include <avr> prog_uint16_t myConstants[] PROGMEM = {0, 21140, 702 , 9128, 0, 25764, 8456, 0,0,0,0,0,0,0,0,29810,8968,29762,29762,4500};</avr>
= (Assignment Operator)
= assignment operator (single equal sign)
Stores the value to the right of the equal sign in the variable to the left of the equal sign.
The single equal sign in the C programming language is called the assignment operator. It has a different meaning than in algebra class where it indicated an equation or equality. The assignment operator tells the microcontroller to evaluate whatever value or expression is on the right side of the equal sign, and store it in the variable to the left of the equal sign.
Example
int sensVal; // declare an integer variable named sensVal sensVal = analogRead(0); // store the (digitized) input voltage at analog pin 0 in SensVal
Programming Tips
The variable on the left side of the assignment operator ( = sign ) needs to be able to hold the value stored in it. If it is not large enough to hold a value, the value stored in the variable will be incorrect.
Don’t confuse the assignment operator [=] (single equal sign) with the comparison operator [==] (double equal signs), which evaluates whether two expressions are equal.
See Also
+ - * /
Addition, Subtraction, Multiplication, & Division
Description
These operators return the sum, difference, product, or quotient (respectively) of the two operands. The operation is conducted using the data type of the operands, so, for example, 9 / 4
gives 2
since 9 and 4 are ints. This also means that the operation can overflow if the result is larger than that which can be stored in the data type (e.g. adding 1 to an int with the value 32,767 gives -32,768). If the operands are of different types, the “larger” type is used for the calculation.
If one of the numbers (operands) are of the type float or of type double, floating point math will be used for the calculation.
Examples
y = y + 3; x = x - 7; i = j \* 6; r = r / 5;
Syntax
result = value1 + value2; result = value1 - value2; result = value1 \* value2; result = value1 / value2;
Parameters:
value1: any variable or constant
value2: any variable or constant
Programming Tips:
- Know that integer constants default to int, so some constant calculations may overflow (e.g. 60 * 1000 will yield a negative result).
- Choose variable sizes that are large enough to hold the largest results from your calculations
- Know at what point your variable will “roll over” and also what happens in the other direction e.g. (0 - 1) OR (0 - - 32768)
- For math that requires fractions, use float variables, but be aware of their drawbacks: large size, slow computation speeds
- Use the cast operator e.g. (int)myFloat to convert one variable type to another on the fly.
% (Modulo)
% (modulo)
Description
Calculates the remainder when one integer is divided by another. It is useful for keeping a variable within a particular range (e.g. the size of an array).
Syntax
result = dividend % divisor
Parameters
dividend: the number to be divided
divisor: the number to divide by
Returns
the remainder
Examples
x = 7 % 5; // x now contains 2 x = 9 % 5; // x now contains 4 x = 5 % 5; // x now contains 0 x = 4 % 5; // x now contains 4
Example Code
/\* update one value in an array each time through a loop \*/ int values[10]; int i = 0; void setup() {} void loop() { values[i] = analogRead(0); i = (i + 1) % 10; // modulo operator rolls over variable }
==
x == y (x is equal to y)
!=
x != y (x is not equal to y)
<
x < y (x is less than y)
// save some unsigned ints
const PROGMEM uint16_t charSet[] = { 65000, 32796, 16843, 10, 11234};
// save some chars
const char signMessage[] PROGMEM = {"I AM PREDATOR, UNSEEN COMBATANT. CREATED BY THE UNITED STATES DEPART"};
unsigned int displayInt;
int k; // counter variable
char myChar;
void setup() {
Serial.begin(9600);
while (!Serial);
// put your setup code here, to run once:
// read back a 2-byte int
for (k = 0; k < 5; k++)
{
displayInt = pgm_read_word_near(charSet + k);
Serial.println(displayInt);
}
Serial.println();
// read back a char
int len = strlen_P(signMessage);
for (k = 0; k < len; k++)
{
myChar = pgm_read_byte_near(signMessage + k);
Serial.print(myChar);
}
Serial.println();
}
void loop() {
// put your main code here, to run repeatedly:
}
const char string_0[] PROGMEM = "String 0"; // "String 0" etc are strings to store - change to suit.
const char string_1[] PROGMEM = "String 1";
const char string_2[] PROGMEM = "String 2";
const char string_3[] PROGMEM = "String 3";
const char string_4[] PROGMEM = "String 4";
const char string_5[] PROGMEM = "String 5";
// Then set up a table to refer to your strings.
const char* const string_table[] PROGMEM = {string_0, string_1, string_2, string_3, string_4, string_5};
char buffer[30]; // make sure this is large enough for the largest string it must hold
void setup()
{
Serial.begin(9600);
while(!Serial);
Serial.println("OK");
}
void loop()
{
/* Using the string table in program memory requires the use of special functions to retrieve the data.
The strcpy_P function copies a string from program space to a string in RAM ("buffer").
Make sure your receiving string in RAM is large enough to hold whatever
you are retrieving from program space. */
for (int i = 0; i < 6; i++)
{
strcpy_P(buffer, (char*)pgm_read_word(&(string_table[i]))); // Necessary casts and dereferencing, just copy.
Serial.println(buffer);
delay( 500 );
}
}