Chapter 2

Programming in Python

IN THIS CHAPTER

check Learning the essentials of the Python language

check Working with variables and constants

check Creating your own function definitions

check Working with if logic

check Using lists

check Looping with for loops

In the preceding chapter, you learn how to create a basic Python program that lights up an LED connected to one of the Raspberry Pi’s digital output ports. Getting the Python programming environment set up correctly is no small accomplishment, so by all means you should congratulate yourself. Well done!

However, you need to know a little more than how to turn on an LED to call yourself a Raspberry Pi programmer. In this chapter, you learn enough Python programming features to perform truly useful things with the circuits you connect to your Raspberry Pi. You learn how to work with basic Python programming features such as variables, function definitions, if statements, loops, and lists.

This chapter is by no means a comprehensive guide to Python programming. If you want a more complete tutorial on programming with Python, I suggest Beginning Programming with Python For Dummies, by John Paul Mueller (Wiley). You can also find plenty of good information about Python programming on the Internet. A great place to start is the official website of the Python Software Foundation (www.python.org).

Looking Closer at Python

As you learn in Chapter 1 of this minibook, Python is one of several programming languages you can use to create programs to run on a Raspberry Pi. You’ve already seen a short Python program that flashes an LED on and off every 0.5 second. This program is simple, but it introduces many of the basic concepts you need to know to create Python programs. In particular:

  • Python is what is known in the world of computer programming as an interpreted language. That means that when you run a Python program, the Python shell reads the text of your Python program file, and then interprets and runs each statement one at a time. In fact, you can run Python statements without even creating a saved Python program by simply typing the statement into the Python shell. For example, when you type print “Hello, World!” in the shell and press Enter, the Python shell interprets the statement you entered and executes it, displaying the text Hello, World! on the console.

    This is in contrast to most other programming languages, which are processed by a special program called a compiler before they’re executed. The compiler converts the text of the program into machine instructions that the computer can execute. In this type of program, called a compiled program, the entire program is compiled all at once; then the compiled program is executed. In contrast, in an interpreted language, the text of the program is interpreted and executed one line at a time.

  • Unlike most other programming language, Python uses indentation to indicate how programming statements are combined together to create blocks. In a language such as C++ or Java, blocks of related statements are marked by opening and closing curly braces. Not so with Python. In Python, lines that are indented at the same level are considered part of the same block.

    You’ve already seen this in the sample program shown in the previous chapter:

    while True:
    GPIO.output(3, GPIO.HIGH)
    time.sleep(0.5)
    GPIO.output(3, GPIO.LOW)
    time.sleep(0.5)

    Here, the four statement that are indented beneath the while statement are considered to be part of the while statement.

    The preceding code would be interpreted quite differently if it had been written like this instead:

    while True:
    GPIO.output(3, GPIO.HIGH)
    time.sleep(0.5)
    GPIO.output(3, GPIO.LOW)
    time.sleep(0.5)

    In this case, the last line (time.sleep(0.5)) would not be considered a part of the same block as the three statements before it. As a result, it would not be executed in the loop indicated by the while statement.

  • Python is very loose about how you use variables. Unlike C++ or Java, you don’t have to declare variables in your Python programs or assign data types to variables. Python will figure out based on the context what kind of data is stored in each variable you use.

In case you’re wondering, Python is not named after the snake. Python’s creators were very fond of the British TV series Monty Python’s Flying Circus, and named the language in honor of the comedy troupe. (IDLE, the standard development environment for Python, technically stands for Integrated DeveLopment Environment, but it’s also a nod to one of Monty Python’s founding members, Eric Idle.)

Building a Test Circuit

All the programs in this chapter are designed to work with the circuit shown in Project 56, which connects eight LEDs to the Raspberry Pi via eight GPIO ports.

All the programs in this chapter assume that an LED is connected to the following output pins:

LED

Pin

LED

Pin

LED1

29

LED5

37

LED2

31

LED6

36

LED3

33

LED7

38

LED4

35

LED8

40

Within the programs, these pins will be referred to using the variables LED1 through LED8.

Figure 2-1 shows the finished circuit, ready to be used for testing the programs you’ll write as you work your way through this chapter.

image

FIGURE 2-1: A Raspberry Pi test circuit with eight LEDs.

Project 56: A Raspberry Pi LED Test Board

In this project, you connect a breadboard with eight LEDs to GPIO ports on a Raspberry Pi. You can then use this board to test the programs shown in this chapter.

image
image
image

Parts

  • One Raspberry Pi 2 or 3 with Raspbian installed, connected to a monitor, keyboard, and power
  • One small solderless breadboard (RadioShack 2760003)
  • Eight 5mm red LEDs (RadioShack 2760209)
  • Eight images resistors (orange-orange-brown)
  • Nine jumper wires (M/F)

Steps

  1. Insert the resistors.

    images: E3 to F3

    images: E5 to F5

    images: E7 to F7

    images: E9 to F9

    images: E11 to F11

    images: E13 to F13

    images: E15 to F15

    images: E17 to F17

  2. Insert the LEDs.

    LED

    Anode

    Cathode:

    LED1

    J3

    Ground

    LED2

    J5

    Ground

    LED3

    J7

    Ground

    LED4

    J9

    Ground

    LED5

    J11

    Ground

    LED6

    J13

    Ground

    LED7

    J15

    Ground

    LED8

    J17

    Ground

  3. Connect jumpers from the breadboard to the GPIO pins on the Raspberry Pi.

    Breadboard

    GPIO Pin

    A3

    29

    A5

    31

    A7

    33

    A9

    35

    A11

    37

    A13

    36

    A15

    38

    A17

    40

  4. Connect the ground bus to pin 39 on the Raspberry Pi.

    You can now use the programs in this chapter.

Flashing the LEDs

In the preceding chapter, I show you a program that flashes a single LED on and off. In this chapter, I show you several variants of that program, which flash the eight LEDs in the test project in various sequences. Along the way, you can add more Python statements to your repertoire to provide more and more complex ways to control the flashing.

remember Keep in mind throughout this chapter that if you can turn an LED on or off with a Python program, you can control anything that can be connected to a GPIO port. The Raspberry Pi itself doesn’t know or care what kind of circuit you connect to a GPIO port. All it knows is that when you tell it to, the Raspberry Pi makes the port HIGH or LOW. It’s the external circuitry connected to the port that determines what happens when the port goes HIGH.

The only limitation is that the Raspberry Pi itself can swing only about 16 mA through its GPIO ports. If the circuit connected to the port requires more current than 16 mA, you must isolate the higher-current portion of the circuit from the Raspberry Pi. The easiest way to do that is to use a transistor driver or a relay.

Listing 2-1 shows a simple program that flashes all eight of the LEDs on and off at half-second intervals. This program is similar to the program that is presented in the preceding chapter; the only difference is that it flashes eight LEDs instead of just one.

LISTING 2-1 Flashing LEDs

import RPi.GPIO as GPIO
import time

GPIO.setmode(GPIO.BOARD)
GPIO.setup(29, GPIO.OUT)
GPIO.setup(31, GPIO.OUT)
GPIO.setup(33, GPIO.OUT)
GPIO.setup(35, GPIO.OUT)
GPIO.setup(37, GPIO.OUT)
GPIO.setup(36, GPIO.OUT)
GPIO.setup(38, GPIO.OUT)
GPIO.setup(40, GPIO.OUT)

while True:
GPIO.output(29, GPIO.HIGH)
GPIO.output(31, GPIO.HIGH)
GPIO.output(33, GPIO.HIGH)
GPIO.output(35, GPIO.HIGH)
GPIO.output(37, GPIO.HIGH)
GPIO.output(36, GPIO.HIGH)
GPIO.output(38, GPIO.HIGH)
GPIO.output(40, GPIO.HIGH)

time.sleep(0.5)

GPIO.output(29, GPIO.LOW)
GPIO.output(31, GPIO.LOW)
GPIO.output(33, GPIO.LOW)
GPIO.output(35, GPIO.LOW)
GPIO.output(37, GPIO.LOW)
GPIO.output(36, GPIO.LOW)
GPIO.output(38, GPIO.LOW)
GPIO.output(40, GPIO.LOW)

time.sleep(0.5)

Using Comments

A comment is text that provides an explanation of your code. Python completely ignores comments, so you can put any text you want in a comment. Using plenty of comments in your programs to explain what your program does and how it works is a good programming practice.

Python lets you use two different types of comments:

  • Single-line comments: A single-line comment begins with a hash character (#) and extends to the end of the current line. Python ignores anything you type on a line following the hash character. Here’s an example:

    #Set the GPIO pin mode

  • You can also place a single-line comment at the end of a Python statement, as in this example:

    GPIO.output(29, GPIO.HIGH) #LED1

    Here, I used a comment to indicate that pin 29 is LED1.

  • Multi-line comments: A multi-line comment is a comment that spans more than one line. It starts with a group of three adjacent quotation marks and continues until another group of three quotation marks is found. Here’s an example:

    """Listing 2-1: Flash all eight LEDs.

    This version of the program demonstrates
    the use of comments.
    """

    Although it isn’t a requirement, it is customary for all Python programs to begin with a multi-line comment that provides basic information about what the program does.

Listing 2-2 shows a version of the LED Flasher program that includes both types of comments.

LISTING 2-2 LED Flasher with Comments

"""Listing 2-1: Flash all eight LEDs.

This version of the program demonstrates the use of
comments.
"""

import RPi.GPIO as GPIO
import time

#Set up the GPIO mode and output pins.
GPIO.setmode(GPIO.BOARD)
GPIO.setup(29, GPIO.OUT) #LED1
GPIO.setup(31, GPIO.OUT) #LED2
GPIO.setup(33, GPIO.OUT) #LED3
GPIO.setup(35, GPIO.OUT) #LED4
GPIO.setup(37, GPIO.OUT) #LED5
GPIO.setup(36, GPIO.OUT) #LED6
GPIO.setup(38, GPIO.OUT) #LED7
GPIO.setup(40, GPIO.OUT) #LED8

while True:
#Turn on the LEDs.
GPIO.output(29, GPIO.HIGH) #LED1
GPIO.output(31, GPIO.HIGH) #LED2
GPIO.output(33, GPIO.HIGH) #LED3
GPIO.output(35, GPIO.HIGH) #LED4
GPIO.output(37, GPIO.HIGH) #LED5
GPIO.output(36, GPIO.HIGH) #LED6
GPIO.output(38, GPIO.HIGH) #LED7
GPIO.output(40, GPIO.HIGH) #LED8

#Wait half a second.
time.sleep(0.5)

#Turn off the LEDs.
GPIO.output(29, GPIO.LOW) #LED1
GPIO.output(31, GPIO.LOW) #LED2
GPIO.output(33, GPIO.LOW) #LED3
GPIO.output(35, GPIO.LOW) #LED4
GPIO.output(37, GPIO.LOW) #LED5
GPIO.output(36, GPIO.LOW) #LED6
GPIO.output(38, GPIO.LOW) #LED7
GPIO.output(40, GPIO.LOW) #LED8

#Wait another half a second.
time.sleep(0.5)

Creating Identifiers

In Python, an identifier is a name that is used to refer to items such as variables or function names. You’ll often need to create your own identifiers when you write Python programs. When you create your own identifier, you must follow these simple rules:

  • Identifier names can contain uppercase or lowercase letters, the digits 0 through 9, or underscore (_) characters. Note that the underscore is the only special character allowed; you can’t use other punctuation in an identifier.
  • An identifier must begin with a letter or an underscore. You cannot begin an identifier with a digit.
  • Python is case-sensitive, which means that ElapsedTime and elapsedtime are two different identifiers. This rule can be an annoying source of bugs, so if your program isn’t working the way you expect it to, check the capitalization of any identifiers the program uses.

Using Constants

A constant is an identifier that has been assigned a fixed value that doesn’t change throughout the program’s execution. This allows you to use the constant name in your program rather than the value itself. Later, if you decide to change the value, you don’t have to hunt through the program to find every occurrence of the constant. Instead, you simply change the line that defines the constant. In Python, constant names are usually written in all capital letters.

To create a constant in Python, you use the equals sign to assign a value to the constant, like this:

LED1 = 29

Here I’ve created a constant named LED1 that is given a value of 29. Then I can use the constant later in the program, like this:

GPIO.output(LED1, GPIO.HIGH)

Using a constant in this way makes it easier to keep track of the pin numbers used for each of the GPIO ports used by the program.

Listing 2-3 shows a complete program that uses constants to keep track of the pin numbers.

LISTING 2-3 The LED Flasher Program with Constants

"""Listing 2-3: Blink all eight LEDs.

This version of the program uses constants to identify
the LEDs.
"""

import RPi.GPIO as GPIO
import time

LED1 = 29
LED2 = 31
LED3 = 33
LED4 = 35
LED5 = 37
LED6 = 36
LED7 = 38
LED8 = 40

GPIO.setmode(GPIO.BOARD)
GPIO.setup(LED1, GPIO.OUT)
GPIO.setup(LED2, GPIO.OUT)
GPIO.setup(LED3, GPIO.OUT)
GPIO.setup(LED4, GPIO.OUT)
GPIO.setup(LED5, GPIO.OUT)
GPIO.setup(LED6, GPIO.OUT)
GPIO.setup(LED7, GPIO.OUT)
GPIO.setup(LED8, GPIO.OUT)

while True:
GPIO.output(LED1, GPIO.HIGH)
GPIO.output(LED2, GPIO.HIGH)
GPIO.output(LED3, GPIO.HIGH)
GPIO.output(LED4, GPIO.HIGH)
GPIO.output(LED5, GPIO.HIGH)
GPIO.output(LED6, GPIO.HIGH)
GPIO.output(LED7, GPIO.HIGH)
GPIO.output(LED8, GPIO.HIGH)

time.sleep(0.5)

GPIO.output(LED1, GPIO.LOW)
GPIO.output(LED2, GPIO.LOW)
GPIO.output(LED3, GPIO.LOW)
GPIO.output(LED4, GPIO.LOW)
GPIO.output(LED5, GPIO.LOW)
GPIO.output(LED6, GPIO.LOW)
GPIO.output(LED7, GPIO.LOW)
GPIO.output(LED8, GPIO.LOW)

time.sleep(0.5)

Using Variables

A variable is an identifier that refers to a memory location whose value can change throughout the program. For example, suppose I wanted to change the rate at which the LED Flasher program flashes, starting with a rapid flash but gradually flashing at an ever slower rate. I could easily accomplish this by using a variable to represent the amount of time to wait between each flash and increasing the value of the variable with each repetition of the program’s while loop.

The first step in doing this is to create the variable. You do that the same way you create a constant — in fact, a constant is just a variable whose value does not change during the program’s execution. For example:

sleepTime = 0.05

Here, I create a variable named sleepTime and assign it an initial value of 0.05.

You could then use this variable when you call the sleep function, like this:

time.sleep(sleepTime)

This causes the program to delay the number of seconds indicated by the sleepTime variable — in this case, five one-hundredths of a second.

Later in the program, you can change the value of a variable. For example, you can add 0.05 to the variable’s value like this:

sleepTime = sleepTime + 0.05

The first time this statement is executed, the sleepTime variable is set to 0.1, which is images. The second time the statement is executed, sleepTime is set to 0.15; each time, the value of sleepTime is increased by 0.05.

Note that you can do other types of math if you want. For example:

x = 10
y = x * 3

In this example, the value of the variable x is multiplied by 3 and the result is assigned to the variable y. Thus, 30 will be assigned to the variable y.

Here are a few things to know about math in Python:

  • Python uses the normal order of operations found in math. Thus, multiplication and division are done before addition and subtraction. For example:

    x = 10
    y = x + 5 * 3

    This statement assigns the value 25 to y, because 5 is first multiplied by 3 and then the result is added to 10.

  • You can use parentheses to change the order of calculation. For example:

    x = 10
    y = (x + 5) * 3

    Here, Python first does the calculation inside the parentheses, giving a result of 15. It then multiples the 3 by the 15 to give the final result, 45.

Listing 2-4 shows a program that uses a variable to change the speed at which the LEDs flash each time the while statement causes the program to loop. As you can see, the sleepTime variable is used to provide the delay time. Each time through the loop, the value of the sleepTime variable is increased by 0.05. Thus, the LEDs flash very fast when the program first starts, but the flashing gets progressively slower as the program continues.

LISTING 2-4 The LED Flasher Program with a Variable

"""Listing 2-4: Blink all eight LEDs.

This version of the program uses a variable to gradually
slow the flash rate.
"""

import RPi.GPIO as GPIO
import time

LED1 = 29
LED2 = 31
LED3 = 33
LED4 = 35
LED5 = 37
LED6 = 36
LED7 = 38
LED8 = 40

sleepTime = 0.05

GPIO.setmode(GPIO.BOARD)
GPIO.setup(LED1, GPIO.OUT)
GPIO.setup(LED2, GPIO.OUT)
GPIO.setup(LED3, GPIO.OUT)
GPIO.setup(LED4, GPIO.OUT)
GPIO.setup(LED5, GPIO.OUT)
GPIO.setup(LED6, GPIO.OUT)
GPIO.setup(LED7, GPIO.OUT)
GPIO.setup(LED8, GPIO.OUT)

while True:
GPIO.output(LED1, GPIO.HIGH)
GPIO.output(LED2, GPIO.HIGH)
GPIO.output(LED3, GPIO.HIGH)
GPIO.output(LED4, GPIO.HIGH)
GPIO.output(LED5, GPIO.HIGH)
GPIO.output(LED6, GPIO.HIGH)
GPIO.output(LED7, GPIO.HIGH)
GPIO.output(LED8, GPIO.HIGH)

time.sleep(sleepTime)

GPIO.output(LED1, GPIO.LOW)
GPIO.output(LED2, GPIO.LOW)
GPIO.output(LED3, GPIO.LOW)
GPIO.output(LED4, GPIO.LOW)
GPIO.output(LED5, GPIO.LOW)
GPIO.output(LED6, GPIO.LOW)
GPIO.output(LED7, GPIO.LOW)
GPIO.output(LED8, GPIO.LOW)

time.sleep(sleepTime)

sleepTime = sleepTime + 0.05

Creating Your Own Functions

You have already seen how to use various functions that are part of function libraries that you can import into a Python program. For example, the statement time.sleep(1) calls a function named sleep to delay the execution of the program for one second.

technicalstuff The equivalent statements in any other programming languages, such as Arduino’s sketch language and BASIC, measure time delays in milliseconds rather than microseconds.

You can also create your own functions in Python. This can be especially useful when you have a long sequence of statements that needs to be repeated in your program. Rather than just list the statements multiple times, you can place them in a function, and call the function whenever you need the statements.

As an example, you could create a function that would turn on all eight LEDs. To do that, you write a def statement that specifies the name of the function. Then, you list all the statements that are part of the function with indentation after the def statement, like this:

def setLEDsOn():
GPIO.output(LED1, GPIO.HIGH)
GPIO.output(LED2, GPIO.HIGH)
GPIO.output(LED3, GPIO.HIGH)
GPIO.output(LED4, GPIO.HIGH)
GPIO.output(LED5, GPIO.HIGH)
GPIO.output(LED6, GPIO.HIGH)
GPIO.output(LED7, GPIO.HIGH)
GPIO.output(LED8, GPIO.HIGH)

Note that the def statement lists the name of the function (setLEDsOn), followed by an empty set of parentheses and a colon. I explain the empty parentheses in a just a moment. The colon indicates that indented lines that follow are to be executed whenever the function is called.

To call the function, you just type the name of the function as if it were any other Python statement. For example:

setLEDsOn()

When this statement is encountered, the statements that are defined for the setLEDsOn function are executed, which causes all eight LEDs to turn on.

There are two important details to note about defining and calling functions:

  • The statements that make up the function are not actually executed by the def statement. The def statement defines but does not execute the function.
  • The def statement for a function must appear in your program before any statement that calls the function.

Now to the empty parentheses that follow the function name in the def statement. A function can have one or more arguments that can be passed to it when the function is called. You’ve already seen several examples of this. For example, the time.sleep function accepts an argument that specifies the number of seconds of sleep. And the GPIO.output function accepts two arguments; the first indicates the output pin and the second indicates the output value.

The empty parentheses means that the function you’re defining doesn’t use any arguments. However, you can easily add one or more arguments to a function definition by listing argument names within the parentheses.

For example, suppose you want to create a function named setLEDs that can set the LED values to either HIGH or LOW. In that case, you could define the function like this:

def setLEDs(value):
GPIO.output(LED1, value)
GPIO.output(LED2, value)
GPIO.output(LED3, value)
GPIO.output(LED4, value)
GPIO.output(LED5, value)
GPIO.output(LED6, value)
GPIO.output(LED7, value)
GPIO.output(LED8, value)

Then, to turn the LEDs on, you would call the setLEDs function like this:

setLEDs(GPIO.HIGH)

To turn them off, call setLEDs like this:

setLEDs(GPIO.LOW)

Listing 2-5 shows a version of the LED flashing program that uses a function to flash the LEDs. As you can see, using the setLEDs function simplifies the program’s while loop.

LISTING 2-5 The LED Flasher Program with a Function

"""Listing 2-5: Blink all eight LEDs.

This version of the program defines a function to turn
the LEDs on or off.
"""

import RPi.GPIO as GPIO
import time

LED1 = 29
LED2 = 31
LED3 = 33
LED4 = 35
LED5 = 37
LED6 = 36
LED7 = 38
LED8 = 40

GPIO.setmode(GPIO.BOARD)
GPIO.setup(LED1, GPIO.OUT)
GPIO.setup(LED2, GPIO.OUT)
GPIO.setup(LED3, GPIO.OUT)
GPIO.setup(LED4, GPIO.OUT)
GPIO.setup(LED5, GPIO.OUT)
GPIO.setup(LED6, GPIO.OUT)
GPIO.setup(LED7, GPIO.OUT)
GPIO.setup(LED8, GPIO.OUT)

def setLEDs(setValue):
GPIO.output(LED1, setValue)
GPIO.output(LED2, setValue)
GPIO.output(LED3, setValue)
GPIO.output(LED4, setValue)
GPIO.output(LED5, setValue)
GPIO.output(LED6, setValue)
GPIO.output(LED7, setValue)
GPIO.output(LED8, setValue)

while True:
setLEDs(GPIO.HIGH)
time.sleep(0.5)
setLEDs(GPIO.LOW)
time.sleep(0.5)

Using If Statements

An if statement lets you add conditional testing to your programs. In other words, it lets you execute certain statements only if a particular condition is met. This type of conditional processing is an important part of any but the most trivial of programs.

Every if statement must include a conditional expression that lays out a logical test to determine whether the condition is true or false. For example:

x > 5

This condition is true if the value of the variable x is greater than 5. If x has a value that is equal to or less than 5, the condition is false.

One thing that Python has in common with other languages such as C or Java is that it requires you to use two equal signs to test for equality. For example:

x == 5

This condition is true if the value of the variable x is exactly 5. If the value is anything other than 5, the condition is false.

The basic form of an if statement looks like this:

if condition:
statements

Note that the condition is followed by a colon, and any statements that are executed if the condition is true must be indented (by the same amount) beneath the if statement.

Here’s a simple example:

if sleepTime == 0.5:
sleepTime = 1.0

This if statement looks at the value of the sleepTime variable and changes the value to 1.0 if the current value is 0.5.

The if statement can also include an else clause that provides one or more statements that are executed if the condition is not true. For example:

if sleepTime == 0.5:
sleepTime = 1.0
else:
sleepTime = 0.5

In this example, one of two things happens: If the sleepTime variable has a value of 0.5, the sleepTime variable’s value is set to 1.0. But if the sleepTime variable has a value other than 0.5, the sleepTime variable’s value is set to 0.5.

Keep in mind that both the if and else parts can have more than one statement. In that case, the indentation must be maintained, as in this example:

if Timer == 0.5:
sleepTime = 1.0
Counter = 0
else:
sleepTime = 0.5
Counter = Counter + 1

One final thing to know about if statements is that one if statement can be contained within another. This arrangement is called nesting, and is very useful for implementing complex decisions. Indentation becomes especially important when if statements are nested.

Listing 2-6 shows a program that cleverly uses a nested if statement to flash the LEDs in an alternating pattern of three quick flashes followed by three longer flashes. The program uses a variable named sleepTime to control the delay interval (0.1 for the quick flashes, 0.5 for the longer flashes) and a second variable named flashCount to count how many times the LEDs have been flashed. The nested if statement looks like this:

if flashCount == 3:
flashCount = 0
if sleepTime == 0.1:
sleepTime = 0.5
else:
sleepTime = 0.1

Here, the first if statement is used to check the flashCount variable’s value. If it is 3, the flashCount variable is reset to zero. Then a second if statement is used to set the sleepTime variable to either 0.1 or 0.5. In essence, this inner if statement toggles the sleepTime variable between 0.1 and 0.5 each time the flashCount variable reaches 3.

LISTING 2-6 The LED Flasher Program with an If Statement

"""Listing 2-6: Blink all eight LEDs.

This version of the program uses an If statement to
alternate between long and short flashes.
"""

import RPi.GPIO as GPIO
import time

LED1 = 29
LED2 = 31
LED3 = 33
LED4 = 35
LED5 = 37
LED6 = 36
LED7 = 38
LED8 = 40

sleepTime = 0.1
flashCount = 0

GPIO.setmode(GPIO.BOARD)
GPIO.setup(LED1, GPIO.OUT)
GPIO.setup(LED2, GPIO.OUT)
GPIO.setup(LED3, GPIO.OUT)
GPIO.setup(LED4, GPIO.OUT)
GPIO.setup(LED5, GPIO.OUT)
GPIO.setup(LED6, GPIO.OUT)
GPIO.setup(LED7, GPIO.OUT)
GPIO.setup(LED8, GPIO.OUT)

def setLEDs(setValue):
GPIO.output(LED1, setValue)
GPIO.output(LED2, setValue)
GPIO.output(LED3, setValue)
GPIO.output(LED4, setValue)
GPIO.output(LED5, setValue)
GPIO.output(LED6, setValue)
GPIO.output(LED7, setValue)
GPIO.output(LED8, setValue)

while True:
setLEDs(GPIO.HIGH)
time.sleep(sleepTime)
setLEDs(GPIO.LOW)
time.sleep(sleepTime)

flashCount = flashCount + 1
if flashCount == 3:
flashCount = 0
if sleepTime == 0.1:
sleepTime = .5
else:
sleepTime = 0.1

Using While Loops

So far, all the Python programs you’ve seen have used the following while statement to cause the main portion of the program to loop repeatedly as long as the program is allowed to run:

while True:

It may not surprise you to learn that the full syntax for the while statement is this:

while condition:
statements

Here, condition can be the same type of conditional test that is used in an if statement. Specifying just the word True as the conditional test is a special form of while statement that repeats forever, because the conditional test True, as its name suggest, always evaluates to True.

Note that the statement part of the while loop can be a single statement or a series of statements enclosed in curly brackets.

Here’s an example of a while loop that flashes the LEDs three times for 0.1 second:

flashCount = 0
while flashCount < 3:
setLEDs(GPIO.HIGH)
time.sleep(.1)
setLEDs(GPIO.LOW)
time.sleep(.1)
flashCount = flashCount + 1

On each execution of this loop, the setLEDs function is called twice to turn the LEDs on and off. Then, the flashCount variable is increased by 1. The flashCount variable starts with a value of zero, and the condition on the while statement says to repeat the loop as long as the flashCount variable is less than 3. Thus, the loop is run three times: the first time through, flashCount is zero; the second time, flashCount is 1; the third time, flashCount is 2.

Like if statements, while loops can be nested. Listing 2-7 shows a version of the LED flasher that uses two while loops to flash the LEDs in a pattern of three times for one-tenth of a second followed by three times for one half of a second. These two while loops are nested inside a while True loop, so the pattern of three short, three long repeats indefinitely until the program is stopped.

LISTING 2-7 LED Flasher with Nested While Loops

"""Listing 2-7: Blink all eight LEDs.

This version of the program uses nested while loops to
alternate between long and short flashes.
"""

import RPi.GPIO as GPIO
import time

LED1 = 29
LED2 = 31
LED3 = 33
LED4 = 35
LED5 = 37
LED6 = 36
LED7 = 38
LED8 = 40

GPIO.setmode(GPIO.BOARD)
GPIO.setup(LED1, GPIO.OUT)
GPIO.setup(LED2, GPIO.OUT)
GPIO.setup(LED3, GPIO.OUT)
GPIO.setup(LED4, GPIO.OUT)
GPIO.setup(LED5, GPIO.OUT)
GPIO.setup(LED6, GPIO.OUT)
GPIO.setup(LED7, GPIO.OUT)
GPIO.setup(LED8, GPIO.OUT)

def setLEDs(setValue):
GPIO.output(LED1, setValue)
GPIO.output(LED2, setValue)
GPIO.output(LED3, setValue)
GPIO.output(LED4, setValue)
GPIO.output(LED5, setValue)
GPIO.output(LED6, setValue)
GPIO.output(LED7, setValue)
GPIO.output(LED8, setValue)

while True:
flashCount = 0
while flashCount < 3:
setLEDs(GPIO.HIGH)
time.sleep(.1)
setLEDs(GPIO.LOW)
time.sleep(.1)
flashCount = flashCount + 1
flashCount = 0
while flashCount < 3:
setLEDs(GPIO.HIGH)
time.sleep(0.5)
setLEDs(GPIO.LOW)
time.sleep(0.5)
flashCount = flashCount + 1

Using For Loops

Most programming languages have a for loop that is designed to loop through a series of statements while incrementing a counter variable through a given range, such as from 1 to 3.

In Python, this type of for loop looks like this:

for variable in range(count):
statements

The statements indented beneath the for loops will be executed the number of times indicated by count. For each execution of the loop, variable will be increased by one, starting with zero for the first time through the loop.

For example, consider this for statement:

for x in range(3):
print(x)

This will result in the following output in the Python Shell window:

0
1
2

The range function is actually more complex than this might lead you to believe. Range can actually take up to three arguments: start, stop, and stride.

If you use only one argument, it is taken to be the stop argument, and in practice the stop argument is a count of the number of values returned, starting with zero for the first time through the loop.

If you use two arguments, the first is the start argument and the second is the stop argument. In this case, the start argument specifies the value of the variable on the first iteration of the loop, and the stop argument is one greater than the value of the variable on the last trip through the loop.

For example, consider this for statement:

for x in range(5, 9):
print(x)

When you run this statement, the following output will be displayed:

5
6
7
8

Here, the loop runs a total of four times. The starting value is 5 and the ending value is one less than 9.

The third argument lets you count by a value other than 1. For example:

for x in range(5, 25, 5):
print(x)

The output created by this for loop is:

5
10
15
20

You can coax a for statement into counting backward by using a negative stride value. For example:

for x in range(5, 0, -1):
print(x)

This creates the following output:

5
4
3
2
1

tip Every other programming language I’ve worked in (and I’ve worked in a lot!) uses the term step instead of stride. Perhaps this is simply a tribute to Monty Python’s Ministry of Silly Walks sketch. The default value of 1 is a normal stride. Any other value could be a silly stride.

Listing 2-8 shows a version of the LED Flasher program that uses a pair of for statements to flash the LEDs three times with a short delay, and then three times with a longer delay.

LISTING 2-8 The LED Flasher Program with FOR Loops

"""Listing 2-8: Blink all eight LEDs.

This version of the program uses a for statement to
alternate between long and short flashes.
"""

import RPi.GPIO as GPIO
import time

LED1 = 29
LED2 = 31
LED3 = 33
LED4 = 35
LED5 = 37
LED6 = 36
LED7 = 38
LED8 = 40

GPIO.setmode(GPIO.BOARD)
GPIO.setup(LED1, GPIO.OUT)
GPIO.setup(LED2, GPIO.OUT)
GPIO.setup(LED3, GPIO.OUT)
GPIO.setup(LED4, GPIO.OUT)
GPIO.setup(LED5, GPIO.OUT)
GPIO.setup(LED6, GPIO.OUT)
GPIO.setup(LED7, GPIO.OUT)
GPIO.setup(LED8, GPIO.OUT)

def setLEDs(setValue):
GPIO.output(LED1, setValue)
GPIO.output(LED2, setValue)
GPIO.output(LED3, setValue)
GPIO.output(LED4, setValue)
GPIO.output(LED5, setValue)
GPIO.output(LED6, setValue)
GPIO.output(LED7, setValue)
GPIO.output(LED8, setValue)

while True:
for flashCount in range(3):
setLEDs(GPIO.HIGH)
time.sleep(0.1)
setLEDs(GPIO.LOW)
time.sleep(0.1)
for flashCount in range(3):
setLEDs(GPIO.HIGH)
time.sleep(0.5)
setLEDs(GPIO.LOW)
time.sleep(0.5)

Looking at Python Lists

The last Python feature I want to show you in this chapter is perhaps one of Python’s most interesting feature: the list feature. In Python, a list is a sequence of values that can be treated individually or as a whole. You can add any kind of data you want to a list.

Lists are commonly represented as a sequence of values separate by commas and enclosed in square brackets. For example, here is a list of string values:

names = ["Chapman", "Cleese", "Gilliam", "Idle", "Jones", "Palin"]

You can use a list in a for statement, like this:

for name in names:
print(name)

This example prints the following output:

Chapman
Cleese
Gilliam
Idle
Jones
Palin

In fact, I should point out that the range function (see the preceding section) is actually a function that simply returns a list. For example, the range(3) function returns the list [0, 1, 2]. So the following two for loops are equivalent:

for x in range(3):
print(x)

for x in [0, 1, 2]:
print(x)

You can use lists to simplify your LED flashing program by using a list to store the pin numbers of the eight GPIO ports connected to the LEDs, like this:

LEDs = [29, 31, 33, 35, 37, 36, 38, 40]

Then you can replace the eight lines of code that set the GPIO ports to output mode with a simple for loop:

for LED in LEDs:
GPIO.setup(LED, GPIO.OUT)

And you can rewrite your setLEDs function like this:

def setLEDs(setValue):
for LED in LEDs:
GPIO.output(LED, setValue)

Listing 2-9 shows a version of the LED Flasher program that uses lists to simplify the program.

LISTING 2-9 The LED Flasher Program with a List

"""Listing 2-9: Blink all eight LEDs.

This version of the program uses a list to represent the
LED pins.
"""

import RPi.GPIO as GPIO
import time

LEDs = [29, 31, 33, 35, 37, 36, 38, 40]

GPIO.setmode(GPIO.BOARD)
for LED in LEDs:
GPIO.setup(LED, GPIO.OUT)

def setLEDs(setValue):
for LED in LEDs:
GPIO.output(LED, setValue)

while True:
for flashCount in range(3):
setLEDs(GPIO.HIGH)
time.sleep(0.1)
setLEDs(GPIO.LOW)
time.sleep(0.1)
for flashCount in range(3):
setLEDs(GPIO.HIGH)
time.sleep(0.5)
setLEDs(GPIO.LOW)
time.sleep(0.5)

You can access items in a list individually by using an index number. In Python, this is called a slice, because it gives you just a slice of the entire list. For example, to access the first item in a list, slice the list using index 0:

print List1[0]

Here, the first item in a list named List1 is printed.

You can access items at the end of a list by using a negative index number. This example slices off just the last item in List1:

print List1[-1]

To access a range of items, specify the start and stop index values separated by a colon. For example, to slice the first three values in List1:

print List1[0:3]

Finally, you can specify a stride value as well. For example:

print[0:-1:2]

This example prints every other item in the list, starting with the first. Note that you can omit the start or stop indexes:

print[::2]

This example also prints every other item in the list, starting with the first. Note that if you omit a start or stop value, you must still include the colon for the omitted value.

To print the items in a list in reverse order, use images as the stride value:

print[::-1]

Listing 2-10 shows yet another version of the LED Flasher program. This one uses a slice in a for loop to flash the LEDs first in one direction, and then in the opposite direction. This creates an effect similar to the spooky electronic eyes on the evil Cylons in the old TV series Battlestar Galactica. The first for loop flashes all eight LEDs. Then the second for loop flashes the middle six LEDs in reverse order by using the following slice:

for LED in LEDs[-2:1:-1]:

This slice selects the LEDs in reverse order, starting with the second-to-last item in the LEDs list and ending with the second item.

LISTING 2-10 The Cylon LED Flasher

"""Listing 2-10: Cylon LED Flasher.

This version of the program uses a pair of for loops to
flash the LEDs one at a time, like a cylon.
"""

import RPi.GPIO as GPIO
import time

LEDs = [29, 31, 33, 35, 37, 36, 38, 40]

GPIO.setmode(GPIO.BOARD)
for LED in LEDs:
GPIO.setup(LED, GPIO.OUT)

while True:
for LED in LEDs:
GPIO.output(LED,GPIO.HIGH)
time.sleep(0.1)
GPIO.output(LED,GPIO.LOW)
for LED in LEDs[-2:1:-1]:
GPIO.output(LED,GPIO.HIGH)
time.sleep(0.1)
GPIO.output(LED,GPIO.LOW)