Chapter 2. Arduino

This chapter is a modified version of the Arduino primer initially published as an appendix of my book The Maker’s Guide to the Zombie Apocalypse from NoStarch Press and is used here with their kind permission.

If you are new to Arduino, this chapter will get you started with this great little board. 

What Is an Arduino?

There are various types of Arduino boards, but by far the most common and the one that is used for all the projects in this book is the Arduino Uno (see Figure 2-1).

The Arduino Uno has gone through a number of revisions. The Arduino Uno shown in Figure 2-1 is a revision 3 (R3) board (the latest at the time of writing).

Let’s start our tour of the Arduino with the USB socket, which serves several purposes: it can be used to provide power to the Arduino, for programming the Arduino from your computer, and finally, as a communications link. 

The little red button next to the USB socket is the Reset button. When you press this, the Arduino will restart and run the program that is installed on it.

Figure 2-1. An Arduino Uno R3

Along both the top and bottom edges of the Arduino, there are connection sockets to which electronics can be attached. The digital inputs and outputs, identified by a number between 0 and 13, can be seen at the top of Figure 2-1. Each pin can be configured in your programs to be either an input or an output. You might connect a switch to a digital input, and the digital input will be able to tell if the switch is pressed or not. Alternatively, you might connect an LED to a digital output and by changing the digital output from low to high, you can turn the LED on. In fact there is one LED built onto the board called the “L” LED that is connected to digital pin 13.

Beneath the digital I/O pins, there is a power LED that simply indicates that the board is powered. The ICSP (In-Circuit Serial Programming) header is only for advanced programming of the Arduino without using the USB connection. Most users of Arduino will never use the ICSP header.

It is worth highlighting the ATMega328 (the brains of the Arduino). The ATMega328 is a microcontroller IC (Integrated Circuit). This chip stores the program that the Arduino will run (it contains 32 KB of flash memory).

Below the ATMega328, there is a row of analog input pins labeled A0 to A5. Whereas digital inputs can only tell if something is on or off, analog inputs can measure the voltage at the pin (as long as the voltage is between 0 and 5V). Such a voltage could be from a sensor of some sort. If you run short of digital inputs and outputs, then these analog input pins can also be used as digital inputs and outputs.

Next to this, there is a row of power connectors that can be used as alternative ways of supplying power to the Arduino. They can also be used to supply power to other electronics that you build.

The Arduino also has a DC power jack. This can accept anything between 7V and 12V DC and uses a voltage regulator to provide the 5V that the Arduino operates on. The Arduino will automatically accept power from the USB socket and power from the DC connector depending on which is connected. 

Installing the Arduino IDE

The Arduino is not quite what you would expect from a computer.  It has no operating system, and you do not connect a keyboard, monitor, or mouse to it. It only ever runs a single program and you have to upload that program to its flash memory using a proper computer. You can reprogram the Arduino as many times as you like (well, many thousands of times).

In order to program the Arduino, you need to install the Arduino IDE on your computer. The cross-platform nature of this software—the Arduino IDE can be run on Windows, Mac, and Linux—is one of the reasons for the Arduino’s great popularity. In addition, the Arduino IDE allows you to program the Arduino over a USB connection without any need for special programming hardware.

To install the Arduino IDE for your platform, download the software and then follow the instructions on the Arduino website.

Note that Windows and Mac users will need to install USB drivers so that the Arduino IDE can communicate with the Arduino itself.

Once everything is installed, run the Arduino IDE. Figure 2-2 shows the Arduino IDE window.

The Upload button will, as the name suggests, upload the sketch to the Arduino board. Before it uploads the sketch, it converts the textual programming code into executable code for the Arduino. If there are errors, they will be displayed in the Log area. The Verify button does the same thing but without taking the final step of uploading the program to the board.

Figure 2-2. The Arduino IDE

The Serial Monitor button opens up the Serial Monitor window, which is used for communicating with the Arduino. You will use the Serial Monitor in many of the experiments in this book, as it is a great way of sending commands to an Arduino from your computer. The Serial Monitor allows two-way communication, which means that you can send text messages to the Arduino and also receive responses from it.

The Status area at the bottom of the window will tell you the type of Arduino and its corresponding serial port through which it will be programmed when the Upload button is pressed. The port shown in Figure 2-2 (/dev/cu.usbmodem411) is of the type you would expect to see when using a Mac or Linux computer. If you are using a Windows computer to program the Arduino, then this will be COM4, or COM followed by a number that Windows allocated to the Arduino when you connected it.

Last but not least, the main part of the Arduino IDE is the Program Area where you type the program code that you want to upload to the Arduino.

In the world of Arduino, programs are called sketches, and the File menu of the Arduino IDE allows you to Open and Save sketches as you would a document in a word processor. The File menu also has an Examples sub-menu from which you can load Arduino’s built-in example sketches.

Uploading a Sketch

To test out your Arduino board, and to make sure the Arduino IDE is properly installed, start by opening the example sketch called Blink. You will find this by navigating to File –› Examples –› 01. Basics. (The Blink sketch is the example that is loaded in Figure 2-2).

Use a USB lead to attach your Arduino to the computer you are going to use to program the Arduino. You should see the power LED of the Arduino light up and a few of the other LEDs flicker as it is plugged in.

Now that the Arduino is connected, you need to tell the Arduino both the type of board being programmed (Arduino Uno) and the serial port that it is connected to. Set the board type by navigating to Tools –›  Board –› Arduino Uno.

Set the serial port  by navigating to Tools –› Serial Port. If you are using a Windows computer there are not likely to be many options there. In fact, you may just find the option COM4. On a Mac or Linux computer, there are generally a variety of USB devices listed and it can be difficult to determine which one is your Arduino board. You should see an item in the list that starts dev/tty.usbmodemNNN where NNN is a number. In Figure 2-3, the Arduino attached to my Mac has been selected.

Figure 2-3. Selecting the Arduino serial port

If your Arduino does not show up in the list, then this usually points to a problem with the USB drivers. If so, try reinstalling them.

Once you are ready to upload the sketch to the Arduino, press the Upload button. Messages should start to appear in the Log area of the window and then after a few seconds, the LEDs labeled “TX” and “RX” on the Arduino should start flickering as the program is uploaded onto the board.

If everything goes according to plan, when the upload is complete, you should see a message something like the one shown in Figure 2-4.

Figure 2-4. A successful upload

This message tells you that the sketch has uploaded, and that it has used 1,084 bytes of the 32,256 bytes available.

After the sketch has finished uploading, you will notice that the built-in “L” LED on the Arduino will be slowly blinking on and off. This is your newly uploaded Blink sketch living up to its name.

The Book Code

All of the software for this book—both Arduino sketches (as Arduino programs are called) and Python programs for the  Raspberry Pi—is available from the book’s GitHub page.

To get the files onto your Mac, Linux, or Windows computer, click the Download ZIP button, which is found in the bottom right of the GitHub page.

This will download a ZIP file that you can save on your desktop or other convenient location. When you expand the ZIP archive, it will unpack a directory called make_action-master/. You will find the Arduino code in a directory called arduino/. Inside the arduino/ directory are two subdirectories, experiments/ and projects/.

Each experiment or project program is held in a directory of its own and within that there is usually a single file that is the actual program. For example, within the directory experiments/, you will find the directory ex_01_basic_motor_control/, which contains the single file basic_motor_control.ino. If you already have the Arduino IDE installed, then opening this file will open it in the Arduino IDE. 

An alternative way of gaining access to these sketches is to copy both the experiments and projects folders into your Arduino sketchbook directory, which is called Arduino/ and will be in your normal documents folder (such as My Documents/ on Windows or Documents/ on a Mac). 

If the files are copied to the sketchbook/ directory, then you will be able to open them by navigating to File –› Sketchbook in the Arduino IDE.

Programming Guide

This section contains an overview of the main commands to help you understand the sketches used in the book. If you are new to programming and want to learn Arduino C, you should consider reading my book Programming Arduino: Getting Started with Sketches

Setup and Loop

All Arduino sketches must include a setup() function and a loop() function (functions are blocks of program code that do something). To see how the setup() and loop() work, let’s dissect the Blink example that we uploaded to the Arduino:

int led = 13;
// the setup routine runs once when you press reset:
void setup() {                
  // initialize the digital pin as an output.
  pinMode(led, OUTPUT);     
}

// the loop routine runs over and over again forever:
void loop() {
  digitalWrite(led, HIGH);   // turn the LED on (HIGH is the voltage level)
  delay(1000);               // wait for 1 second
  digitalWrite(led, LOW);    // turn the LED off by making the voltage LOW
  delay(1000);               // wait for 1 second
}

You will notice that quite a lot of the text of the sketch has a // in front of it. This indicates that the rest of the text after // until the end of the line is to be treated as a comment. It’s not program code, it’s just documentation that tells the person looking at the program what is going on.

As the comments say, the lines of code inside the setup() function are run just once (or more precisely every time power is applied to the Arduino or the Reset button is pressed). So, you use setup() to do all the things you need to do just once when the program starts. In the case of Blink, this just means specifying that the LED pin is set to be an output.

The commands inside the loop() function will be run over and over again—that is, as soon as the last of the command lines in loop() has done its business, it will start over on the first line again.

I have skipped over what the commands inside setup() and loop() actually do in Blink, but don’t worry, I will discuss them soon.

Variables

Variables are a way of giving names to values.  The first line of Blink (ignoring comments) is as follows:

int led = 13;

This defines a variable called led and gives it an initial value of 13. The value 13 is chosen because this is the name of the Arduino pin that the L LED is connected to and int is the type of variable. The word int is short for integer and means a whole number (no decimal points).

Although it’s not required to use a variable name for every pin that you use, it is a good idea to do so, because it makes it easier to see what the pin is used for. Also, should you want to use a different pin, you only need to change the value of the variable in one place where you define it.

You may have noticed that in the sketches that accompany this book, when declaring variables like this that define a pin to be used, the line has const at the front of it like this:

const int led = 13;

The const keyword tells the Arduino IDE that the variable is not really a variable, but is a constant; in other words, its value is never going to change from 13. This does result in slightly smaller and faster running sketches and is generally considered to be a good habit to get into.

Digital Outputs

The Blink sketch is a good example of a digital output. Pin 13 is configured to be an output in the setup() function by this line (the variable led having earlier been defined to be 13):

pinMode(led, OUTPUT);

This is in the setup() function because it only needs to be done once. Once the pin is set to be an output, it will stay as an output until we tell it to be something else.

Turning the LED on and off to make it blink needs to happen more than once, so the code for this goes inside:

digitalWrite(led, HIGH);   // turn the LED on (HIGH is the voltage level)
delay(1000);               // wait for 1 second
digitalWrite(led, LOW);    // turn the LED off by making the voltage LOW
delay(1000);               // wait for 1 second

The digitalWrite() has two parameters (inside parentheses and separated by a comma). The first parameter is the Arduino pin to write to and the second parameter is the value to be written to the pin. So, a value of HIGH will set the output to 5V (which turns on the LED) and a value of LOW will set the pin to 0V turning the LED off.

The delay() function pauses the program for the amount of time (in milliseconds) specified as a parameter. There are 1,000 milliseconds in 1 second, so each of the delay() functions shown here will pause the program for 1 second.

In “Experiment: Controlling an LED” you will use a digital output connected to an external LED and make that blink rather than the built-in LED.

Digital Inputs

Being mostly concerned with outputs rather than inputs, this book primarily uses digitalWrite(). However, you should also know about digital inputs, which can be used to attach switches and sensors to an Arduino.

You can set an Arduino pin to be a digital input using the pinMode() function. The following example would set pin 7 to be an input. You could of course use a variable name in place of 7.

Just as you would with an output, you define an input pin in the setup() function, as it is rare to change the mode of a pin once the sketch is running:

pinMode(7, INPUT)

Having set the pin to be an input, you can then read the pin to determine if the voltage at that pin is closer to 5V (HIGH) or closer to 0V (LOW). In this example, the LED will be turned on if the input is LOW at the time it is tested (once lit, the LED will stay lit, as there is nothing in the code to turn it off again):

void loop() 
{
  if (digitalRead(7) == HIGH)
  {
    digitalWrite(led, LOW)
  }
}

Suddenly, the code has started to get a little complex, so we’ll go over it one line at a time.

On the second line, we have a { symbol. Sometimes this is put on the same line as loop() and sometimes on the next line. This is just a matter of personal preference; it has no effect on the running of the code. The { symbol marks the start of a block of code that ends with its matching } symbol. It is a way of grouping together all the lines of code that belong to the loop function.

The first of these lines uses the if statement.  Immediately after the word “if” is a condition. In this case the condition is (digitalRead(7) == HIGH). The double equals sign (==) is a way of comparing the two values on either side of it. So, in this case, if pin 7 is HIGH, then the block of code surrounded by { and } after if will run, otherwise it won’t. Lining up the { and } makes it easier to see which } belongs to which {.

We have already seen the code to be run if the condition is true. This is the digitalWrite() function that we used to turn the LED on.

In this example, it is assumed that the digital input is firmly HIGH or LOW. If you are using a switch connected to a digital input, then all that switch can do is close a connection. Typically, this will mean connecting the digital input to GND (0V). If the switch’s connection is open, then the digital input will be said to be floating. In other words, electrically it’s not connected firmly to anything. The input will pick up electrical noise and can often alternate between high and low. To prevent this undesirable behavior, a pull-up resistor is normally used, as shown in Figure 2-5.

Figure 2-5. Using a pull-up resistor with a digital input

When the switch is not closed (as shown in Figure 2-5) the resistor pulls the input pin up to 5V. When the switch is closed by pressing the button, the weak pulling up of the input is overwhelmed by the switch connecting the digital input to GND.

Although you can use an actual pull-up resistor, Arduino inputs have built-in pull-up resistors of about 40kΩ in value that are enabled if you set the pin mode to be INPUT_PULLUP rather than just INPUT. The following code demonstrates how you would set the pin mode of a digital input to be used with a switch, without having to use an external pull-up resistor shown in Figure 2-5:

pinMode(switchPin, INPUT_PULLUP);

Analog Inputs

Analog inputs allow you to measure a voltage between 0 and 5V on any of the special analog input pins of the Arduino labeled A0 to A5. Unlike digital inputs and outputs, you do not need to use the pinMode() in setup when using an analog input.

To read the value of an analog input, use the analogRead() function, supplying the name of the pin you want to read as a parameter. Unlike digitalRead(), analogRead() returns a number rather than just true or false. The number that you get back from analogRead() is a number between 0 and 1,023. A result of 0 means 0V and 1,023 means 5V. To convert the number you get back from analogRead() to an actual voltage, you need to multiply the number by 5 and then divide it by 1,023—or you can simply divide it by 204.6. Here’s how you would do it in Arduino C:

int raw = analogRead(A0);
float volts = raw / 204.6;

The variable raw is an int (whole number) because the reading from an analog input is always a whole number. However, to scale the raw reading to be a decimal number, the variable needs to be of type float (floating point).

You can connect various sensors to analog inputs—for example, later in the book, you will learn how to use an analog input with a photoresistor light sensor (see “Project: Arduino House Plant Waterer” ) and how to connect a variable resistor (see “Project: A Thermostatic Beverage Cooler”).

Analog Outputs

Digital outputs allow you to turn something (for example, an LED) on and off. But if you want to control the power to something in a graduated way, you need to use an analog output. An analog output is useful for controlling the brightness of an LED or the speed of a motor, for instance. As you might expect, this book will use this feature quite a lot.

Not all the pins of an Arduino Uno are capable of acting as an analog output—you must use D3, D5, D6, D9, D10, or D11. These pins are marked with a little ~ next to the pin on the Arduino itself.

To control an analog output, use the analogWrite() function with a number between 0 and 255 as the parameter. A value of 0 means 0V (completely off), and a value of 255 is fully on.

It is tempting to think of an analog output as being a voltage between 0 and 5V, and if you attach a volt meter between a pin being used as an analog output and GND, the voltage will indeed seem to change between 0 and 5V as you change the value that you use in your analogWrite(). In fact, things are a little more complex than that. Figure 2-6 shows what is really going on with this kind of output, which is called pulse-width modulation (PWM).

An analog output pin generates 490 pulses per second on all the analog output–capable pins (except D5 and D6, which operate at 980 pulses per second). The width of the pulses are varied. The larger the proportion of the time that the pulse stays high, the greater the power delivered to the output, and hence the brighter the LED or faster the motor.

The reason that a volt meter reports this as a change in voltage is that the volt meter cannot respond fast enough, and therefore does a kind of averaging to produce a voltage that appears to vary smoothly. 

Figure 2-6. Analog outputs pulse-width modulation

If/Else

As you’ll recall from “Digital Inputs”, we used an if statement to perform a specified action if a certain condition is true.  To gain even greater control over the flow of code, you can use if/else, which will perform one set of code if the condition is true and a different set of code if it is false.

The following example would turn the pin LED on and off depending on whether an analog reading is greater than 500 or less than or equal to 500:

if (analogRead(A0) > 500)
{
  digitalWrite(led, HIGH);
}
else
{
  digitalWrite(led, LOW);
}

So far we have met two types of comparison operators: == (equal to) and > (greater than). There are actually some more comparisons you can make:

  • <= (less than or equal to)

  • >= (greater than or equal to)

  • != (not equal to)

In addition to comparing only two values, you can also make more complicated comparisons using && (and) and ||(or). For example, if you wanted to only turn the LED on if the reading was between 300 and 400, you would write the following:

int reading = analogRead(A0);
if ((reading >= 300) && (reading <=400))
{
  digitalWrite(led, HIGH);
}
else
{
  digitalWrite(led, LOW);
}

Loops

A loop allows code to be repeated a specified number of times or until some condition changes. To accomplish this, you either use a for loop or a while loop: for loops are better for doing something a fixed number of times, and while loops are better for doing something while some condition is true.

The for loop in the following example will make the LED blink 10 times (note that the for loop is in setup() rather than loop(), because if you put it in loop() it would blink another 10 times after it had finished the first 10 and so on, which is not the desired effect):

for (int i = 0; i < 10; i++)
{
  digitalWrite(led, HIGH);
  delay(1000);
  digitalWrite(led, LOW);
  delay(1000);
}

If you wanted to keep an LED blinking for as long as a button connected to a digital input is pressed, then you would use a while loop:

while (digitalRead(9))
{
  digitalWrite(led, HIGH);
  delay(1000);
  digitalWrite(led, LOW);
  delay(1000);
}

This code assumes that pin D9 is connected to a switch (as shown in Figure 2-5).

Functions 

Functions can cause a lot of confusion to those that are new to programming. Perhaps the easiest way to think of functions is as ways of grouping together some lines of code and giving them a name so that it is easy to use them over and over again.

If you were to look at some of the internal workings of Arduino, you would find that the built-in functions such as digitalWrite() are actually more than a little complicated. For example, here is the code for digitalWrite() (don’t worry what it does, just be glad that you don’t have to type all that code in every time you want to change pins from high to low):

void digitalWrite(uint8_t pin, uint8_t val)
{
    uint8_t timer = digitalPinToTimer(pin);
    uint8_t bit = digitalPinToBitMask(pin);
    uint8_t port = digitalPinToPort(pin);
    volatile uint8_t *out;

    if (port == NOT_A_PIN) return;

    // If the pin that support PWM output, we need to turn it off
    // before doing a digital write.
    if (timer != NOT_ON_TIMER) turnOffPWM(timer);

    out = portOutputRegister(port);

    uint8_t oldSREG = SREG;
    cli();

    if (val == LOW) {
        *out &= ~bit;
    } else {
        *out |= bit;
    }

    SREG = oldSREG;
}

By giving that big chunk of code a name, we can just refer to it by name to make use of it.

In addition to built-in functions, like digitalWrite, you can create your own functions to lump together things you use. For example, you could create a function that will blink the LED a number of times specified as a parameter. The pin to blink could also be specified as a parameter. The following sketch illustrates this, by making a function called blink and calling it during startup() so that the Arduino “L” LED blinks 5 times after a reset:

const int ledPin = 13;
void setup()
{
  pinMode(ledPin, OUTPUT);
  blink(ledPin, 5);
}

void loop() {}

void blink(int pin, int n)
{
  for (int i = 0; i < n; i++)
  {
    digitalWrite(ledPin, HIGH);
    delay(500);
    digitalWrite(ledPin, LOW);
    delay(500);
  }
}

The setup() function sets the ledPin to be an output and then calls the function blink, passing it the pin that should be blinked followed by the number of times to blink it. The loop() function is empty and does nothing, but the Arduino IDE will still insist that it is there.

The blink function itself begins with the word void, which indicates that the function does not return anything—in other words, you cannot assign the result of calling that function to a variable, as you might want to do if the function performed some kind of calculation. Following that, we see the name of the function (blink) and then the parameters that the function takes enclosed within parentheses and separated by commas. When you define a function, you must specify the type of each of the parameters (that is, whether they are an int, float, or something else). In this case, both the pin to blink (pin) and the number of times to blink (n) are ints (whole numbers).

As with most programming languages, the C programming language has the concept of global and local variables. Global variables (such as ledPin in the preceding example) can be used from anywhere in the program. On the other hand, local variables such as parameters  to functions (pin and n in this example) and even i inside the for loop are only accessible within the function in which they are defined.

So, in setup(), the line blink(ledPin, 5) passes the global variable ledPin into the function blink, where it will be assigned to the local variable pin. You might wonder why you should do this. The answer is that by passing in the pin to blink, we make the blink function general purpose, so it can be used to flash any pin we tell it to, rather than just ledPin.

In the body of the blink function, we have a for loop that will repeat the digitalWrite() and delay() functions inside it n times. So, if n is 3, the LED will blink 3 times.

Summary

In this chapter, you have learned how to install the Arduino IDE and get started with a few basic Arduino programming commands, and looked at how your code can control the Arduino’s input/output pins.

If you are new to programming, some of the concepts described in this chapter will take some time to sink in. One of the best ways to learn how to program is to look at existing examples and then alter them to get a feeling for what everything does.

All the program code used in this book is available for download via the book’s GitHub repository, so you do not have to write any of your own programs to make use of this book, although you will probably find yourself wanting to use the experiments and projects as a basis for your own project ideas.

In the next chapter, you will find a similar primer to this one, but for the Raspberry Pi.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset