Lab 10: Random Colors
Pixel says...
Random places plus color wheel colors make confetti made of light! We'll toss a new dot onto the strip ten times every second. Let's see how it fills up!
Program file: 10-random-colors.py
What you'll learn
- How to pick a random place and a random color with
randint() - How to feed a random number into
wheel()to get rich colors - How a program can leave every dot lit, so the strip slowly fills up
- How a small function, such as
clear(), does one job
What you'll need
- Your base kit: a Pico, a breadboard, and the 30-pixel LED strip, wired as shown in the Kit User's Guide
- The
config.pyfile saved on the Pico (see Getting Code onto the Kit) - Thonny open and connected to your Pico
- The ideas from Lab 08: Random and Lab 09: Color Wheel
The program
This program clears the strip, and then every tenth of a second it lights a random pixel with a random color from the wheel.
# Lab 10: Random Colors
# Filename: 10-random-colors.py
# Version: 1.0.0
#
# Color-wheel colors appear at random places along the strip.
from machine import Pin
from neopixel import NeoPixel
from utime import sleep
from urandom import randint
# https://docs.micropython.org/en/latest/library/random.html
import config
# hardware settings from config.py
NEOPIXEL_PIN = config.NEOPIXEL_PIN
NUMBER_PIXELS = config.NUMBER_PIXELS
strip = NeoPixel(Pin(NEOPIXEL_PIN), NUMBER_PIXELS)
red = (255, 0, 0)
orange = (140, 60, 0)
yellow = (255, 255, 0)
green = (0, 255, 0)
blue = (0, 0, 255)
# cyan = (0, 255, 255)
indigo = (75, 0, 130)
violet = (138, 43, 226)
white = (128, 128, 128)
colors = (red, orange, yellow, green, blue, indigo, violet)
color_count = len(colors)
levels = [255, 128, 64, 32, 16, 8, 4, 2, 1]
level_count = len(levels)
def wheel(pos):
# Input a value 0 to 255 to get a color value.
# The colors are a transition r - g - b - back to r.
if pos < 0 or pos > 255:
return (0, 0, 0)
if pos < 85:
return (255 - pos * 3, pos * 3, 0)
if pos < 170:
pos -= 85
return (0, 255 - pos * 3, pos * 3)
pos -= 170
return (pos * 3, 0, 255 - pos * 3)
# offset should be incremented by one for motion
def draw_random_color():
random_offset = randint(0, NUMBER_PIXELS-1)
random_color = randint(0, 255)
strip[random_offset] = wheel(random_color)
strip.write()
def clear():
for i in range(0, NUMBER_PIXELS):
strip[i] = (0,0,0)
strip.write()
# setup
counter = 0
clear()
# main loop
while True:
draw_random_color()
sleep(.1)
Run it. Dots of color pop up all over the strip, and none of them turn off. After a few seconds, most of the strip glows.
How it works
The wheel is back
The file has a wheel() function. It is the same one you met in Lab 09. It turns a number from 0 to 255 into a color.
The file also has other names, such as levels and color_count. The main loop does not use them, so you can skip over them.
Draw one random color
This function picks a random pixel and a random spot on the wheel, and then lights the pixel.
def draw_random_color():
random_offset = randint(0, NUMBER_PIXELS-1)
random_color = randint(0, 255)
strip[random_offset] = wheel(random_color)
strip.write()
random_offset is a pixel number from 0 to 29. random_color is a wheel position from 0 to 255. Then wheel(random_color) turns that position into red, green, and blue numbers.
Lab 08 picked three random numbers for a color. That can give pale colors. Here one number picks a spot on the wheel, and in every wheel color one of the three numbers is 0. So the colors look pure and bright.
Start with a dark strip
This function turns every pixel off and writes the change.
def clear():
for i in range(0, NUMBER_PIXELS):
strip[i] = (0,0,0)
strip.write()
A function is a named block of code. You define it once with def, and then you can call it by name. The next lines run clear() once at the start and then repeat the drawing forever.
clear()
...
while True:
draw_random_color()
sleep(.1)
The clear() line runs one time. The loop then draws a dot, waits a tenth of a second, and draws another. That makes about ten dots every second.
Nothing is erased
Look back at Lab 08. It turned each pixel off after half a second. This program has no line that turns a pixel off.
So every dot stays lit. Sometimes the program picks a pixel that already glows. That pixel changes to a new color. Picking pixels by chance means it takes about 12 seconds, on average, to touch every pixel at least once. Then the strip keeps shimmering as pixels change color.
Power check
Once the whole strip is lit, all 30 pixels glow. Every wheel color adds up to 255, so each pixel draws about 20 mA. That makes about 600 mA for the strip, and a USB port supplies about 500 mA. See How Bright Can You Go? for the details. To cut the total to about 150 mA, divide each color number by 4.
Replace the line strip[random_offset] = wheel(random_color) with these two lines to dim every dot.
red, green, blue = wheel(random_color)
strip[random_offset] = (red // 4, green // 4, blue // 4)
The first line splits the three numbers from wheel() into red, green, and blue. The // sign divides and drops any leftover decimal.
Try it yourself
- Change
sleep(.1)tosleep(.02). How many dots appear each second now? How fast does the strip fill? - Make each dot turn off after a pause. In Lab 08, the pixel goes dark after half a second. Bring that idea here. Hint: the pixel number lives inside
draw_random_color(), so try moving those lines into thewhile Trueloop.
Check your understanding
- Why does this strip fill up when the strip in Lab 08 did not?
- What does
clear()do, and how many times does it run? - Why do wheel colors look brighter than colors from three random numbers?
- What does
randint(0, NUMBER_PIXELS-1)pick, and why is there a-1?
Lab complete!
You built a light confetti machine! Random places plus wheel colors make a fun mix, and you did it with two small functions.
What's next: In Lab 11: Rainbow, the pixels stop being random and line up in a real rainbow.