Lab 9: Smiley Face
Pixel says...
You can light any pixel you like. So let's draw a face! You'll type the picture with letters,
and your code will turn each letter into a color. Let's light this up!
Program file: 09-smiley-face.py
What you'll learn
- How to write a picture as 8 lines of text
- How a dictionary works as a color key
- How two numbers in brackets pick one letter out of a picture
- How nested loops turn a whole picture into colored pixels
- How to change the picture and draw your own
What you'll need
- Your kit, with the matrix wired as shown in the Kit Guide
config.pysaved on the Pico- Thonny open and connected to your Pico
- The
xyfunction from Lab 7 and nested loops from Lab 8
The program
This program draws a yellow smiley face with blue eyes and a red smile.
# Lab 09: Smiley Face
# Filename: 09-smiley-face.py
# Version: 1.0.0
#
# Draws a smiley face. The picture is 8 lines of text, one line for each
# row of the matrix. Each letter stands for a color in the color key.
# Change the letters to draw your own picture.
from machine import Pin
from neopixel import NeoPixel
from utime import sleep
import config
print("Lab 09: Smiley Face (version 1.0.0)")
# hardware settings from config.py
NEOPIXEL_PIN = config.NEOPIXEL_PIN
NUMBER_PIXELS = config.NUMBER_PIXELS
MATRIX_WIDTH = config.MATRIX_WIDTH
MATRIX_HEIGHT = config.MATRIX_HEIGHT
SERPENTINE = config.SERPENTINE
strip = NeoPixel(Pin(NEOPIXEL_PIN), NUMBER_PIXELS)
# the color key: which color each letter stands for
COLORS = {
".": (0, 0, 0), # off
"Y": (28, 22, 0), # yellow
"B": (0, 0, 32), # blue
"R": (32, 0, 0), # red
}
# the picture: 8 rows of 8 letters
SMILEY = [
"..YYYY..",
".YYYYYY.",
"YYBYYBYY",
"YYYYYYYY",
"YRYYYYRY",
"YYRRRRYY",
".YYYYYY.",
"..YYYY..",
]
def xy(x, y):
if SERPENTINE and y % 2 == 1:
return y * MATRIX_WIDTH + (MATRIX_WIDTH - 1 - x)
return y * MATRIX_WIDTH + x
def draw(picture):
# look at every letter and give the pixel in the same spot its color
for y in range(MATRIX_HEIGHT):
for x in range(MATRIX_WIDTH):
letter = picture[y][x]
strip[xy(x, y)] = COLORS[letter]
strip.write()
draw(SMILEY)
while True:
sleep(1)
Run it. A smiley face fills the matrix and stays there. Click the red Stop button when you want it to end.
Lab 09: Smiley Face (version 1.0.0)

This picture was drawn by a computer simulator, so your real matrix may look a little different.
How it works
A picture made of letters
SMILEY = [
"..YYYY..",
".YYYYYY.",
"YYBYYBYY",
"YYYYYYYY",
"YRYYYYRY",
"YYRRRRYY",
".YYYYYY.",
"..YYYY..",
]
Squint at those lines. You can already see the face! A piece of text in quotes is called a string. This list holds 8 strings, one for each row of the matrix. Each string has 8 letters, one for each pixel in that row.
Here is the same picture with every letter sitting on its own pixel:

This picture was drawn by a computer simulator.
The color key
COLORS = {
".": (0, 0, 0), # off
"Y": (28, 22, 0), # yellow
"B": (0, 0, 32), # blue
"R": (32, 0, 0), # red
}
A map has a key that tells you what each symbol means. This is the key for our picture. In Python it is called a dictionary. A dictionary holds pairs. The first half of a pair is the thing you look up, and the second half is the answer.
So COLORS["Y"] looks up the letter Y and hands back (28, 22, 0), which is yellow. A dot hands back (0, 0, 0), which means off.
Pick one letter
letter = picture[y][x]
This line uses two sets of brackets. The first one, picture[y], picks a row, which is one string. The second one, [x], picks one letter from that string. Both count from 0.
| You write | What Python does | Answer |
|---|---|---|
SMILEY[2] |
Take row 2 | "YYBYYBYY" |
SMILEY[2][0] |
Take letter 0 of row 2 | "Y" |
SMILEY[2][2] |
Take letter 2 of row 2 | "B" |
SMILEY[5][3] |
Take letter 3 of row 5 | "R" |
Draw the whole picture
def draw(picture):
# look at every letter and give the pixel in the same spot its color
for y in range(MATRIX_HEIGHT):
for x in range(MATRIX_WIDTH):
letter = picture[y][x]
strip[xy(x, y)] = COLORS[letter]
strip.write()
This is the nested loop from Lab 8. The outer loop walks down the rows. The inner loop walks across each row. For every spot, the code reads the letter, looks up its color, and sets that pixel.
The loops touch all 64 pixels. Then one strip.write() sends the whole picture at once.
Key idea
The picture is data, and draw is the code that reads it. To change the picture, you change the data. The code stays the same.
How much power does a face use?
Count the letters: 44 are Y, 2 are B, and 6 are R. Add up the color numbers the same way you did in Lab 5.
| Letter | Color numbers in one pixel | Pixels | Total |
|---|---|---|---|
| Y | 28 + 22 + 0 = 50 | 44 | 2,200 |
| B | 32 | 2 | 64 |
| R | 32 | 6 | 192 |
| All | 52 | 2,456 |
2,456 × 0.078 is about 190 mA. That is well under the 500 mA that a USB (Universal Serial Bus) port supplies. Small color numbers keep a full picture safe.
Try it yourself
- Change the eye color. In
COLORS, change the numbers after"B"to(0, 28, 0). Both eyes turn green. Why did one change fix both eyes? -
Turn the smile into a frown. Swap rows 4 and 5 of the picture so they look like this:
"YYRRRRYY", "YRYYYYRY", -
Add a new color. Add the line
"P": (32, 6, 14),toCOLORSfor pink. Then change a few letters in the picture toPto give your face rosy cheeks. -
Draw your own picture. Replace the 8 strings with your own. Here is a heart to get you started. Every string must have exactly 8 letters.
SMILEY = [ ".RR..RR.", "RRRRRRRR", "RRRRRRRR", "RRRRRRRR", ".RRRRRR.", "..RRRR..", "...RR...", "........", ]
If you see KeyError, you used a letter that is not in COLORS. That's a puzzle to solve! Add the letter to the key, or fix the typing slip. If you see IndexError, one of your strings has fewer than 8 letters.
Check your understanding
- What does a dot mean in the picture?
- What letter does
SMILEY[2][5]give? Count from 0. - What is a dictionary? What does
COLORS["R"]hand back? - How many strings are in the picture? How many letters are in each string?
- Why does
strip.write()come after both loops and not inside them?
Lab complete!
You drew a picture with code! Every image on every screen starts the same way: a grid of colors.
What's next: In Lab 10: Picture Show, your buttons will flip through a whole gallery of pictures.