Advanced Programming Concepts
Advanced Programming Concepts
Arrays
If variables can be thought of as buckets that hold a single piece of information, then
arrays can be thought of as a collection of buckets, or a big bucket with a lot of little
buckets inside. Arrays are extremely useful for a lot of different programs basically,
any time you want to perform a similar operation on several variables (of the same type)
you should consider putting the variables in an array. For example, if I want to blink
eight LEDs at the same time, I could put them in an array, and then use a for loop to
iterate over the array, like so:
/* this is the array that holds the pin numbers our LEDs would
be connected to */
int ledPins[] = {2,3,4,5,6,7,8,9};
// in setup()we can set all the pins to output with a simple for
loop
// 8, because we have 8 elements in the array
for( int i = 0; i < 8; i++) {
// sets each ledPin in our array to OUTPUT
pinMode(ledPins[i], OUTPUT);
}
The ledPins[i] part is important; it allows us to reference each element in our array
by its place in the array, starting with 0 (which can be confusing). So, in our example
above ledPins[0] == 2, since 2 is the 1st element we put into the array. This means that
ledPins[1] == 3, and ledPins[7] == 9, and is the last element in our array.
See http://arduino.cc/en/Reference/Array for further explanation.
2011 SparkFun Electronics, Inc. SparkFun Electronics Educational Materials are Licensed under Creative Commons Attribution -ShareAlike, CC BY-SA
SparkFun Electronics Summer Semester is a trademark of SparkFun Electronics, Inc. All other trademarks contained herein are the property of their respective owners.
SparkFun Electronics Summer Semester Educational Material
Data Types
In addition to the data types already covered like integers, booleans, and characters,
there are some more data types that may prove useful for your specific application.
Float: Data type for floating point numbers (those with a decimal point). They can range
from 3.4028235E+38 down to -3.4028235E+38. Stored as 32 bits (4 bytes). A word of
advice: floating point arithmetic is notoriously unpredictable (e.g. 5.0 / 2.0 may not
always come out to 2.5), and much slower than integer operations, so use with caution.
Some readers may be familiar with the Double data type currently, the Arduino
implementation of Double is exactly the same as Float, so if youre importing code that
uses doubles make sure the implied functionality is compatible with floats.
Long: Data type for larger numbers, from -2,147,483,648 to 2,147,483,647, and store
32 bits (4 bytes) of information.
String: On the Arduino, there are really two kinds of strings: strings (with a lower case
s) can be created as an array of characters (of type char). String (with a capital S), is
a String type object. The difference is illustrated in code:
Char stringArray[10] = SparkFun;
String stringObject = String(SparkFun);
The advantage of the second method (using the String object) is that it allows you to
use a number of built-in methods, such as length(), replace(), and equals().
More methods can be found here: http://arduino.cc/en/Reference/StringObject
2011 SparkFun Electronics, Inc. SparkFun Electronics Educational Materials are Licensed under Creative Commons Attribution -ShareAlike, CC BY-SA
SparkFun Electronics Summer Semester is a trademark of SparkFun Electronics, Inc. All other trademarks contained herein are the property of their respective owners.
SparkFun Electronics Summer Semester Educational Material
Pointers
Pointers seem to be one of the concepts that gives some people a bit of trouble. In the
simplest terms, a pointer is a memory address. In C-based languages (including
Arduino), when a variable is created, like so:
int foo;
A certain chunk of memory (how big a chunk is determined by the data type) is allocated
to storing the value of that variable. That chunk of memory also has an address. Most of
the time we, as programmers dont have to deal with the address, but sometimes
dealing directly with a pointer to an address is more efficient. To declare a variable to be
a pointer, use an asterisk (*) before the variable name like so:
int *pnt;
Typically, we would say that pnt is declared as a pointer to int. If we want to assign our
pointer to the memory address of foo, we can use the & operator, (usually called the
reference or address-of operator), like so:
int *pnt = &foo;
This tells our pointer to point to the address of our foo variable (not the value of it).
To get or assign a value with a pointer, you need to use the dereference operator (*).
Assigning the value from our pointer to a regular integer looks like this:
int foo2 = *pnt;
Assigning a number value to our pointer can be done like so:
*pnt = 100; //sets whatever pnt is pointing to a value of 100
Note that we cannot simply say:
pnt = 100;
This would change the memory address of the pointer to 100 and since theres
probably nothing at memory address 100, we would get an error.
Theres plenty more on pointers on the internet, mostly within the C language.
Note that in Arduino programming, you may never have to use a pointer, although for
certain operations it will simplify your code but only if you know what youre doing.
2011 SparkFun Electronics, Inc. SparkFun Electronics Educational Materials are Licensed under Creative Commons Attribution -ShareAlike, CC BY-SA
SparkFun Electronics Summer Semester is a trademark of SparkFun Electronics, Inc. All other trademarks contained herein are the property of their respective owners.
SparkFun Electronics Summer Semester Educational Material
2011 SparkFun Electronics, Inc. SparkFun Electronics Educational Materials are Licensed under Creative Commons Attribution -ShareAlike, CC BY-SA
SparkFun Electronics Summer Semester is a trademark of SparkFun Electronics, Inc. All other trademarks contained herein are the property of their respective owners.
SparkFun Electronics Summer Semester Educational Material
Switch/Case statements
Sometimes youve got a bunch of if statements that all check the same variable. It is
possible to combine all these if statements into one statement called a Switch/Case
statement. The Switch/Case statement will check the value of a given variable against
the values specified in the case statements and execute code if the values match. So
for example (from the Arduino Reference):
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
}
The example above uses an integer variable called var and has cases that check if var
is equal to 1 or 2 with a default to handle all the other values it could have. Here is some
pseudo-code to explain the syntax:
switch (var) {
case label:
// code that executes when var is equal to label
break;
case label:
// code that executes when var is equal to label
break;
default:
// code that executes when var is equal to label
}
2011 SparkFun Electronics, Inc. SparkFun Electronics Educational Materials are Licensed under Creative Commons Attribution -ShareAlike, CC BY-SA
SparkFun Electronics Summer Semester is a trademark of SparkFun Electronics, Inc. All other trademarks contained herein are the property of their respective owners.
SparkFun Electronics Summer Semester Educational Material
Break indicates that the computer should exit the entire switch/case statement and
continue with the rest of the code in the sketch. Break is not strictly necessary when
writing a switch/case statement, but if you do omit it the computer will go on to check the
rest of the cases until it encounters a break or checks every single case. In this example
var is the only text that you might change so that it matches the variable you are
checking against. Default is optional, so you can omit it, but usual you will want to use
this as a catch all in case your variable winds up with a value you have not listed in the
various cases.
2011 SparkFun Electronics, Inc. SparkFun Electronics Educational Materials are Licensed under Creative Commons Attribution -ShareAlike, CC BY-SA
SparkFun Electronics Summer Semester is a trademark of SparkFun Electronics, Inc. All other trademarks contained herein are the property of their respective owners.
SparkFun Electronics Summer Semester Educational Material
2011 SparkFun Electronics, Inc. SparkFun Electronics Educational Materials are Licensed under Creative Commons Attribution -ShareAlike, CC BY-SA
SparkFun Electronics Summer Semester is a trademark of SparkFun Electronics, Inc. All other trademarks contained herein are the property of their respective owners.
SparkFun Electronics Summer Semester Educational Material
2011 SparkFun Electronics, Inc. SparkFun Electronics Educational Materials are Licensed under Creative Commons Attribution -ShareAlike, CC BY-SA
SparkFun Electronics Summer Semester is a trademark of SparkFun Electronics, Inc. All other trademarks contained herein are the property of their respective owners.
SparkFun Electronics Summer Semester Educational Material
The exclusive or operator XOR (^) performs the logical XOR operation on two binary
representations of equal length. The result is 1 if only the first bit or only the second bit
is 1, but returns 0 if both bits are 1 or both bits are 0. For example:
0101
XOR 0011
= 0110
Bit Shifts, as opposed to bitwise operators, occur on only a single binary representation
(not a pair). Several concepts become important when introducing bit shifting: the most
significant bit (MSB) and least significant bit (LSB). The most significant bit is the bit
position in the binary number that has the greatest value (typically the bit furthest to the
left). The least significant bit is that bit with the lowest numerical value.
There are four typical types of bit shifts that you may encounter: Arithmetic Shift, Logical
Shift, Rotate No Carry, and Rotate Through Carry. Each type of shift can either be shiftright or shift-left, indicating which direction the bits are being shifted.
Arithmetic Shifts
Arithmetic Shifts shift out the bit at either end and discard it. In a left shift, all the bit
values shift to the left, and a 0 is inserted into the new place (on the far right). In a right
shift, the sign bit is shifted in on the right (the sign bit is usually a copy of the MSB at the
time, also defining the sign of the number in some cases).
The following is an arithmetic shift right:
2011 SparkFun Electronics, Inc. SparkFun Electronics Educational Materials are Licensed under Creative Commons Attribution -ShareAlike, CC BY-SA
SparkFun Electronics Summer Semester is a trademark of SparkFun Electronics, Inc. All other trademarks contained herein are the property of their respective owners.
SparkFun Electronics Summer Semester Educational Material
Logical shifts are very similar to arithmetic shifts, with bits shifted out being replaced by
0. In the case of a left-shift, arithmetic and logical shifts are exactly the same. In the
right shift however, a 0 is always inserted with no attention paid to the sign bit.
Notice the difference in a right logical shift:
Next we have Rotate No Carry (also called Circular) and Rotate Through Carry shifts.
In a Rotate No Carry shift, the bits are rotated as if they were joined at either end the
bit that gets shifted off gets moved around to the other side instead of being discarded.
Pictured is a rotate left bit shift (no carry):
The difference between rotate through carry and rotate no-carry refers to the presence
(or absence) of a carry flag. The carry flag is basically a holder for another bit, and the
holder can be thought of as in between the two ends of the register. This means that
whatever bit gets shifted out get placed into the carry flag, and the old value that was in
the carry flag gets shifted in on the appropriate side (depending on left or right shift).
2011 SparkFun Electronics, Inc. SparkFun Electronics Educational Materials are Licensed under Creative Commons Attribution -ShareAlike, CC BY-SA
SparkFun Electronics Summer Semester is a trademark of SparkFun Electronics, Inc. All other trademarks contained herein are the property of their respective owners.
SparkFun Electronics Summer Semester Educational Material
Notice how the carry bit (labeled C) gets shifted in and replaced by the bit being shifted
out.
Fortunately, in C++ (and in Arduino) there are only two bit shifting operations, bitshift left
(<<<) and bitshift right (>>>).
Luckily, these operations are equivalent to the arithmetic shift mentioned above. For
example:
int a = 5;
// binary: 0000000000000101
int b = a << 3;
int c = b >> 3;
// binary: 0000000000000101, or back to 5
like we started with
So theres your (not so) brief introduction to bit wise operations and bit shifting.
2011 SparkFun Electronics, Inc. SparkFun Electronics Educational Materials are Licensed under Creative Commons Attribution -ShareAlike, CC BY-SA
SparkFun Electronics Summer Semester is a trademark of SparkFun Electronics, Inc. All other trademarks contained herein are the property of their respective owners.
SparkFun Electronics Summer Semester Educational Material
Casting
Say you want to map a sensor value from its normal range (0 to 1023) to a new range
(0 to 100). You want to use the map function because it does all the math for you
(yay!), but you cant because your sensor value is an integer and the map function
requires a float (in Arduino it doesnt, but in Processing it does). Are you stuck? No!
Although you could go back and change your code to make all the integers into floats,
you can also perform a cast translating one variable type into another.
It looks something like this:
int sensorValue = analogRead(A0); //our integer variable
float newValue = (float) sensorValue; //new float variable
takes the int and casts it into a float neat!
Basically, the rule is to put the data type that you want your variable to become in
parentheses when assigning it to a new variable.
For our earlier example, we could save a step by casting our variable directly in the map
statement, like so:
int sensorValue = analogRead(A0);
sensorValue = map((float)sensorValue, 0, 1023, 0, 100);
Note that there are sometimes consequences for casting. For instance, when casting
from a float to an integer, the decimal places will be lost (not rounded) so 3.7 becomes
3, as does 3.1.
2011 SparkFun Electronics, Inc. SparkFun Electronics Educational Materials are Licensed under Creative Commons Attribution -ShareAlike, CC BY-SA
SparkFun Electronics Summer Semester is a trademark of SparkFun Electronics, Inc. All other trademarks contained herein are the property of their respective owners.
SparkFun Electronics Summer Semester Educational Material
2011 SparkFun Electronics, Inc. SparkFun Electronics Educational Materials are Licensed under Creative Commons Attribution -ShareAlike, CC BY-SA
SparkFun Electronics Summer Semester is a trademark of SparkFun Electronics, Inc. All other trademarks contained herein are the property of their respective owners.
SparkFun Electronics Summer Semester Educational Material