Program the Robot

Coding in CircuitPython for Crickit and Circuit Playground Express

Crickit and Circuit Playground Express (CPX) are a great combo for robotics projects. And when paired with CircuitPython, it's very straightforward to write your own code and iterate quickly during testing.

Setup the CPX and Crickit

The Circuit Playground Express (CPX) paired with the Crickit is a powerful, yet simple to use combination for building animatronics! To get started, you'll want to set up the CPX for use with CircuitPython by following this guide. When you're ready, and can upload code to the board return here.

To use the Crickit with the CPX, follow the steps listed here to install the special build of CircuitPython (name will begin with 'adafruit-circuitpython-circuitplaygroundexpress-crickit...'), as well as the latest library bundle.

Audio File

We'll have the bot play some circus music when it starts up. Download the file here and copy it to the root level of your CPX CIRCUITPY drive that shows up when it's plugged into your computer.

The CC licensed circus theme music came from Freesound.

CircuitPython Code

Adafruit suggests using the Mu editor to edit your code and have an interactive REPL in CircuitPython. You can learn about Mu and installation in this tutorial.

The full code is included below -- you can copy and paste that into Mu and save it to your CPX to get it all working. After the full code is an explanation of how the various code snippets work.

import time
import board
import neopixel
import audioio
import adafruit_crickit

print("Adabot Tightrope Unicyclist!")
RED =   (16, 0, 0)
GREEN = (0, 16, 0)
BLACK = (0, 0, 0)

pixels = neopixel.NeoPixel(board.NEOPIXEL, 10, brightness = 0.2)
pixels.fill(BLACK)

# Create a motor on Crickit Motor 1 port
motor = adafruit_crickit.crickit.dc_motor_1

############### User variables
run_time = 6
speed = 0.65

############### Music
cpx_audio = audioio.AudioOut(board.A0)  # speaker out on Crickit
def play_file(wavfile):
    with open(wavfile, "rb") as f:
        wav = audioio.WaveFile(f)
        cpx_audio.play(wav)
        while cpx_audio.playing:
            pass

wav_file_name = "circus.wav"
play_file(wav_file_name)

while True:
    # set NeoPixels green in direction of movement
    for i in range(5):
        pixels[i] = GREEN
    for i in range(5):
        pixels[i+5] = BLACK

    motor.throttle = speed  # full speed forward
    time.sleep(run_time)  # motor will run for this amount of time

    # set NeoPixels red when stopped
    pixels.fill(RED)
    motor.throttle = 0  # stop the motor

    # set NeoPixels green in direction of movement
    for i in range(5):
        pixels[i] = BLACK
    for i in range(5):
        pixels[i+5] = GREEN

    motor.throttle = -1 * speed  # full speed backward
    time.sleep(run_time)  # motor will run for this amount of time

    pixels.fill(RED)
    motor.throttle = 0  # stopped

Here are the different sections of the code, and how they work.

Library Imports

First, we'll import a few libraries. We'll import time so we can use the sleep command.

We also import the board library, which gives us convenient definitions for objects on the CPX that we can call.

Then, we'll import neopixel and audioio. That way we can blink lights (neopixels) and make some music!

Finally, the good stuff - from the adafruit_crickit library we import crickit, this is the library that lets us talk to the Crickit robotics board and make stuff move!

These code snippets aren't meant to be run on their own, they are here for explanation purposes.
Download: file
import time
import board
import neopixel
import audioio
from adafruit_crickit import crickit

NeoPixel Prep

We'll define variables to represent the color values we'll use for the NeoPixels to indicate forward, backward, and stopped states.

Then, we'll set up the NeoPixel object and set them to black (off).

Download: file
RED =   (16, 0, 0)
GREEN = (0, 16, 0)
BLACK = (0, 0, 0)

pixels = neopixel.NeoPixel(board.NEOPIXEL, 10, brightness = 0.2)
pixels.fill(BLACK)

Motor Prep

The next thing to do is to instantiate the motor output, we'll be using the Motor 1 port (The two pins are labeled on the Crickit as Motor and then the "1" pair) To make things easier to type we'll call the motor, simply motor!

Download: file
# Create a motor on Crickit Motor 1 port
motor = crickit.dc_motor_1

User Variables

Depending on your tightrope's length, you may want to unicycle for greater or lesser amounts of time in each direction. You may also want to direct Adabot to go faster or slower.

These two variables -- run_time and speed -- are used to define the run time in each direction in seconds, and the amount of power to send to the motor from '0' to '1'. (Technically, this goes down to '-1' for reverse, but we'll handle that with a bit of math later.)

Download: file
############### User variables
run_time = 6
speed = 0.65

Music, Maestro

This next section is used to create an audio output object named cpx_audio, and then to define a process called play_file() we can call upon to play back audio files in the .wav format.

Download: file
############### Music
cpx_audio = audioio.AudioOut(board.A0)  # speaker out on Crickit
def play_file(wavfile):
    with open(wavfile, "rb") as f:
        wav = audioio.WaveFile(f)
        cpx_audio.play(wav)
        while cpx_audio.playing:
            pass

We saved a file to the CPX named 'circus.wav' so we'll cast a variable for that, and then run the play_file() command to have it play once during startup of the robot.

Download: file
wav_file_name = "circus.wav"
play_file(wav_file_name)

Main Loop

With the setup complete, now we get into the bulk of the program, which runs over and over. This is everything that follows the while True: line.

The main loop does just a few things over and over:

  • Light the five NeoPixels on the left of the board green
  • Run the motor forward for a set amount of time
  • Light all NeoPixels red
  • Stop the motor
  • Light the five NeoPixels on the right of the board green
  • Run the motor backward for a set amount of time
  • Light all NeoPixels red
  • Stop the motor
  • Repeat

This is the code that does those steps:

NeoPixels Forward

This runs through the first five NeoPixels in the for loop and sets them to green, then runs through the second five and sets them black, or off.

Download: file
    # set NeoPixels green in direction of movement
    for i in range(5):
        pixels[i] = GREEN
    for i in range(5):
        pixels[i+5] = BLACK

Motor Forward

This section uses the motor.throttle command and sets it to the speed we previously defined, for the run_time in seconds.

Download: file
motor.throttle = speed  # full speed forward
time.sleep(run_time)  # motor will run for this amount of time

Stop

Then, we set all NeoPixels red, and stop the motor.

Download: file
# set NeoPixels red when stopped
pixels.fill(RED)
motor.throttle = 0  # stop the motor

Then, we essentially repeat these steps for the reverse direction. Note, the use of motor.throttle = -1 * speed as a way to reverse motor direction.

Download: file
# set NeoPixels red when stopped
pixels.fill(RED)
motor.throttle = 0  # stop the motor

# set NeoPixels green in direction of movement
for i in range(5):
    pixels[i] = BLACK
for i in range(5):
    pixels[i+5] = GREEN

motor.throttle = -1 * speed  # full speed backward
time.sleep(run_time)  # motor will run for this amount of time

pixels.fill(RED)
motor.throttle = 0  # stopped

Once you start to run your unicyclist on the tightrope you can come back and revisit the code to change the behavior.

  • What if you want to pause between directions and play the song again?
  • How about varying the speed to ease into and out of the top speed?
  • Since the same things happen in each direction, can you optimize the code to reduce the repetitive code blocks?
This guide was first published on May 29, 2018. It was last updated on May 29, 2018. This page (Program the Robot) was last updated on Sep 22, 2019.