CircuitPython Code

Getting Familiar

CircuitPython is a programming language based on Python, one of the fastest growing programming languages in the world. It is specifically designed to simplify experimenting and learning to code on low-cost microcontroller boards. Here are some guides which cover the basics:

Be sure you have the latest CircuitPython loaded onto your board per the second guide.

CircuitPython is easiest to use within the Mu Editor. If you haven't previously used Mu, this guide will get you started.

Download Library Files

Plug your nRF Feather board into your computer via a USB cable. Please be sure the cable is a good power+data cable so the computer can talk to the board.

A new disk should appear in your computer's file explorer/finder called CIRCUITPY. This is the place we'll copy the code and code library. If you can only get a drive named FTHR840BOOT, load CircuitPython per the guide above.

Create a new directory on the CIRCUITPY drive named lib.

Download the latest CircuitPython libraries to your computer using the green button below. Match the library you get to the version of CircuitPython you are using. Save to your computer's hard drive where you can find it.

Note: This project uses the Bluetooth functionality available in CircuitPython 4.0.0-beta.1 and later, on nRF52840 boards such as the Feather nRF52840 Express. Make sure you are using that version or later.

With your file explorer/finder, browse to the bundle and open it up. Copy the following folder from the library bundle to your CIRCUITPY lib directory you made earlier:

  • adafruit_ble (folder)
  • adafruit_bluefruit_connect (folder)
  • adafruit_crickit.mpy (file)
  • adafruit_motor (folder)
  • adafruit_seesaw (folder)

All of the other necessary code is baked into CircuitPython!

CircuitPython Program

Download the circuit.py program below and save it on the CIRCUITPY flash drive as code.py. As soon as CircuitPython restarts, the servo arm will move into position, away from the NeoPixel ring.

# CircusPython!
# For use with the Adafruit BlueFruit LE Connect app.
# Works with CircuitPython 4.0.0-beta.1 and later running on an nRF52840 board.

import random
import time

from adafruit_crickit import crickit
from adafruit_ble.uart import UARTServer

from adafruit_bluefruit_connect.packet import Packet
# Only the packet classes that are imported will be known to Packet.
from adafruit_bluefruit_connect.color_packet import ColorPacket
from adafruit_bluefruit_connect.button_packet import ButtonPacket

# Initialize the NeoPixel ring to a fire color, not too bright.
crickit.init_neopixel(24, brightness=0.1)
color = (25, 12, 0)

# Creates a sparkly "fire"-like effect.
def sparkle():
    crickit.neopixel[random.randrange(24)] = (0, 0, 0)
    crickit.neopixel[random.randrange(24)] = color
    crickit.neopixel[random.randrange(24)] = color
    crickit.neopixel[random.randrange(24)] = color

uart_server = UARTServer()

# Increase this to slow down movement of the servo arm.
DELAY = 0.0

# Angle for Blinka before jumping through the ring.
UP_ANGLE = 50

# Go to this angle when jumping through the ring. Adjust
# slightly as necessary so you don't bump into the ring.
DOWN_ANGLE = 2

advertising_now = False
crickit.servo_1.angle = UP_ANGLE
angle = UP_ANGLE

while True:
    sparkle()
    if not uart_server.connected:
        if not advertising_now:
            uart_server.start_advertising()
            advertising_now = True
        continue

    # Connected, so no longer advertising.
    advertising_now = False

    if uart_server.in_waiting:
        packet = Packet.from_stream(uart_server)
        if isinstance(packet, ColorPacket):
            # Change the fire color.
            color = packet.color
        elif isinstance(packet, ButtonPacket):
            if packet.pressed:
                if packet.button == '5' and angle != UP_ANGLE:
                    # The Up button was pressed.
                    for a in range(angle, UP_ANGLE+1, 1):
                        crickit.servo_1.angle = a
                        # Sparkle while moving.
                        sparkle()
                        time.sleep(DELAY)
                    angle = UP_ANGLE
                elif packet.button == '6' and angle != DOWN_ANGLE:
                    # The Down button was pressed.
                    for a in range(angle, DOWN_ANGLE-1, -1):
                        crickit.servo_1.angle = a
                        # Sparkle while moving.
                        sparkle()
                        time.sleep(DELAY)
                    angle = DOWN_ANGLE

How the Program Works

The first part of the program sets up a UARTServer, which is a BLE service that wirelessly sends streams of characters between a BLE device and a client computer (which could be a phone or tablet). The program then starts advertising its UART service to anyone listening. The client computer receives the advertisement, and tells the user it's available. The user can then choose to connect as a client of the service.

One a connection is established, the program code waits for incoming command packets from the client, specifically either a ColorPacket or a ButtonPacket. When one arrives, the program either adjusts the NeoPixel color, or sees which button has been pressed: up-arrow or down-arrow. If it's a button press, the code moves the servo one degree at a time in the specified direction, until it hits a limit. During the servo movement, the code continues to call sparkle() so that the "fire" animation will not stop.

This guide was first published on Jan 30, 2019. It was last updated on Jan 30, 2019. This page (CircuitPython Code) was last updated on Sep 15, 2019.