Happy Halloween!

Circuit Playground Express

Computers come in all shapes and sizes. The Circuit Playground Express (CPX) is a "microprocessor," a computer that, compared with a full computer, is somewhat reduced in its features, speed, or performance.

We're going to be using your laptop computer to program the CPX, which can then run the program on its own.

You'll have a number of different options to experiment with in programming your CPX.

Let's get started!

Flash Drives and Text Editors

  1. Take a CPX and plug in the USB cable between the device and a USB-A port (or adapter and USB-C port) on your computer. When you plug the device in, it may start flashing some of its LED lights—it's using the power from your computer to run the last program that was installed on it.

    The CPX appears on your computer as a flash drive called "CIRCUITPY." If you open this drive, you'll see a small number of files and folders. The CPX can only hold a single program at a time, and the file for that program is called code.py.
  2. Open the code.py program with VSCode or some other text editor and you can start editing that program immediately. Any changes made to this file, when saved to the CPX, will automatically start running on that device.

Saving Programs

Because the CPX only runs a program if it's called code.py, if you want to save multiple CPX programs, you'll have to give them new names. You can "Save-As" any program on your computer with a more descriptive name (like blinkenlights.py or scary_witch.py). But when it's time to run that code on the CPX, you'll have to rename it to code.py on the CPX after you upload it.

The CircuitPython language

The CPX runs a variant of Python called CircuitPython, which is a small programming language that makes use of the Python syntax. If you've programmed in Python before you'll recognize the format of CircuitPython statements.

You'll be entering and manipulating code today to see how it works on the CPX!

The CPX Input/Output interface

You've got a CPX plugged into your laptop, you've certainly noticed that the device itself has no keyboard for input and no screen for output. The CPX gets its input from various sensors and input ports that are on the device itself, including a slider switch and two buttons. We'll see how those work soon.

Output can consist of a red LED light and ten "neopixels"—powerful, programmable LED lights that encircle the CPX. There's also a very small speaker installed on the CPX that you might use.

For the CPX to be able to run programs, it also needs some libraries that are imported so we can interact with the CPX's buttons, sensors, lights, etc.

Let's run through a few tutorial programs to get acquainted with the Circuit Playground Express.

Programs

Each of the programs given here is a complete, working program, with comments in the code describing the various lines, as well as comments at the top of each example explaining what the program does.

How to Learn Circuit Python

  1. Don't just copy-paste these programs. Type them in by hand so you can read the code while you're typing it.
  2. If you're typing straight into the code.py file on the CPX, when you "Save" the program it will automatically start to run.
  3. If the program doesn't work the way it's supposed to, you've got some debugging to do.
  4. If the program works just the way it's supposed to, try making a couple of small changes to the program to experiment with it and see what happens.
  5. When you're ready to move on to the next program, do so!

1. Getting started

You can write functions for your programs, but the only program that is ever running on the CPX is code.py, so you don't need to write a main() function. Just put the code directly into the program.

"""
This example turns on the little red LED.
(The green LED indicates power on the cpx.)
"""

# import the libraries needed
from adafruit_circuitplayground import cp

"""
All CPX programs require an infinite loop 
to repeatedly run through the instructions
in the body of the program. 
"""

while True:                 # infinite loop
    cp.red_led = True       # turns on the red_led
                            # on the cpx

Save this programs as code.py onto the CIRCUITPY device attached to your computer. After a moment to transfer the program onto the CPX, you should see the red led light up.

Yay! That's a program! Let's try another one.

2. Blinky

Here's a small variation that uses a timer.

"""
Blinky program flashes the red led 
"""

# import the libraries needed
from adafruit_circuitplayground import cp
import time
        
while True:
    cp.red_led = True       # light on
    time.sleep(0.5)         # hang out for half a second
    cp.red_led = False      # light off
    time.sleep(0.5)         # wait for half a second

Save this programs as code.py onto the CIRCUITPY device attached to your computer. After a moment to transfer the program onto the CPX, you should see the red led blinking.

Figure out how to make the light flash more quickly or more slowly.

There are a few switches/buttons that you can program on the CPX. Take a look at this program that uses the slide switch on the board.

3. Slide switch

"""
Demonstrates coding with the slide switch
"""

# import the libraries needed
from adafruit_circuitplayground import cp
import time

while True:    
    if cp.switch:                  # if the switch is "on" (to the left)
        cp.red_led = True          # turn on the red LED
    else:                          # otherwise...
        cp.red_led = False         # leave the LED off

So... how can we combine these two? As long as the slide switch if one, blink the light...

4. Switch Blinky

"""
Demonstrates using slide switch with blinking
"""

# import the libraries needed
from adafruit_circuitplayground import cp
import time

while True:    
    if cp.switch:                  # if the switch is "on" (to the left)
        cp.red_led = True       # light on
        time.sleep(0.5)         # hang out for half a second
        cp.red_led = False      # light off
        time.sleep(0.5)         # wait for half a second

Sound

The CPX has a very small, low-fidelity speaker that can play sounds of a given frequency, or even small sound files.

Here we build a simple "Annoy-a-Tron," which emits a high-pitched sound at random intervals.

Run this program, connect the CPX to its battery pack, and hide it away someplace... and watch it drive people crazy. >:-)

5. Annoy-a-Tron

"""
Annoy-a-tron
Based on the old ThinkGeek Annoy-a-tron.

In testing, the while-True CPX loop runs at a frequency
of ~2500 Hz. So something that happens on average 
once every 2500 times would happen on average once per
second. In subsequent testing, loop seemed to run faster?
Adust LOOP_FREQ as needed.


"""

from adafruit_circuitplayground import cp
import random
import time

LOOP_FREQ = 5000    # approximate times while-loop
                    # runs in 1 second
BEEP_FREQ = 1/60    # once every 60 seconds

while True:
    if cp.switch:
        # print("Slide switch off!")
        cp.stop_tone()
        continue
    else:
        if random.randrange( int(LOOP_FREQ / BEEP_FREQ)) == 0:
            cp.start_tone(10000)    # near the upper freq limit for speaker
            time.sleep(0.10)        # play for a moment
            cp.stop_tone()

Colors

Colors in computers are often represented as a combination of Red, Green, and Blue (RGB) values, with each of those colors indicated by a value in the range 0-255, where 0 is completely dark and 255 is maximum brightness. To indicate the brightest red color, then, you'd use (255, 0, 0) for (maximum red, no green, no blue).

  ( 128   ,    128    ,    0 )     
    red   ,   green   ,  blue    
    (red + green = yellow)

Multiple values in parentheses and separated by commas are called a tuple, and we can use them the describe colors, and light up pixels with those colors, on the CPX. Let's see how.

NeoPixels

There are 10 pixels around the edge of the CPX, numbered from 0-9. You can turn on all of the pixels to a given color like this. (Note that 128 is half-brightness for the pixels, and it's already very, very bright!)

"""
All pixels one color
"""
from adafruit_circuitplayground import cp

while True:    
    cp.pixels.fill( (0, 128, 0) )

Because the pixels each have their own address, 0-9, we can turn them on individually as well:

"""
Light the first three pixel. Also, use the brightness method to control brightness.
"""
from adafruit_circuitplayground import cp

cp.pixels.brightness = 0.2  # 20% brightness

while True:    
    cp.pixels[0] = (255, 255, 255)  # white
    cp.pixels[1] = (0, 0, 255)      # blue
    cp.pixels[2] = (255, 0, 0)      # red

Now let's try a more sophisticated program.

6. Light Chase

Try this program and see what happens! We're using two loops inside the main while loop to operate the pixels. The first one goes through all of the lights numbered 0-9, and checks to see if each one is in the list of lights to be turned on (lights). If it is, light it blue, otherwise, turn it off. Then we pause for 0.4 seconds, and finally we update that list of lights to a new set of values: instead of 0, 3, and 6, we'll now light 1, 4, and 7.

The mod operation % allows the light count to wrap around: if we were lighting up NeoPixel number 9, 9 + 1 is 10, and 10 % 10 is 0, meaning we'll now be lighting up light 0 again.

Try it out!

"""
NeoPixel Light Chaser 
"""

from adafruit_circuitplayground import cp
import time

cp.pixels.brightness = 0.2    # 20% brightness

# Identify lights to turn on
lights = [0, 1, 2, 3]

while True:
    for i in range(10):             # 0 - 9
        if i in lights:
            cp.pixels[i] = (0, 0, 255)  # blue
        else
            cp.pixels[i] = (0, 0, 0)    # off
    time.sleep(0.2)                 # wait 0.4 seconds
    # advance all pixels
    for i in range(len(lights)):
        lights[i] = (lights[i] + 1) % 10    # wraps around

So we now have strategies for controlling out lights.

Sensors

We've seen out lights can produce output on the CPX. There are multiple sensor inputs that we can use to interact with the device as well. Let's see some demonstrations of those.

7. Candy Bar Watcher

Try this code and see how the covering the light sensor will change its values.

You'll need to download the hey_put_that_back.wav sound file and drag it onto your CIRCUITPY drive so that the code can play that file when needed.

Before you load the program onto the CPX, move the slide switch to the right ("off"). Once the sound file and the program have been loaded onto the device, put a piece of candy over the light sensor and slide the switch to the left ("on").

"""
Candy Bar Watcher
Put this code and the `hey_put_that_back.wav` file onto your
Circuit Playground Express. Plug the CPX into its battery pack,
and cover the light sensor with a small candy bar.

Oooooh! Scary!!!! :)

Happy Halloween!
"""

from adafruit_circuitplayground import cp
import time

cp.pixels.brightness = 0.3

def pulse():
    """Creates glowing pixels to draw attention
    to the trap!"""
    direction = +1   # could be - 1 too
    val = 1
    for i in range(200):
        '''pixels 5-9 are on the opposite side of the
        light sensor, so we can cover up the light sensor
        and not have the pulsing light interfere with 
        light sensing'''
        cp.pixels[5:10] = ((val, 0, 0) * 5)
        # print(val) # for debugging
        time.sleep(0.005)
        # display value in plotter
        print((cp.light,))
        val += direction * 1
        if val > 100 or val < 1:
            direction = direction * -1

# Start main loop
while True:
    if cp.switch:
        pulse()
        time.sleep(0.2)
        if cp.light > 5:
            cp.play_file("hey_put_that_back.wav")
            time.sleep(2)

Accelerometers

The CPX has x-y-z accelerometers that can measure forces acting on the unit.

We can read those accelerometers and determine all sorts of things, including how the unit is being tilted, or whether or not it has been moved.

8. Halloween Pumpkin Witch!

Download the cackling witch sound file and put it onto the CIRCUITPY drive on your computer. Then load this program onto the CPX and see if you can figure out how it all works.

"""
Halloween Pumpkin Witch
Put this code and the `witch.wav` file onto your Circuit Playground
Express. Plug the CPX into its battery pack, and place the whole 
thing at the bottom of a small plastic pumpkin with candy in it.

Oooooh! Scary!!!! :)

Happy Halloween!
"""

from adafruit_circuitplayground import cp
import time
import random

def flash():
    """Creates three flashes of light"""
    cp.pixels.brightness = 0.1
    for i in range(3):
        # turn LEDs 0-9 on at full white
        cp.pixels[0:9] = [(255, 255, 255)] * 9
        # wait a very short period of time
        time.sleep(random.random() / 10)
        # turn LEDS all off (0s are dark)
        cp.pixels[0:9] = [(0, 0, 0)] * 9
        time.sleep(random.random() / 10)

# Store initial x-y-z acceleration readings
x, y, z = cp.acceleration

# Start main loop
while True:
    # if switch is turned on
    if cp.switch:
        # save old acceleration readings
        oldx, oldy, oldz = x, y, z
        # wait a moment
        time.sleep(0.1)
        # get new acceleration readings
        x, y, z = cp.acceleration
        # compare the values with Pythagorean theorem
        difference = ((x-oldx)**2 + (y-oldy)**2 + (z-oldz)**2)**0.5
        print(difference)     # displays result in Mu serial window

        # randomly flash lights to attract attention
        if random.random() < 0.05:
            flash()

        # if acceleration values are different enough, the
        # pumpkin has been moved. Activate the witch!
        if difference > 0.9:
            cp.play_file("witch.wav")
            # get new acceleration values
            x, y, z = cp.acceleration