Once you've finished setting up your Circuit Playground Express with CircuitPython, you can access the code and necessary libraries by downloading the Project Bundle.

To do this, click on the Download Project Bundle button in the window below. It will download as a zipped folder.

# SPDX-FileCopyrightText: 2022 Liz Clark for Adafruit Industries
#
# SPDX-License-Identifier: MIT

import time
import board
import pwmio
import neopixel
from adafruit_motor import servo
from adafruit_led_animation.animation.comet import Comet
from adafruit_led_animation.sequence import AnimationSequence
from adafruit_led_animation.color import PURPLE

#  create 2 PWM instances for the servos
left_pwm = pwmio.PWMOut(board.A3, duty_cycle=2 ** 15, frequency=50)
right_pwm = pwmio.PWMOut(board.A6, duty_cycle=2 ** 15, frequency=50)

#  left wing servo
left_servo = servo.Servo(left_pwm)
#  right wing servo
right_servo = servo.Servo(right_pwm)

#  use onboard neopixels on CPX
pixel_pin = board.NEOPIXEL
#  number of onboard neopixels
num_pixels = 10

#  neopixels object
pixels = neopixel.NeoPixel(pixel_pin, num_pixels, brightness=0.05, auto_write=False)

#  comet animation
comet = Comet(pixels, speed=0.01, color=PURPLE, tail_length=10, bounce=True)

#  create animation sequence
animations = AnimationSequence(comet)

#  beginning angles for each wing
left_angle = 100
right_angle = 30
#  minimum range for the servos
min_range = 30
#  maximum range for the servos
max_range = 100
#  the change in degrees for the servos
degree_change = 10
#  it's not recommended to go faster than 0.05
speed = 0.05

while True:
	#  run comet animation while servos move
    animations.animate()

	#  left angle decreases by 10
    left_angle = left_angle - degree_change
	#  once it's less than 30 degrees, reset to 100
    if left_angle < min_range:
        left_angle = max_range
	#  right angle increases by 10
    right_angle = right_angle + degree_change
	#  once it's greater than 100, reset to 30
    if right_angle > max_range:
        right_angle = min_range
	#  move left wing
    left_servo.angle = left_angle
	#  move right wing
    right_servo.angle = right_angle
	#  delay
    time.sleep(0.05)

Upload the Code and Libraries to the Circuit Playground Express

After downloading the Project Bundle, plug your Circuit Playground Express into the computer's USB port with a known good USB data+power cable. You should see a new flash drive appear in the computer's File Explorer or Finder (depending on your operating system) called CIRCUITPY. Unzip the folder and copy the following items to the Circuit Playground Express' CIRCUITPY drive. 

  • lib folder
  • code.py

Your Circuit Playground Express CIRCUITPY drive should look like this after copying the lib folder and the code.py file.

CIRCUITPY

How the CircuitPython Code Works

The code begins by setting up two pins for the servo motors to have PWM out. Then left_servo and right_servo are created as servo objects.

#  create 2 PWM instances for the servos
left_pwm = pwmio.PWMOut(board.A3, duty_cycle=2 ** 15, frequency=50)
right_pwm = pwmio.PWMOut(board.A6, duty_cycle=2 ** 15, frequency=50)

#  left wing servo
left_servo = servo.Servo(left_pwm)
#  right wing servo
right_servo = servo.Servo(right_pwm)

The onboard NeoPixels are used for this project. The pin to access them is board.NEOPIXEL. Then, pixels is setup as the NeoPixel object.

#  use onboard neopixels on CPX
pixel_pin = board.NEOPIXEL
#  number of onboard neopixels
num_pixels = 10

#  neopixels object
pixels = neopixel.NeoPixel(pixel_pin, num_pixels, brightness=0.05, auto_write=False)

The Comet animation is setup and added to the AnimationSequence(). If you want to change the color for the animation, you would change the color property. 

#  comet animation
comet = Comet(pixels, speed=0.01, color=PURPLE, tail_length=10, bounce=True)

#  create animation sequence
animations = AnimationSequence(comet)

There are a few variables for the servo motor angles that are defined before the loop. You can change these values to customize the look of your bat's wing flapping. 

min_range and max_range define the angle range of the wings. Change these values if you want to increase or decrease the range of the motor angles between 0 and 180. degree_change is the rate of movement for the motors. If you increase this value, the motors will move more abruptly; decrease the value and the motors will move more incrementally. speed is the delay amount in the loop and as a result, determines how fast the servo motors move.

#  beginning angles for each wing
left_angle = 100
right_angle = 30
#  minimum range for the servos
min_range = 30
#  maximum range for the servos
max_range = 100
#  the change in degrees for the servos
degree_change = 10
#  it's not recommended to go faster than 0.05
speed = 0.05

In the loop, animations.animate() allows the comet NeoPixel animation to run as long as the code is running.

#  run comet animation while servos move
    animations.animate()

The servos move like mirror images of each other to imitate a wing flapping motion. As a result, the angle of the servo on the left increases while the angle of the servo on the right decreases.

The left_angle value decreases by the value of degree_change. Once its value is less than min_range, its reset to max_range.

#  left angle decreases by 10
    left_angle = left_angle - degree_change
	#  once it's less than 30 degrees, reset to 100
    if left_angle < min_range:
        left_angle = max_range

The right_angle value increases by the value of degree_change. Once its value is greater than max_range, its reset to min_range.

#  right angle increases by 10
    right_angle = right_angle + degree_change
	#  once it's greater than 100, reset to 30
    if right_angle > max_range:
        right_angle = min_range

The servos move by changing the value of their angle property.

#  move left wing
    left_servo.angle = left_angle
	#  move right wing
    right_servo.angle = right_angle
	#  delay
    time.sleep(speed)

This guide was first published on Oct 25, 2022. It was last updated on Oct 26, 2022.

This page (Code the Halloween Bat) was last updated on Mar 05, 2023.

Text editor powered by tinymce.