Setup the ItsyBitsy nRF52840 with CircuitPython


We'll need to get our board setup so we can run the CircuitPython code. Let's walk through these steps to get the latest version of CircuitPython onto your board. 

The Mu Python Editor

Mu is a simple Python editor that works with Adafruit CircuitPython hardware. It's written in Python and works on Windows, MacOS, Linux and Raspberry Pi. The serial console is built right in, so you get immediate feedback from your board's serial output! While you can use any text editor with your code, Mu makes it super simple. Instructions for Mu are available here.

Installing or upgrading CircuitPython

You should ensure you have CircuitPython 4.0 or greater on your board. Plug your board in with a known good data + power cable (not the cheesy USB cable that comes with USB power packs, they are power only). You should see a new flash drive pop up.

If the drive is CIRCUITPY, then open the boot_out.txt file to ensure the version number is 4.0 or greater. 

Adafruit CircuitPython 5.0.0-beta.3 on 2020-01-08; Adafruit ItsyBitsy nRF52840 Express with nRF52840

If you do not have CircuitPython on your board, you can add it or upgrade via this page on the ItsyBitsy guide.

Download the Adafruit CircuitPython Library Bundle

In order to run the code, we'll need to download a few libraries. Libraries contain code to help interface with hardware a lot easier for us.

Use the ItsyBitsy nRF52840 page on Installing Libraries to get the library that matches the major version of CircuitPython you are using noted above, i.e. 4.x for the versions starting with 4, 5.x for the versions starting with 5, etc.

To run the code for this project, we need the three libraries in the Required Libraries list below. Unzip the library bundle and search for the libraries. Drag and drop the files into a folder named lib on the CIRCUITPY drive (which appears when your board is plugged into your computer via a known good USB cable) if the directory is not already on the ItsyBitsy nRF52840).

Required Libraries 

  • neopixel.mpy
  • adafruit_servokit.mpy
  • adafruit_pca9685.mpy

Once we have all the files we need, a directory listing will look similar to above as far as files and directories.

Double Check

See the directory listing above and double check that you have all the files listed to make this project function. If any are missing or in an incorrect directory, move them so they're in the right places.

# SPDX-FileCopyrightText: 2021 Noe Ruiz for Adafruit Industries
# SPDX-License-Identifier: MIT

Guardian Egg Shoulder Robot with servo and NeoPixel ring

# pylint: disable=import-error
import time
import random
import board
import pwmio
import neopixel
from adafruit_motor import servo
from adafruit_led_animation.animation.comet import Comet
from adafruit_led_animation.animation.SparklePulse import SparklePulse
from adafruit_led_animation.sequence import AnimationSequence
from adafruit_led_animation.color import RED, BLUE

PIXEL_PIN = board.D5
SERVO_PIN = board.A2
ORDER = neopixel.GRB

# Initialize servo
PWM = pwmio.PWMOut(SERVO_PIN, frequency=50)
SERVO = servo.Servo(PWM)

# Initialize NeoPixels and animations
PIXELS = neopixel.NeoPixel(PIXEL_PIN, NUM_PIXELS, auto_write=False,
LARSON = Comet(PIXELS, bounce=True, speed=0.6/NUM_PIXELS,
               color=(RED[0] * BRIGHTNESS,  # This is a little faster than
                      RED[1] * BRIGHTNESS,  # using the NeoPixel brightness
                      RED[2] * BRIGHTNESS)) # setting.
SPARKLE = SparklePulse(PIXELS, period=2, speed=0.15,
                       max_intensity=BRIGHTNESS, color=BLUE)
ANIMATIONS = AnimationSequence(LARSON, SPARKLE, advance_interval=7,

MOVING = False                # Initial state = paused
START_TIME = time.monotonic() # Initial time
DURATION = 1.0                # Hold initial position for 1 sec

while True: # Loop forever...

    # Move turret -- randomly looks around and pauses
    NOW = time.monotonic()
    ELAPSED = NOW - START_TIME # Seconds since start of motion or pause
    if ELAPSED >= DURATION:    # End motion/pause?
        MOVING = not MOVING    # Toggle between those two states
        START_TIME = NOW       # and record the new starting time
        ELAPSED = 0.0
        if MOVING:             # Switching from paused to moving
            while abs(POSITION - NEXT_POSITION) < 10:  # Min +/- 10 degrees
                NEXT_POSITION = random.uniform(0, 180) # Try, try again
            DURATION = 0.2 + 0.6 * abs(POSITION - NEXT_POSITION) / 180
        else:                  # Switching from moving to paused
            SERVO.angle = NEXT_POSITION         # Move to end of sweep
            DURATION = random.uniform(0.5, 2.5) # Pause time
    if MOVING:
        FRACTION = ELAPSED / DURATION                        # Linear 0 to 1
        FRACTION = (3 * FRACTION ** 2) - (2 * FRACTION ** 3) # Ease in/out

    ANIMATIONS.animate() # Cycle through NeoPixel animations

This guide was first published on Apr 07, 2021. It was last updated on Nov 27, 2023.

This page (Code) was last updated on Nov 27, 2023.

Text editor powered by tinymce.