Although the Raspberry Pi can use a monitor or TV as a display, it is often nice to use a smaller, more specialized display with it. In this chapter, we explore a range of different displays that can be attached to a Raspberry Pi.
Some of the recipes require the use of a solderless breadboard and male-to-female jumper wires (see Recipe 9.8).
Be sure to check out the accompanying video for this recipe at http://razzpisampler.oreilly.com.
You want to display a four-digit number in an old-fashioned, seven-segment LED display.
Attach an Inter-Integrated Circuit (I2C) LED module, such as the model shown in Figure 14-1, to a Raspberry Pi using female-to-female jumper wires.
To make this recipe, you will need the following:
Four female-to-female jumper wires (see “Prototyping Equipment and Kits”)
Adafruit 4×7-segment LED with I2C backpack (see “Modules”)
The connections between the Raspberry Pi and the module are as follows:
VCC (+) on the display to 5V on the Raspberry Pi general-purpose input/output (GPIO) connector
GND (-) on the display to GND on the Raspberry Pi GPIO connector
SDA (D) on the display to GPIO 2 (SDA) on the Raspberry Pi GPIO connector
SCL (C) on the display to GPIO 3 (SCL) on the Raspberry Pi GPIO connector
Note that Adafruit also supplies a jumbo-sized LED display. You can connect this to the Raspberry Pi using the just-listed connections, but the larger display has two positive power pins: one for the logic (V_IO) and one for the display (5V). This is because, being a large display, it requires more current. Fortunately, the Raspberry Pi can supply enough power for it. You can use an extra female-to-female jumper wire to connect this extra pin to the second 5V pin on the GPIO connector.
For this recipe to work, you will also need to set up your Raspberry Pi for I2C, so follow Recipe 9.3 first.
Enter these commands to install the Adafruit code to support this display:
$ cd /home/pi $ git clone https://github.com/adafruit/Adafruit_Python_LED_Backpack.git $ cd Adafruit_Python_LED_Backpack $ sudo python setup.py install
The Adafruit library includes examples, and it’s one of these that we will use to illustrate the use of the display. Run the program using the command below and the display should show the time. Note that this code is Python 2 only, so use the python
(not python3
) command:
$ cd examples $ sudo python ex_7segment_clock.py
If you open the example file ex_7segment_clock.py in an editor, you’ll see that the key commands are the following:
from
Adafruit_LED_Backpack
import
SevenSegment
This imports the library code into your program. You then need to create a instance of SevenSegment
using the next line of code. The address supplied as an argument is the I2C address (see Recipe 9.4).
Every I2C slave device has an address number. The LED board has three pairs of solder pads on the back that can be bridged with solder if you want to change the address. This is essential if you need to operate more than one I2C device from a single Raspberry Pi. This is why we specify an address of 0x70 in the following line:
segment
=
SevenSegment
.
SevenSegment
(
address
=
0x70
)
To actually set the contents of a particular digit, use a line like this one:
segment
.
set_digit
(
0
,
int
(
hour
/
10
))
The first argument (0
) is the digit position. Note that these positions are 0, 1, 3, and 4. Position 2 is reserved for the two dots in the center of the display.
Find out more about the Adafruit library.
Recipe 14.2 uses the same Adafruit software for a matrix display.
Use an I2C LED module, such as the model shown in Figure 14-2, attached to a Raspberry Pi using female-to-female jumper wires.
To make this recipe, you will need the following:
Four female-to-female jumper wires (see “Prototyping Equipment and Kits”)
Adafruit bicolor LED square-pixel matrix with I2C backpack (see “Modules”)
The connections between the Raspberry Pi and the module are as follows:
VCC (+) on the display to 5V on the Raspberry Pi GPIO connector
GND (-) on the display to GND on the Raspberry Pi GPIO connector
SDA (D) on the display to GPIO 2 (SDA) on the Raspberry Pi GPIO connector
SCL (C) on the display to GPIO 3 (SCL) on the Raspberry Pi GPIO connector
For this recipe to work, you will also need to set up your Raspberry Pi for I2C, so follow Recipe 9.3 first.
The display uses the same library as Recipe 14.1. To install it, run the following commands:
$ cd /home/pi $ git clone https://github.com/adafruit/Adafruit_Python_LED_Backpack.git $ cd Adafruit_Python_LED_Backpack $ sudo python setup.py install
Run the example program using:
$ cd examples $ sudo python bicolor_matrix8x8_test.py
The program demonstrates the versatility of the Adafruit library. It starts by iterating through all of the colors for each pixel in turn. The first part of the code is listed here, with some of the comments removed:
import
time
from
PIL
import
Image
from
PIL
import
ImageDraw
from
Adafruit_LED_Backpack
import
BicolorMatrix8x8
display
=
BicolorMatrix8x8
.
BicolorMatrix8x8
()
for
c
in
[
BicolorMatrix8x8
.
RED
,
BicolorMatrix8x8
.
GREEN
,
BicolorMatrix8x8
.
YELLOW
]:
# Iterate through all positions x and y.
for
x
in
range
(
8
):
for
y
in
range
(
8
):
# Clear the display buffer.
display
.
clear
()
# Set pixel at position i, j to appropriate color.
display
.
set_pixel
(
x
,
y
,
c
)
# Write the display buffer to the hardware. This must be called to
# update the actual display LEDs.
display
.
write_display
()
# Delay for a quarter second.
time
.
sleep
(
0.25
)
The code is well explained in its accompanying comments.
You can find out more about this product at http://www.adafruit.com/products/902.
Follow Recipe 9.16 and install the software that the Sense HAT needs and then use the library commands to display text.
The program ch_14_sense_hat_clock.py illustrates this by repeatedly displaying the date and time in a scrolling message:
from
sense_hat
import
SenseHat
from
datetime
import
datetime
import
time
hat
=
SenseHat
()
time_color
=
(
0
,
255
,
0
)
# green
date_color
=
(
255
,
0
,
0
)
# red
while
True
:
now
=
datetime
.
now
()
date_message
=
'{:
%d
%B
%Y
}'
.
format
(
now
)
time_message
=
'{:
%H
:
%M
:
%S
}'
.
format
(
now
)
hat
.
show_message
(
date_message
,
text_colour
=
date_color
)
hat
.
show_message
(
time_message
,
text_colour
=
time_color
)
As with all the program examples in this book, you can also download this program (see Recipe 3.22).
Two colors are defined so that the date and time parts of the message can be displayed in different colors. These colors are then used as an optional parameter to show_message
.
Other optional parameters to show_message
are:
scroll_speed
back_colour
You can use the display for a lot more than just displaying scrolling text. Starting at its most basic, you can set individual pixels using set_pixel
, set the orientation of the display using set_rotation
, and display an image (albeit a small one) with load_image
. The example that follows, which you can find in ch_13_sense_hat_taster.py, illustrates these function calls. As with all the program examples in this book, you can download them (see Recipe 3.22).
The image must be just 8×8 pixels, but you can use most common graphics formats, such as .jpg and .png, and the bit depth will be handled automatically:
from
sense_hat
import
SenseHat
import
time
hat
=
SenseHat
()
red
=
(
255
,
0
,
0
)
hat
.
load_image
(
'small_image.png'
)
time
.
sleep
(
1
)
hat
.
set_rotation
(
90
)
time
.
sleep
(
1
)
hat
.
set_rotation
(
180
)
time
.
sleep
(
1
)
hat
.
set_rotation
(
270
)
time
.
sleep
(
1
)
hat
.
clear
()
hat
.
set_rotation
(
0
)
for
xy
in
range
(
0
,
8
):
hat
.
set_pixel
(
xy
,
xy
,
red
)
hat
.
set_pixel
(
xy
,
7
-
xy
,
red
)
Figure 14-3 shows the Sense HAT displaying a crude image.
For full documentation on the Sense HAT, see https://pythonhosted.org/sense-hat/api/.
For information on formatting dates and times, see Recipe 7.2.
Other recipes that use the Sense HAT are Recipes 9.16, 13.11, 13.14, 13.15, and 13.17.
Use a Pimoroni Displayotron HAT attached to your Raspberry Pi, as shown in Figure 14-4.
This HAT requires both I2C and SPI to be enabled, so if you have not already done so, follow Recipe 9.3 and Recipe 9.5.
Then fetch the code for its accompanying library from GitHub and install it by using the following commands:
$ curl -sS get.pimoroni.com/displayotron | bash
This command will ask you if want to install the examples and documentation. Be warned: the whole thing takes quite some time to install.
By way of example, the following program (ch_14_displayotron_ip.py) finds the hostname and IP address of your Raspberry Pi and displays them, along with the time. If all is well, the backlit LED will be green, but if the network connection is down, the backlight will turn red:
import
dothat.lcd
as
lcd
import
dothat.backlight
as
backlight
import
time
from
datetime
import
datetime
import
subprocess
while
True
:
lcd
.
clear
()
backlight
.
rgb
(
0
,
255
,
0
)
try
:
hostname
=
subprocess
.
check_output
([
'hostname'
])
.
split
()[
0
]
ip
=
subprocess
.
check_output
([
'hostname'
,
'-I'
])
.
split
()[
0
]
t
=
'{:
%H
:
%M
:
%S
}'
.
format
(
datetime
.
now
())
lcd
.
write
(
hostname
)
lcd
.
set_cursor_position
(
0
,
1
)
lcd
.
write
(
ip
)
lcd
.
set_cursor_position
(
0
,
2
)
lcd
.
write
(
t
)
except
:
backlight
.
rgb
(
255
,
0
,
0
)
time
.
sleep
(
1
)
As with all the program examples in this book, you can also download this program (see Recipe 3.22).
The test program imports the necessary libraries, including subprocesses (see Recipe 7.15), which will be used to find the IP address (see Recipe 2.2) of the Raspberry Pi and its hostname.
Here are the main methods in the library:
lcd.clear
lcd.set_cursor_position
lcd.write
backlight.rgb
You can find the examples that are supplied by Pimoroni in two subdirectories, basic and advanced, within the directory /home/pi/Pimoroni/displayotron/examples/dothat.
You can find out more about this HAT on Pimoroni’s product page.
Use an OLED display based on the SSD1306 driver chip, using an I2C interface (Figure 14-5).
To make this recipe, you will need the following:
Four female-to-female jumper wires (see “Prototyping Equipment and Kits”)
I2C OLED display 128×64 pixels (see “Modules”)
The connections between the Raspberry Pi and the module are as follows:
VCC on the display to 5V on the Raspberry Pi GPIO connector
GND on the display to GND on the Raspberry Pi GPIO connector
SDA on the display to GPIO 2 (SDA) on the Raspberry Pi GPIO connector
SCL on the display to GPIO 3 (SCL) on the Raspberry Pi GPIO connector
For this recipe to work, you will also need to set up your Raspberry Pi for I2C, so follow Recipe 9.3 first.
Adafruit has a library for these displays, which you can install by using these commands:
$ git clone https://github.com/adafruit/Adafruit_Python_SSD1306.git $ cd Adafruit_Python_SSD1306 $ sudo python3 setup.py install
This library uses the Python Image Library (PIL), which you can install by using the following command:
$ sudo pip3 install pillow
The code example ch_14_oled_clock.py displays the time and date on the OLED display:
import
Adafruit_SSD1306
from
PIL
import
Image
,
ImageDraw
,
ImageFont
import
time
from
datetime
import
datetime
# Set up display
disp
=
Adafruit_SSD1306
.
SSD1306_128_64
(
rst
=
None
,
i2c_address
=
0x3C
)
small_font
=
ImageFont
.
truetype
(
'FreeSans.ttf'
,
12
)
large_font
=
ImageFont
.
truetype
(
'FreeSans.ttf'
,
33
)
disp
.
begin
()
disp
.
clear
()
disp
.
display
()
# Make an image to draw on in 1-bit color.
width
=
disp
.
width
height
=
disp
.
height
image
=
Image
.
new
(
'1'
,
(
width
,
height
))
draw
=
ImageDraw
.
Draw
(
image
)
# Display a message on 3 lines, first line big font
def
display_message
(
top_line
,
line_2
):
draw
.
rectangle
((
0
,
0
,
width
,
height
),
outline
=
0
,
fill
=
0
)
draw
.
text
((
0
,
0
),
top_line
,
font
=
large_font
,
fill
=
255
)
draw
.
text
((
0
,
50
),
line_2
,
font
=
small_font
,
fill
=
255
)
disp
.
image
(
image
)
disp
.
display
()
while
True
:
now
=
datetime
.
now
()
date_message
=
'{:
%d
%B
%Y
}'
.
format
(
now
)
time_message
=
'{:
%H
:
%M
:
%S
}'
.
format
(
now
)
display_message
(
time_message
,
date_message
)
time
.
sleep
(
0.1
)
As with all the program examples in this book, you can also download this program (see Recipe 3.22).
Every I2C slave device has an address, which is set in the line:
disp
=
Adafruit_SSD1306
.
SSD1306_128_64
(
rst
=
None
,
i2c_address
=
0x3C
)
This is fixed at 3C (hex) for many of the low-cost I2C modules but may vary, so you should check any documentation that comes with the device or use I2C tools (Recipe 9.4) to list all the I2C devices attached to the bus so that you can see the address of your display.
The preceding code example uses a technique called double buffering. This involves preparing what is to be displayed and then switching it onto the image in one go. This prevents the display from flickering.
You can see the code for this in the display_message
function. This first draws onto the image a blank rectangle the entire size of the display. It then draws the text onto the image
and then sets the display content to be image
using disp.image(image)
. The display isn’t actually updated until the function disp.display()
is called.
To be able to use text of different sizes, a TrueType font is used. This font is already on the Raspberry Pi, but to be able to use it, you need to copy it into the current directory using the following command:
$ cp /usr/share/fonts/truetype/freefont/FreeSansBold.ttf
Small OLED displays are cheap, don’t use much current, and have high resolution despite their diminutive size. They are replacing LCD displays in many consumer products.
The instructions here are for four-pin I2C interfaces. If you really want to use the SPI interface, take a look at Adafruit’s tutorial on this.
Use an LED strip based on the WS2812 RGB LED chips on your Raspberry Pi.
Using these LED strips (Figure 14-6) can be really easy, with a direct connection to the Raspberry Pi and power for the LEDs supplied by the Raspberry Pi’s 5V supply. This is the “Happy Day” scenario that should work just fine, but do see the Discussion for providing external power so that your LED strip use is trouble free.
Although it might be tempting to power the LEDs from the 3.3V supply pin on the GPIO connector, do not do this—it can supply only low currents (see Recipe 9.2). Using this pin could easily damage your Raspberry Pi.
The LED strip used in Figure 14-6 is cut from a reel. In this case, there are 10 LEDs. Because each LED can use up to 60mA, 10 is probably a sensible limit for the number of LEDs that can be used without arranging for a separate power supply for the LED strip (see the Discussion section).
To connect the strip to the Raspberry Pi, jumper wires with female connectors on one end were cut and the wire ends soldered to the three connections on the LED strip (see Recipe 9.2): GND, DI (Data In), and 5V. These can then be attached to GPIO pins GND, GPIO 18, and 5V, respectively.
Notice that the LED strip has a right-facing arrow printed on it (Figure 14-7). Make sure that when you solder leads to the LED strip, you start from the cut end to the left of the arrow.
We are going to use the Adafruit software to control our addressable LEDs. To install it, run the following commands:
$ pip3 install adafruit-blinka $ sudo pip3 install rpi_ws281x adafruit-circuitpython-neopixel
The following example program (ch_14_neopixel.py) will set the LED red in successive positions along the strip:
As with all the program examples in this book, you can also download this program (see Recipe 3.22).import
time
import
board
from
neopixel
import
NeoPixel
led_count
=
5
red
=
(
100
,
0
,
0
)
no_color
=
(
0
,
0
,
0
)
strip
=
NeoPixel
(
board
.
D18
,
led_count
,
auto_write
=
False
)
def
clear
():
for
i
in
range
(
0
,
led_count
):
strip
[
i
]
=
no_color
strip
.
show
()
i
=
0
while
True
:
clear
()
strip
[
i
]
=
red
strip
.
show
()
time
.
sleep
(
1
)
i
+=
1
if
i
>=
led_count
:
i
=
0
Run the program with Python 3 and use the sudo
command like this:
$ sudo python3 ch_14_neopixel.py
If you have a different number of LEDs in your strip, modify led_count
. The rest of the constants do not need to be changed.
You can use only GPIOs 10, 12, 18, and 21 with NeoPixels. If you want to use a different GPIO pin, change board.D18
to whichever pin you are using.
You can set the color of each of the LEDs independently. The colors are set as a tuple of red, green, and blue intensities. The changes to the LED colors are not actually updated until the method show
is called.
Each LED in the strip can use a maximum of about 60mA. They will do this only if all three color channels (red, green, and blue) are at maximum brightness (255). If you plan to use a lot of LEDs, you will need to use a separate 5V power supply sufficient to supply all the LEDs in your strip. Figure 14-8 shows how you would wire up a separate power supply. A female direct current (DC) jack-to-screw terminal adapter (see “Prototyping Equipment and Kits”) makes it easy to connect an external power supply to a breadboard.
NeoPixels are also available in ring format, such as this display: https://www.adafruit.com/product/1586.
You can read more about the Adafruit approach to NeoPixels here.
Use a Pimoroni Unicorn HAT to provide an 8x8 LED matrix (Figure 14-9).
Start by installing the Unicorn HAT software from Pimoroni:
$ curl https://get.pimoroni.com/unicornhat | bash
You will be asked several times to confirm various bits of software to install and finally to reboot your Raspberry Pi.
When you’ve completed the installation, here’s a colorful program (ch_14_unicorn.py) to run on it. It will repeatedly set the color of a random pixel to a random color. Run the program using the sudo
command:
import
time
import
unicornhat
as
unicorn
from
random
import
randint
unicorn
.
set_layout
(
unicorn
.
AUTO
)
unicorn
.
rotation
(
0
)
unicorn
.
brightness
(
1
)
width
,
height
=
unicorn
.
get_shape
()
while
True
:
x
=
randint
(
0
,
width
)
y
=
randint
(
0
,
height
)
r
,
g
,
b
=
(
randint
(
0
,
255
),
randint
(
0
,
255
),
randint
(
0
,
255
))
unicorn
.
set_pixel
(
x
,
y
,
r
,
g
,
b
)
unicorn
.
show
()
time
.
sleep
(
0.01
)
time
.
sleep
(
1
)
As with all the program examples in this book, you can also download this program (see Recipe 3.22).
The Unicorn HAT makes a very convenient way to attach a matrix of addressable LEDs. You will also find other chains of addressable LEDs laid out in various configurations, including matrices with even more LEDs on them. Generally, such matrices of addressable LEDs are actually arranged electrically as a long chain of LEDs.
For more information on addressable (NeoPixel) LEDs, see Recipe 14.6.
Attach an Inky pHAT or Inky wHAT module to your Raspberry Pi (Figure 14-10). Download the Pimoroni software for this using the command:
$ curl https://get.pimoroni.com/inky | bash
If (when prompted) you accept the option to fetch examples and documentation, this will take quite some time to install.
As an example program (ch_14_phat.py), let’s have the Inky pHAT display the Raspberry Pi’s IP address:
from
inky
import
InkyPHAT
from
PIL
import
Image
,
ImageFont
,
ImageDraw
from
font_fredoka_one
import
FredokaOne
import
subprocess
inky_display
=
InkyPHAT
(
"red"
)
inky_display
.
set_border
(
inky_display
.
WHITE
)
img
=
Image
.
new
(
"P"
,
(
inky_display
.
WIDTH
,
inky_display
.
HEIGHT
))
draw
=
ImageDraw
.
Draw
(
img
)
font
=
ImageFont
.
truetype
(
FredokaOne
,
22
)
message
=
str
(
subprocess
.
check_output
([
'hostname'
,
'-I'
]))
.
split
()[
0
][
2
:]
(
message
)
w
,
h
=
font
.
getsize
(
message
)
x
=
(
inky_display
.
WIDTH
/
2
)
-
(
w
/
2
)
y
=
(
inky_display
.
HEIGHT
/
2
)
-
(
h
/
2
)
draw
.
text
((
x
,
y
),
message
,
inky_display
.
RED
,
font
)
inky_display
.
set_image
(
img
)
inky_display
.
show
()
As with all the program examples in this book, you can also download this program (see Recipe 3.22).
You won’t be playing any video games on these displays because they take a few seconds to update, but after they update, the ePaper keeps whatever you have drawn on it even when the power is removed. Pimoroni sells small displays like the Inky pHAT used here, and also a display twice the size that is pretty much as big as the Raspberry Pi (Inky wHAT).
More information is available in the full documentation of Inky pHAT.