Code the UFO with CircuitPython

The Circuit Playground Express has all the features you'll need to make a great, reactive light and sound effects pack for your flying saucer. And, coding it all in CircuitPython is straightforward and uses high level commands to make things simple.

We'll use the built in accelerometer to measure the orientation of the board, and then use those readings to effect the light colors, the pitch of the sounds, and the speed of the light/sound cycle.

For example, we can have it make faster, higher pitched sounds when tilted, and then slow down and lower the tones when the craft is level. This is usually when the aliens do all of their abductions of cows and otherwise peaceful citizens, BTW.

The Circuit Playground Express can be used with three different programming methods: CircuitPython, Arduino, and Make:Code. For this project we'll use CircuitPython.

Make sure know how to set up your Circuit Playground Express  for use with CircuitPython by following this guide

Once you've installed the latest version of CircuitPython for Circuit Playground Express from here and the library bundle from here, (be sure to unzip it and replace the lib folder on your CIRCUITPY drive with the new one from the bundle) you're ready!

Now, you're can to add a small CircuitPython script to tell the board what to do! Copy the code from the section below, then paste it into a new document in your favorite code/text editor.

With your Circuit Playground Express plugged in, you'll see a drive on your computer called CIRCUITPY. Save the file to this drive as main.py.

#  UFO Flying Saucer with Circuit Playground Express
#  https://learn.adafruit.com/ufo-circuit-playground-express/
#  Plays UFO lights and sounds if the board is upside down only,
#  Tilt to change light color, cycle speed, tone pitch

from adafruit_circuitplayground.express import cpx
import neopixel
import board
import time

#create neopixel object. set brightness lower if needed, say .2
pixels = neopixel.NeoPixel(board.NEOPIXEL, 10, brightness=.8)

def simpleCircle(wait, R, G, B):  # timing, color values per channel
    baseFreq = int(20 + (G * 0.3))  # tone value derived from rotation

    for i in range(10):
        pixels[i] = ((0, 0, 0))
        cpx.start_tone(baseFreq + i)  # increasing pitch sweep
        time.sleep(wait)

    for i in range(10):
        pixels[i] = ((R, G, B))
        time.sleep(wait)

# Main loop gets x, y and z axis acceleration, prints the values, and turns on
# lights if the UFO is upside down, plays tones
while True:
    R = 0
    G = 0
    B = 0
    x, y, z = cpx.acceleration  # read the accelerometer values

    R = 10 * (R + abs(int(x)))  # scale up the accel values into color values
    G = 10 * (G + abs(int(y)))
    B = 10 * (B + abs(int(z)))

    # check for upside down state on z axis
    if z < 0:  # any negative number on z axis means it's upside down enough
        speed = (0.01 * (B * 0.025))
        simpleCircle(speed, R, G, B)  # speed based on tilt, .01 is good start

    else:  # right side up means no colors or sound!
        pixels.fill((0, 0, 0))
        cpx.stop_tone()

Now, try tilting your board. You'll see that it doesn't do anything while it is right side up, with the board facing the ceiling. But once you tilt it beyond 90 degrees to point it toward the ground, the lights will start to cycle and the sound effects will begin to play!

Notice how different angles create different colors, sound pitches, and frequency of the effects. 

The "normal" range for play_tone values is usually ~100-2000 -- higher than what we're using here. But these very low values -- in the 20s and 30s -- create a strange glitchy sound that's perfect for a UFO!

Now, it's time to package your lights and sounds inside a UFO!

Last updated on 2017-10-24 at 06.03.41 PM Published on 2017-10-24 at 08.26.31 PM