Introducing Python - Programming with Python - BeagleBone For Dummies (2015)

BeagleBone For Dummies (2015)

Part IV

Programming with Python

Visit www.dummies.com/cheatsheet/beaglebone for additional Dummies content on soldering your circuits.

In this part …

· Experimenting with Python, covering the basics on outputs and inputs

· Finding out about Python’s advanced functions for advanced projects

· Controlling a three-color LED, sending emails automatically, and reading from sensors and devices.

· Employing good practices for better programming

Chapter 9

Introducing Python

In This Chapter

Getting acquainted with Python

Writing your first Python script to blink an LED

Using Python to configure an input pin and test your code with a pushbutton

One of the greatest features of the BeagleBone is the fact that you can program it in several programming languages. After all, the BeagleBone is an embedded Linux system that works just like a computer, with the added perks of input and output pins.

This chapter introduces Python, a powerful programming language that features a dedicated library to interface with the BeagleBone. Python code is easy to understand, and Adafruit’s BeagleBone IO (input/output) Python Library that you use in this chapter offers a plethora of functions that enable you to control the BeagleBone’s pins in a simple and intuitive way.

This library has conventions that are very similar to the Python library dedicated to Raspberry Pi, the popular RPi.GPIO. Thus, porting projects from one platform to the other should be quite straightforward.

Throughout this chapter, we greatly advise that you use the Cloud9 integrated development environment (IDE) to write the scripts for your projects and test them. Refer to Chapter 8 for more information on how to launch and use it.

Getting Started with Python

Before you get to the fun stuff, you need to be sure that your BeagleBone is set up properly. Installing the operating system is covered in Chapter 2; if you have not already worked through that chapter, go through it now to make sure your BeagleBone is ready to use Python to access its input and output pins.

This section shows you how you can verify whether Python is indeed ready to be used and how to make it ready if it isn’t properly set up.

Making sure your libraries are up to date

Before proceeding, you should update and upgrade your software just to make sure you have the latest versions. Use the following command:

sudo apt-get update && sudo apt-get upgrade

You can test the installation of Adafruit’s BeagleBone Input/Output (BBIO) library for Python by executing the following command:

sudo python -c "import Adafruit_BBIO.GPIO as GPIO; print GPIO"

If everything is working correctly, your console window should print the following line:

<module 'Adafruit_BBIO.GPIO' from '/usr/local/lib/python2.7/dist-packages/Adafruit_BBIO/GPIO.so'>

If so, you can skip the next section.


Comparing Python and BoneScript

If you read Chapters 8 and 9, you should feel relatively comfortable with programming in BoneScript. In many ways, Python and BoneScript are similar. In both languages, you use variables, as well as if and while statements, and you also control the BeagleBone’s pins by changing the values of an object. But you need to be aware of some key differences:

· The flow of code is different. Python’s interpreter runs each line sequentially. Two programs, one in BoneScript and another in Python, that do the same thing may end up being quite different To verify that difference, compare the section "Blinking an LED with Python" in this chapter with the "Blinking an onboard LED with BoneScript" section in Chapter 8.

· Indentation is not just organization. Although you should indent your code as much as possible when you program in BoneScript, indentation is merely a tool — albeit a powerful one — to keep your program organized. In fact, you could write an entire program in a single line of code. In Python, however, indentations tell the interpreter which parts of the code are inside statements such as if and for.


Installing the libraries

If executing the command in the preceding section results in errors, you need to install the libraries manually. Type the following command:

sudo apt-get install build-essential python-dev python-setuptools python-pip python-smbus -y

Things are always subject to change, and future versions of the Linux kernel may require different libraries, which could make this whole process different. You can bookmark the following link as a reference: https://learn.adafruit.com/setting-up-io-python-library-on-beaglebone-black/installation-on-ubuntu. Even though the title mentions Ubuntu, installation in Debian is pretty much the same.

Blinking an LED with Python

Often, it’s said that blinking an LED is the foundation of digital electronics. Doing it isn’t perceived as simply lighting up a tiny lamp; it’s perceived as controlling an output. The gap from blinking an LED to controlling the motors of a quadcopter isn’t a big one. Thus, this project helps you get acquainted with Python and Adafruit’s BeagleBone IO Library.

Wiring the circuit for an LED

Always make sure that your BeagleBone is disconnected from power before you start wiring!

Follow these instructions to wire your circuit as shown in Figure 9-1:

1. Connect the BeagleBone’s ground (GND) — pins 1 and 2 on both headers — to the negative track of the breadboard.

2. Use a jumper to connect P9_14 to a vertical row on your breadboard.

This pin is the one you’ll be using as an output.

3. Connect a 220 Ω or 470 Ω resistor to the jumper you pulled from P9_14.

This step should ensure that your LED doesn’t burn up without reducing its brightness. If the LED is too dim, use a 220 Ω resistor rather than a 470 Ω resistor.

4. Connect the negative leg of the LED (the cathode, which is usually the shorter leg) to ground and the positive leg (the anode, usually the longer leg) to the resistor.

Figure 9-1: Pin P9_14 attached to an LED and a resistor.

Writing the code for an LED

Python scripts end with the extension .py, so start by creating a file named blink.py and type the following code:

#!/usr/bin/python

"""
Blink
Turns an onboard LED on and off continuously,
with intervals of 1 second.
"""

#import libraries
import Adafruit_BBIO.GPIO as GPIO
import time

#create a variable called led, which refers to the P9_14 pin
led = "P9_14"

#initialize the pin as an OUTPUT
GPIO.setup(led, GPIO.OUT)

#loop forever
while True:
GPIO.output(led, GPIO.HIGH) #set P9_14 high - turn it on
time.sleep(1) #stay idle for 1 second
GPIO.output(led, GPIO.LOW) #set P9_14 low - turn it off
time.sleep(1) #stay idle for 1 second

This script can be divided into several parts, which the following sections cover in detail:

· Using a shebang

· Commenting

· Importing libraries

· Creating a variable

· Configuring pins

· Using a loop

· Setting the pin state

Using a shebang

A shebang is a character sequence starting with the number sign and an exclamation mark (#!). It’s not explicitly necessary, but including it on Python scripts is often a good thing to do, so the blink.py file starts with the following line:

#!/usr/bin/python

We suggest that you use Cloud9 IDE to program the BeagleBone, but you can also run scripts from the command line. To run a Python script, you have to type the following command:

python script_name.py

However, if you include a shebang in your code, you only have to type:

./script_name.py

Commenting

Comments are notes that you can write in your script file that don’t belong to the code. You include them to help you with organization. The blink.py file includes the following comments:

"""
Blink
Turns an onboard LED on and off continuously,
with intervals of 1 second.
"""

#import libraries

Python has two types of comments:

· Single-line: A cardinal sign (#) indicates a comment, and the script ignores everything after it until the end of line.

· Multiple-line: Any text between two sets of triple quotation marks (""") is ignored, which allows you to use them to create comments that span multiple lines.

Importing libraries

To use the Adafruit library that’s installed on your BeagleBone, you have to import it. This library allows you to control the pins of your board in a simple and intuitive way by defining an object. For this example, we call the object GPIO, but you can call it whatever you want. The following line of code imports that library:

import Adafruit_BBIO.GPIO as GPIO

You can also use Adafruit’s library to use pins for uses other than GPIO (general purpose input/output), such as PWM (pulse-width modulation) and analog inputs, in which case you’d import it as

import Adafruit_BBIO.PWM as <object_name>

or

import Adafruit_BBIO.ADC as <object name>

The time library is a useful library that, as its name implies, provides functions that deal with time. In this project, you use it so you can use the sleep function, which halts the program for a set amount of seconds. This is how you import it:

import time

Creating a variable

Whenever you want to save a value in a variable, simply write the variable’s name and make it equal to the value you want to save. In this example, you save the string "P9_14" in the led variable:

#create a variable called led, which refers to the onboard P9_14 LED
led = "P9_14"

Configuring pins

In this section, you need to define the pin’s job. In this case, you want to control an LED, so you define it as an output:

#initialize the LED as an OUTPUT
GPIO.setup(led, GPIO.OUT)

For GPIO, the setup function has always two parameters in the following syntax:

setup(GPIO, mode)

The two parameters are:

· GPIO: The pin you want to control — in this case, P9_14, defined in the led variable

· mode: OUT or IN, depending on whether you want to use the pin as an output or input, respectively

The functions that control the pins of the BeagleBone must always be used with the object you defined preceding them!

Using a loop

The while loop can be used as follows:

while condition:
<indented code>

When you use a while loop, the code that’s indented below it repeats itself as long as the while condition is met — in other words, as long as the condition evaluates as True. A condition can be anything. A system controlling a parking lot’s gate could be coded like so:

while number_of_cars == maximum:
keep_gate_closed()

In the preceding example, assume that number_of_cars is a variable that changes according to the current number of cars inside the parking lot. maximum is a variable that has a fixed value containing the number of parking spots. keep_gate_closed() is a function that does exactly what its name suggests. The chapters in the remainder of this book use variables and functions such as these whose names intuitively suggest their tasks.

The while loop in this example continues forever because the condition is defined to be always evaluated as True:

while True:
GPIO.output(led, GPIO.HIGH) #set P9_14 high - turn it on
time.sleep(1) #stay idle for 1 second
GPIO.output(led, GPIO.LOW) #set P9_14 low - turn it off
time.sleep(1) #stay idle for 1 second

In most programming languages, such as BoneScript, indentation is a great way to make sure that your code is well organized and tidy, but your program still works even if you don’t indent any lines of code. In Python, however, your program doesn’t work correctly if you don’t get the indentation right. For statements such as while, the Python interpreter knows what part of the code is included in the statement only by checking the indentation. You can use one or more spaces and tabs, but make sure to maintain consistency throughout the code.

Contrary to JavaScript — and, thus, to BoneScript — Python’s code is evaluated from the top of the script in a sequential fashion, one line at a time. That’s the reason why a thing such as a loop can exist in this programming language. When the Python interpreter reaches the while statement, it knows that the lines indented below it have to run for as long as the condition holds True.

Setting the pin state

You use the output() function to define whether a pin is HIGH or LOW. This function is defined as follows:

output(GPIO, state)

This function has two parameters:

· GPIO: The pin you want to control — in this case, P9_14, defined in the led variable

· state: HIGH or LOW, depending on the state you want the pin to have

In this case, you set the pin’s state to HIGH for 1 second and then to LOW for 1 second, and repeat this process indefinitely. You achieve this process by using the time.sleep(seconds) function, which halts the problem for the defined number of seconds (1 second in this case):

GPIO.output(led, GPIO.HIGH) #set P9_14 high - turn it on
time.sleep(1) #stay idle for 1 second
GPIO.output(led, GPIO.LOW) #set P9_14 low - turn it off
time.sleep(1) #stay idle for 1 second

Running the script for blinking an LED

To see the project working, simply save the script by pressing Ctrl+S or Cmd+S and then click the green Run button. To terminate the program, click Stop or press Ctrl+C.

You should see your LED blinking, such as the one shown in Figure 9-2.

Figure 9-2: Circuit that blinks an LED controlled by Python code.

Reading a Pushbutton with Python

Digital inputs are just as important as digital outputs. Buttons and sensors that control the outputs of a circuit are the basis of some really great projects.

Wiring the circuit for a pushbutton

Always make sure that your BeagleBone is disconnected from power before you start wiring!

To wire a pushbutton to a BeagleBone, follow these steps:

1. Connect the BeagleBone’s (GND) — pins 1 and 2 on both headers — to the negative track of the breadboard.

2. Use a jumper to connect P8_11 to a vertical row on your breadboard.

This pin is the one you’ll be using as an input.

3. Connect the BeagleBone’s 3.3V source — P9_3 or P9_4 — to the breadboard’s positive track.

If you are powering your BeagleBone through an external source, the P_5 and P_6 pins of the BeagleBone supply a 5-volt (V) source; if you are powering it through an USB cable, the pins providing 5 V are P9_7 and P9_8. Regardless, you should avoid using any of those four pins as a small mistake might permanently damage your BeagleBone.

4. Connect the pushbutton.

Place the pushbutton at the center of the board to ensure that each pair of legs is electrically separated. Through the use of jumpers, connect one of its legs to the positive rail of the breadboard and the other leg to the jumper that comes from P8_11.

5. Connect a pull-down resistor between the other leg of the pushbutton and the negative track of the breadboard.

Your circuit should look similar to Figure 9-3.

Writing the code and running the script for a pushbutton

After wiring the circuit, create a file named button.py and type the following code:

#!/usr/bin/python

#import libraries
import Adafruit_BBIO.GPIO as GPIO
import time

button = "P8_11" create a variable called button, which refers to the P8_11 pin

#initialize the pin as an INPUT
GPIO.setup(button, GPIO.IN) # Initialize P8_11 as an input

#loop forever
while True:
if GPIO.input(button) == True: # Checks if the pin is HIGH
print("HIGH")
time.sleep(0.01) # In order to not overburden the CPU

Figure 9-3: Pushbutton connected to BeagleBone’s input pin P8_11.

The terms HIGH and LOW, True and False, and 1 and 0 always refer to the same thing, but their use depends on the context.

This code uses concepts from the “Writing the code for an LED” section. It involves two new concepts, however: the if statement and the print() function. The print() function is quite simple and intuitive; the message that makes up its argument is printed on the console. The if statement should be read as follows: “If this condition is met, run the indented code below the statement.”

Additionally, you use GPIO.input(GPIO), which is a variable that holds the value of the pin — HIGH for when the button is pressed, and LOW for when it isn’t.

Test your circuit by clicking Run and then pressing the pushbutton a few times. Whenever you press it, the message HIGH should be printed on the console, most likely more than once. It prints several times because the script works as follows: In every cycle of the while loop, the script checks whether pin P8_11 is HIGH. If it is, the message prints. Because every cycle of this loop executes extremely fast, the program always reads the value HIGH from P8_11 and prints it several times in less than a second. Even if you’re really quick with pressing the button, in reality you are actually very slow from the BeagleBone’s point of view, so the board always equates one fast press of the pushbutton as the pushbutton being held down for a while.

This kind of thing can be troublesome. Imagine if your mouse registered multiple clicks when you clicked it only once! Thus, buttons are often used with interrupts. Rather than checking whether the pin is HIGH or LOW, the code checks whether the pin just went from HIGH to LOW (a falling edge) or from LOW to HIGH (a rising edge). Pressing a button generates a rising edge, whereas releasing it generates a falling edge. Those things happen only once per button press or release.

Writing the code with interrupts

To check for rising and falling edges rather than whether the input pin is HIGH or LOW, the Adafruit library offers the function wait_for_edge(pin, desired edge). When the program reaches that line of the code, the program blocks until the interrupt happens. It is used as follows:

wait_for_edge(GPIO, mode)

That function takes these parameters:

· GPIO: The first parameter is the input pin you want to check for a rising or falling edge.

· mode: The second parameter is RISING or FALLING, depending on whether you want to check for a rising or falling edge.

Test your circuit with the following code, and you see that HIGH and LOW should be printed only once per button press or release:

#!/usr/bin/python

#import libraries
import Adafruit_BBIO.GPIO as GPIO
import time

button = "P8_11" create a variable called button, which refers to the P8_11 pin

#initialize the pin as an INPUT
GPIO.setup(button, GPIO.IN)

#loop forever
while True:
GPIO.wait_for_edge(button, GPIO.RISING) #blocks the program until a rising edge happens on pin P8_11.
print("HIGH")
GPIO.wait_for_edge(button, GPIO.FALLING) #blocks the program until a falling edge happens on pin P8_11.
print("LOW")

Introducing if … else and if … elif statements

if … else statements, along with loops, are among the most important coding tools for adding control to your program. if… else statements are used as follows

if condition:
do_something()
else
do_something_else()

Their use is just as the words describe them: If a certain condition is met, the indented code below the if runs. Otherwise, the indented code below the else is in the spotlight. If you use only an if, as in the code for the pushbutton, the code after the if runs normally if the pushbutton is pressed. If the pushbutton isn’t pressed, the interpreter just skips that part in the code.

With an if, you can also use the elif statement, which can be read as else if:

if condition1:
do_something()
elif condition2:
do_something_else()
else:
do_another_something_else()

In these situations, the code below the else is often the default possibility; if and elif statements are about particular situations.

You can use an if statement alone, with an elif, with an else, or with both. else and elif, on the other hand, make no sense without a preceding if, and such code would result in an error.

To illustrate the use of an if … elif statement, you use a button circuit and interrupts, but these interrupts happen in a slightly different way. Rather than using the wait_for_edge function, you use two other functions:

· add_event_detect(GPIO, event) defines an event that you want to detect — in this case, a falling or rising edge.

· event_detected(GPIO) is a method that returns True whenever the defined event happens.

To test if…elif and these new functions, you can use the following code:

#!/usr/bin/python

#import libraries
import Adafruit_BBIO.GPIO as GPIO
import time

button = "P8_11" # create a variable called button, which refers to the P8_11 pin
count = 0 # create a variable called count and initialize it with the value zero.
# This variable will count the number of times the button was pressed.

GPIO.setup(button, GPIO.IN) #initialize the pin as an INPUT
GPIO.add_event_detect(button, GPIO.RISING) #adds an event to detect. In this case, the rising edge of pin P8_11.

#loop forever
while True:
if GPIO.event_detected(button) == True: # if a rising edge is detected, run the code below
if count == 0: # if the value of count is zero, run the code below
print("Button was pressed once!")
count = count + 1 #increment count
elif count < 3:
print("Button was pressed less than three times but more than once!")
count = count + 1 #increment count
elif count == 3:
print("Button was pressed three times!")
count = count + 1 #increment count
else:
print("Button was pressed more than three times!")

time.sleep(0.01) # in order to not overburden the CPU

Unlike the example in the “Writing the code with interrupts” section, in which wait_for_edge is used and the program is blocked at that line of code until a pushbutton press occurs, adding an event to detect is a nonblocking technique, which means that your program doesn’t block waiting for the pushbutton to be pressed. You can verify by placing a line of code such as print(“test”) at the end of both programs. In the wait_for_edge case, test is printed only after the pushbutton is pressed and then released, because the interpreter doesn’t get to that line of code before the wait_for_edge functions unblock. In the event_detected case, your screen is filled with the test message, because the program still keeps running despite the pushbutton press, which is why this option is called a nonblocking option.

Getting to know the print function

You can use the print() function to print the actual value of a variable. We simply wrote the code in the preceding section in a different way to illustrate the use of the if, elif, and else statements. In fact, print() is used as follows:

print(argument1 + argument2 + argument3 + ...)

So far, you’ve used this function only with strings you place inside it — indicated by the quotation marks — but you can command it to print variables as well. To print both strings and variables that are numbers in the same print command, you have to convert the numbers to a string first. Don’t worry! You can do that simply by typing str(variable). You can verify by testing the following code:

#!/usr/bin/python

#import libraries
import Adafruit_BBIO.GPIO as GPIO
import time

button = "P8_11" # create a variable called button, which refers to the P8_11 pin
count = 0 # create a variable called count and initialize it with the value zero.
# This variable will count the number of times the button was pressed.

GPIO.setup(button, GPIO.IN) #initialize the pin as an INPUT
GPIO.add_event_detect(button, GPIO.RISING) #adds an event to detect. In this case, the rising edge of pin P8_11.

#loop forever
while True:
if GPIO.event_detected(button) == True: # if a rising edge is detected, run the code below
count = count + 1 #increment the variable count
print("Button was pressed " + str(count) + " times!")

time.sleep(0.01) # in order to not overburden the CPU

The print() function is very useful for receiving feedback from your project, as well as for debugging it.


More on Python

Chapter 11 explores Python’s capabilities further with some interesting projects. Still, there’s a lot more to this programming language than this book covers. The Internet features a vast number of free tutorials at pages such as http://learnpython.org. You can also check out Python For Dummies, by Stef Maruch and Aahz Maruch (John Wiley & Sons, Inc.).