Why Functions
To turn off all the lights we just need a simple loop:
for i in range(20):
pixels[i] = (0,0,0)
However, as we write more interesting lighting sequences, we'll find that we need to do this quite often, so we can create a shortcut that we'll call a function.
Assignment 1
Write a program to do the following (you don't have to use functions to do it),- Light up all of the lights (green) (in sequence with a 0.1 second delay),
- Turn off the lights
- Wait for 1 second,
- Light up all the lights again (red)
- Turn off the lights
import board
import neopixel
import time
pixels = neopixel.NeoPixel(board.GP0, 20)
# make lights green in sequence
for i in range(20):
pixels[i] = (0,10,0)
time.sleep(0.1)
# turn off lights
for i in range(20):
pixels[i] = (0,0,0)
# wait 1 second
time.sleep(1)
# make lights red in sequence
for i in range(20):
pixels[i] = (10,0,0)
time.sleep(0.1)
# turn off lights
for i in range(20):
pixels[i] = (0,0,0)
Writing Functions (Turn off the lights)
A function to turn off the lights looks like this:
def lightsOff():
for i in range(20):
pixels[i] = (0,0,0)
def lightsOff():
- Define the function and give it a name "lightsOff"
- Everything tabbed over after the function definition is in the function: it's what's done when the function is called.
- The function is usually defined at or near the top of the code (later on we'll actually put it in its own file.)
- The function is called in the program when it's needed.
Let's redo Assignment 1 but use a function to turn the lights off. The function is defined on lines 7-10, and called twice on lines 20 and 31.
import board
import neopixel
import time
pixels = neopixel.NeoPixel(board.GP0, 20)
# FUNCTION: to turn off all the lights
def lightsOff():
for i in range(20):
pixels[i] = (0,0,0)
# MAIN PROGRAM STARTS HERE
# make lights blue in sequence
for i in range(20):
pixels[i] = (0,0,10)
time.sleep(0.1)
# CALL the function to turn off lights
lightsOff()
# wait 1 second
time.sleep(1)
# make lights red in sequence
for i in range(20):
pixels[i] = (10,0,0)
time.sleep(0.1)
# CALL the function to turn off lights
lightsOff()
Assignment 2
Write a function calledallBlue
that turns all of the lights blue (in sequence with a 0.1 second timestep), and use it in a program that:
- Light up all of the lights (blue) (in sequence with a 0.1 second delay),
- Turn off the lights
- Wait for 1 second,
- Light up all the lights again (red)
- Turn off the lights
- Wait for 1 second,
- Light up all the lights again (blue)
import board
import neopixel
import time
pixels = neopixel.NeoPixel(board.GP0, 20)
# FUNCTION: to turn off all the lights
def lightsOff():
for i in range(20):
pixels[i] = (0,0,0)
# FUNCTION: to make all leds blue
def allBlue():
for i in range(20):
pixels[i] = (0,0,10)
time.sleep(0.1)
# MAIN PROGRAM STARTS HERE
allBlue() # make lights blue
lightsOff() # turn off lights
time.sleep(1) # wait one second
# make lights red in sequence
for i in range(20):
pixels[i] = (10,0,0)
time.sleep(0.1)
# CALL the function to turn off lights
lightsOff() # turn lights off
time.sleep(1) # wait one second
allBlue() # make lights blue
Passing Parameters
We could make separate functions that light up all the different colors in sequence (you may have already done so for the red lights in Assignment 2). However, this would be easier to handle if we could tell the function which color to use.
So we'll pass a parameter called color
to a function, which will use that color.
Let's call the function lightSequence
.
def lightSequence(color):
for i in range(20):
pixels[i] = color
time.sleep(0.1)
lightSequence( (10,0,0) ) # call to make lights red
lightSequence( (0,0,10) ) # call to make lights blue
In the call to the function with lightSequence( (10,0,0) )
, we pass the color (e.g. red (10,0,0)
in the first call).
The function definition, def lightSequence(color):
expects to be passed one parameter called "color", that the function uses to set the led colors on line 3.
Assignment 3
Use thelightSequence
function to:
- Light up all of the lights (red) (in sequence with a 0.1 second delay),
- Turn off the lights then wait for 1 second.
- Light up all the lights again (green)
- Turn off the lights then wait for 1 second.
- Light up all the lights again (blue)
- Turn off the lights then wait for 1 second.
- Light up all the lights again (yellow)
import board
import neopixel
import time
pixels = neopixel.NeoPixel(board.GP0, 20)
# FUNCTION: to turn off all the lights
def lightsOff():
for i in range(20):
pixels[i] = (0,0,0)
# FUNCTION: to light up all the lights with a given color
def lightSequence(color):
for i in range(20):
pixels[i] = color
time.sleep(0.1)
# MAIN PROGRAM STARTS HERE
lightSequence( (10,0,0) ) # make lights red
lightsOff()
time.sleep(1)
lightSequence( (0,10,0) ) # make lights green
lightsOff()
time.sleep(1)
lightSequence( (0,0,10) ) # make lights blue
lightsOff()
time.sleep(1)
lightSequence( (10,10,0) ) # make lights yellow
Assignment 4
Write a function that lights the LEDs backwards and use it to:- Light up all of the lights (red) (in sequence with a 0.1 second delay),
- Turn off the lights (no wait)
- Light up all the lights backwards (green)
- Light up all the lights again (blue)
- Light up all the lights backwards (red)
We believe in you.
import board
import neopixel
import time
pixels = neopixel.NeoPixel(board.GP0, 20)
# FUNCTION: to turn off all the lights
def lightsOff():
for i in range(20):
pixels[i] = (0,0,0)
# FUNCTION: to light up all the lights with a given color
def lightSequence(color):
for i in range(20):
pixels[i] = color
time.sleep(0.1)
def lightBackwards(color):
for i in range(19, -1, -1):
pixels[i] = color
time.sleep(0.1)
# MAIN PROGRAM STARTS HERE
lightSequence( (10,0,0) ) # make lights red
lightsOff()
lightBackwards( (0,10,0) ) # make lights green
lightSequence( (0,0,10) ) # make lights red
lightBackwards( (10,0,0) )
Passing Multiple Parameters
You can pass multiple variables to a function, they just need to be comma separated. For example, a function to make three lights red, blue, and green respectively would look like:
def lightRGB(a, b, c):
pixels[a] = (10,0,0)
pixels[b] = (0,10,0)
pixels[c] = (0,0,10)
# function call
lightRGB(1, 4, 10)
import board
import neopixel
import time
pixels = neopixel.NeoPixel(board.GP0, 20)
def lightRGB(a, b, c):
pixels[a] = (10,0,0)
pixels[b] = (0,10,0)
pixels[c] = (0,0,10)
# function call
lightRGB(1, 4, 10)
Assignment 5
Write a function calledlightUp
that you can pass a number of lights to and it will light up that many lights in sequence (0.1 second delay between lights). For example, if you passed it the number 7, 7 LEDs would light up.
- Light up the first 5 lights (red) (in sequence with a 0.1 second delay),
- Light up the first 10 lights (green) in sequence
- Light up all the lights (blue) in sequence
- Light just the first 10 lights (red) in sequence
- Light just the first 5 lights (yellow) in sequence
import board
import neopixel
import time
pixels = neopixel.NeoPixel(board.GP0, 20)
# FUNCTION: to turn off all the lights
def lightsOff():
for i in range(20):
pixels[i] = (0,0,0)
# FUNCTION: to light up a given number of lights (n) with a given color (color)
def lightUp(n, color):
for i in range(n):
pixels[i] = color
time.sleep(0.1)
# MAIN PROGRAM STARTS HERE
lightUp(5, (10,0,0))
lightUp(10, (0,10,0))
lightUp(20, (0,0,10))
lightUp(10, (10,0,0))
lightUp(5, (5,5,0))
Error Messages: Passing Parameters
What happens when you pass too many, or too few parameters?
Understanding error messages is a lot easier if you've seen them before. So it's useful to make intentional errors and observe the resulting errom messages.
What error message do you get when you forget to pass a variable to a function that needs one?
The lightRGB
function below requires 3 parameters (a, b, and c), but if we put in only two paramters in the function call:
def lightRGB(a, b, c): # requires 3 parameters
pixels[a] = (10,0,0)
pixels[b] = (0,10,0)
pixels[c] = (0,0,10)
# function call
lightRGB(1, 4) #passing only 2 paramters
Traceback (most recent call last):
File "", line 13, in
TypeError: function takes 3 positional arguments but 2 were given
Assignment 6: Error Messages when Passing Parameters
What error message do you get when you pass too many variables to thelightRGB
function?
import board
import neopixel
import time
pixels = neopixel.NeoPixel(board.GP0, 20)
def lightRGB(a, b, c):
pixels[a] = (10,0,0)
pixels[b] = (0,10,0)
pixels[c] = (0,0,10)
# function call
lightRGB(1, 4, 10, 15)
Traceback (most recent call last):
File "", line 13, in
TypeError: function takes 3 positional arguments but 4 were given
Default Parameters
The lightUp
function can light any given number of leds and sets their color.
def lightUp(n, color):
for i in range(n):
pixels[i] = color
time.sleep(0.1)
However, we might frequently want to light up all the leds. We can set it up so that the function does that by default if you don't pass it a number parameter (n). Because python does not like it if you have non-default parameters after default parameters, we'll also set a default color ("blue").
- Default
n
: 20 - Default
color
: (0, 0, 10)
def lightUp(n=20, color=(0,0,10)):
for i in range(n):
pixels[i] = color
time.sleep(0.1)
Now we can call the function without any argumements and it will still work.
import board
import neopixel
import time
pixels = neopixel.NeoPixel(board.GP0, 20)
def lightUp(n=20, color=(0,0,10)):
for i in range(n):
pixels[i] = color
time.sleep(0.1)
# function call
lightUp()
We can pass either parameter if we want, but it can get tricky if we don't name them. The rule is that you still need to pass the parameters in the right positional order. In this case, that means if you called the function with lightUp(5)
, that would work, but trying to set only the color, lightUp((0,10,0))
would fail (you should try them yourself to see the error messages).
To avoid this issue we can just name the parameters as we pass them. So to make all 20 leds green we can use:
def lightUp(n=20, color=(0,0,10)):
for i in range(n):
pixels[i] = color
time.sleep(0.1)
lightUp(color=(0,10,0))
Assignment 7: Using Default Parameters
Use thelightUp
function, while taking maximum advantage of the default parameters to:
- Light up all the lights (blue) in sequence,
- Light up the first 10 lights (red) in sequence
- Light up all the lights (green) in sequence
- Light up all the lights (blue) in sequence
- Light just the first 10 lights (yellow) in sequence
import board
import neopixel
import time
pixels = neopixel.NeoPixel(board.GP0, 20)
def lightUp(n=20, color=(0,0,10)):
for i in range(n):
pixels[i] = color
time.sleep(0.1)
# function call
lightUp()
lightUp(n=10, color=(10,0,0))
lightUp(color=(0,10,0))
lightUp()
lightUp(10, (5,5,0))
Assignment 8: Last Lights
Write a functionlastLights
that:
- lights up the last n lights in sequence, given the number of lights (n) and their color.
- By default, it should light up all the leds.
- Default color: green
lastLights(n=7)
it should do this:
We believe in you.
import board
import neopixel
import time
pixels = neopixel.NeoPixel(board.GP0, 20)
def lastLights(n=20, color=(0,10,0)):
startLed = 20-n
for i in range(startLed, 20):
print(i)
pixels[i] = color
time.sleep(0.1)
# function call
lastLights(7)
Assignment 9: Step Lights
Write a functionstepLights
that:
- Lights up all the leds that are multiples of the given step
- The default step = 1
- Default color: green
- Default time between steps = 0.1 seconds
stepLights(step=2, dt=1)
it should do this:
We believe in you.
import board
import neopixel
import time
pixels = neopixel.NeoPixel(board.GP0, 20)
def stepLights(step=1, color=(0,10,0), dt=0.1):
for i in range(0, 20, step):
pixels[i] = color
time.sleep(dt)
# function call
stepLights(step=2, dt=1)
Returning Values from Functions
To make interesting color patterns, it can be useful to use complementary colors. These are matched colors that go well together.
A simple way to find a complementary color to a given color is to figure out what color would need to be added to give white.
For example, the RGB color code for blue is (0,0,255) and white is (255,255,255), so if we subtract blue from white we get:
(255, 255, 255) - (0, 0, 255) = (255, 255, 0)
(255, 255, 0) is yellow, which is the complementary color for blue.
Example: Write a function called complementaryColor
that returns the complementary color for any given color.
def complementaryColor(color):
r = 255 - color[0]
g = 255 - color[1]
b = 255 - color[2]
return (r, g, b)
# MAIN PROGRAM: find the complementary color of blue
blue = (0, 0, 255)
compColor = complementaryColor(blue)
print(compColor)
In the function:
- Lines 2-4 calculate the complementary colors.
- Line 5 returns the values calculated by the function to the main program.
To see this in practice. Here is a program that lights up the first light with a color (color1
) and the last light with its complementary color (compColor
), using the complementaryColor
function:
import board
import neopixel
import time
pixels = neopixel.NeoPixel(board.GP0, 20)
def complementaryColor(color):
r = 255 - color[0]
g = 255 - color[1]
b = 255 - color[2]
return (r, g, b)
# MAIN PROGRAM
color1 = (0, 0, 255)
compColor = complementaryColor( color1 )
print(f'complementary color of {color1} is {compColor}')
pixels[0] = color1
pixels[-1] = compColor
Assignment 10: Scaling Complementary Colors
Finding the complementary color by subtracting from 255 makes for some very bright lights. We can instead use a different number, call it a scaling value to subtract the rgb values from instead.
Write a function that takes two input parameters (a color and a scaling value) and returns the scaled complementary color.
Inputs:- A color (in the form (r, g, b))
- A scaling value that is used instead of 255 to calculate the complementary color.
For example. If the input color is color = (10, 5, 7) and the scaling value = 10, then the complementary color returned should be (0, 5, 3).
Use the function to make the first 10 lights the starting color, and the second 10 the complementary color.
import board
import neopixel
import time
pixels = neopixel.NeoPixel(board.GP0, 20)
def complementaryColor(color, scaleFactor):
r = scaleFactor - color[0]
g = scaleFactor - color[1]
b = scaleFactor - color[2]
return (r, g, b)
# MAIN PROGRAM
color1 = (7,2,10)
compColor = complementaryColor( color1 , 10)
print(f'complementary color of {color1} is {compColor}')
for i in range(10):
pixels[i] = color1
pixels[i+10] = compColor
Importing Functions from Other Files
We've made an number of functions that will be useful in designing light patterns. However, keeping them all in the same file adds some clutter we can aleviate by moving our functions into a separate file and importing them when we need them.
This is particularly useful when you're sharing a Pi Pico, because you can save your functions in a separate file that does not get overwritten by other students.
First, let's create a file with the functions, lightsOff
, lightUp
, lastLights
, and complementaryColor
(you can put other functions in if you like). I'm going to call my file docFuncs.py , but you should give yours a unique name.
import board
import neopixel
import time
pixels = neopixel.NeoPixel(board.GP0, 20)
def lightsOff():
for i in range(20):
pixels[i] = (0,0,0)
def lightUp(n=20, color=(0,0,10)):
for i in range(n):
pixels[i] = color
time.sleep(0.1)
def lastLights(n=20, color=(0,10,0)):
startLed = 20-n
for i in range(startLed, 20):
print(i)
pixels[i] = color
time.sleep(0.1)
def complementaryColor(color):
r = 255 - color[0]
g = 255 - color[1]
b = 255 - color[2]
return (r, g, b)
Now, we can write a much shorter program that imports the functions.
from docFuncs import *
lightUp()
lightsOff()
lastLights(8)
Assignment 11: Importing Functions
Add as many functions as you'd like to your functions file and make an interesting lighting pattern using them.