Wings of Fire- an Interactive Dragon Display
by carbonmk in Circuits > Raspberry Pi
265 Views, 1 Favorites, 0 Comments
Wings of Fire- an Interactive Dragon Display
This is a project to give to the Campus School students at Boston College. They are students with severe disabilities, so we must make sure that the project is durable and easy to see for the students. After speaking with the technology specialist, we wanted to make a "Wings of Fire" kind of display for the students since they enjoy that series of books.
When one of the pads is pressed, a random dragon sound will play and the servos will start to swing in opposite directions. This makes it look like whatever you place on the servos are fighting. We placed dragons on the servos in the spirit of the "Wings of Fire" series. If the other pad is pressed, then
Supplies
Electronics:
Pico W
LED Strip
Adafruit mpr121
2 Servo motors (180 degree range)
A speaker that has an audio plug
2 Alligator-to-pin clips
2 Alligator-to-Alligator clips
15 Pin-to-pin wires
Stemma QT plug with pins on the end
An Adafruit microSD SPI reader (pins already soldered on).
An SD card (32 gigabytes or less)
A USB cable (to power the microcontroller)
1 Battery pack
Other materials:
Some sort of display box, here we attempted to make a castle out of wood
Action figures/decorations
Adhesive
Copper Tape
Copper Wire
Wire the Pico to the Speaker
1- Take one of the alligator to pin clips and connect the pin to any ground on the Pico.
2- Connect the alligator clip to the base of the audio jack cable.
3- Take the other alligator to pin clips and connect the pin to GP16 (or your preferred pin) on the Pico.
4- Connect the alligator clip to the tip of the audio jack cable.
5- If applicable, make sure to turn on the speaker.
The speaker will play the audio files you selected for your theme, here we have a selection of dragon sounds.
Wire the Pico to the Micro SD Card Reader
1- Using the SD card reader for your computer, make a new folder on the SD card and load any sounds you want into that folder. Make sure to remember the name of the folder as this will be the path for your sounds in the code.
2- If applicable, make sure to solder the pins onto your Adafruit SD card reader.
3- Take a pin-to-pin wire and connect it to 3.3 Volts on the Pico W and the 3V slot on the SD Card reader.
4- Using another pin-to-pin wire, connect it to any ground on the Pico W and the ground slot on the SD card reader.
5- Connect a pin-to-pin wire to GP10, which is SCK, to CLK slot on the SD Card reader.
6- Connect a pin-to-pin wire to GP11, which is SI or TX, to the “DO SO” slot on the SD card reader.
7- Connect a pin-to-pin wire to GP12, which is SO or RX, to the “CMD SI” slot on the SD card reader.
8- Connect a pin-to-pin wire to GP13, which is CS, to the “DE CS” slot on the SD card reader.
9- Finally, insert the SD card into the slot, you will hear a click when the SD Card is properly inserted.
The SD card reader will allow you to play large sound files since there is very little space on the Pico W.
Wire the Pico to the Adafruit MPR121
1- Plug the Stemma QT side of the Stemma QT-to-pins wire into the mpr121.
2- The yellow wire is SCL which is connected to GP5 on the Pico.
3- The blue wire is SDA and is connected to GP4 on the Pico.
4- The red wire is power which is connected to 3.3 Volts out, not VBUS!
5- The black wire is ground which is connected to any ground on the Pico W.
This will be used for capacitive touch later when assembling the entire box.
Wire the Pico to the Servos
1- Connect a pin-to-pin wire to the red wire on the servo then connect that to VBUS.
2- Connect a pin-to-pin wire to the brown wire on the servo then connect that to any ground
3- Connect a pin-to-pin wire to the orange wire on the servo then connect that to GP14 then the other on GP15 (or any other signal pin you wish).
The servos will be used to move our action figures to make them appear they are fighting.
Wire the Pico to the LED Strip
1- Take the LED strip white alligator clip, and connect it to a pin-to-pin wire. Then connect that pin-to-pin wire to GP16
2- Connect the red alligator clip to a pin-to-pin wire. Then connect that pin-to-pin wire to VBUS.
3- Connect the black alligator clip to a pin-to-pin wire. Then connect that pin-to-pin wire to any ground.
The LED strip will be used to make it look like our dragon decorative piece is breathing fire.
Assembling the Castle
1- Assemble the parts you will be using to build your housing. We used laser cut wood and glued them together to make a castle.
2- (optional) Place your decorations
3- Put the electronics in its holding spot as we prepare to place the rest of the electronics.
4- Place a servo in each position and make sure they swing in opposite directions (to give the appearance of characters fighting when we assemble that)
5- Connect some sort of arbitrary platform (we used pieces of popsicle sticks) to the servos then add your characters.
6- Using the copper tape, place it over one of the front panels of the castle.
7- From the inside, connect the copper tape with either a pin-to-pin wire or copper wire. At the other end of the wire, wrap it around the corresponding touchpad on the mpr121 (or use alligator-to-alligator clips and clamp one end to the mpr121 and the other end to the wire connected to the copper tape).
8- Finally, connect the end of the LED Strip to the dragons mouth and wrap it around the castle.
The Code
I have attached the code below in a file for easy download, but here is the code also if you would rather just read it:
import neopixel, board, time, random, mount_sd, pwmio
from adafruit_motor import servo
from audiomp3 import MP3Decoder
from audiopwmio import PWMAudioOut as AudioOut
import adafruit_mpr121
from adafruit_debouncer import Button
from audiocore import WaveFile
#Set up audio
audio = AudioOut(board.GP16)
#set up LEDs and colors
fire_strip = neopixel.NeoPixel(board.GP17, 30, brightness = 1, auto_write=True)
winner_strip = neopixel.NeoPixel(board.GP18, 20, brightness = 1, auto_write=True)
from adafruit_led_animation.color import (
AMBER, #(255, 100, 0)
AQUA, # (50, 255, 255)
BLACK, #OFF (0, 0, 0)
BLUE, # (0, 0, 255)
CYAN, # (0, 255, 255)
GOLD, # (255, 222, 30)
GREEN, # (0, 255, 0)
JADE, # (0, 255, 40)
MAGENTA, #(255, 0, 20)
OLD_LACE, # (253, 245, 230)
ORANGE, # (255, 40, 0)
PINK, # (242, 90, 255)
PURPLE, # (180, 0, 255)
RED, # (255, 0, 0)
TEAL, # (0, 255, 120)
WHITE, # (255, 255, 255)
YELLOW, # (255, 150, 0)
RAINBOW # a list of colors to cycle through
# RAINBOW is RED, ORANGE, YELLOW, GREEN, BLUE, and PURPLE ((255, 0, 0), (255, 40, 0), (255, 150, 0), (0, 255, 0), (0, 0, 255), (180, 0, 255))
)
INDIGO = (63, 0, 255)
VIOLET = (127, 0, 255)
# We often use these colors, but be sure to check colors used when taking exams
colors = [RED, MAGENTA, ORANGE, YELLOW, GREEN, JADE, TEAL, BLUE, INDIGO, VIOLET, PURPLE, WHITE]
winner_color = [BLUE, GREEN]
def breath_fire():
for i in reversed(range(30)):
fire_strip[i]=ORANGE
time.sleep(.02)
for i in range(5):
fire_strip.fill(RED)
time.sleep(.05)
fire_strip.fill(YELLOW)
time.sleep(.05)
fire_strip.fill(BLACK)
time.sleep(.1)
def breath_blue_fire():
for i in reversed(range(30)):
fire_strip[i]=BLUE
time.sleep(.02)
for i in range(5):
fire_strip.fill(PURPLE)
time.sleep(.05)
fire_strip.fill(WHITE)
time.sleep(.05)
fire_strip.fill(BLACK)
time.sleep(.1)
fire_strip.fill(BLACK)
def flash_winner_strip():
random_color = random.choice(winner_color)
for _ in range(8):
winner_strip.fill(random_color)
time.sleep(0.1)
winner_strip.fill(BLACK)
time.sleep(0.1)
winner_strip.fill(WHITE)
winner_strip.fill(WHITE)
#set up i2c object
i2c = board.STEMMA_I2C()
touch_pad = adafruit_mpr121.MPR121(i2c)
pwm1 = pwmio.PWMOut(board.GP14, frequency=50)
servo_1 = servo.Servo(pwm1, min_pulse = 750, max_pulse = 2500)
pwm2 = pwmio.PWMOut(board.GP15, frequency=50)
servo_2 = servo.Servo(pwm2, min_pulse = 750, max_pulse = 2500)
# Example usage
start_angle = 0
end_angle = 180
step = 5
delay = 0.01 # Adjust this value to control the movement speed
def move_servos_face_to_face(servo1, servo2, start_angle, end_angle, step, delay):
# Move servos from start_angle to end_angle in steps of step degrees
for angle in range(start_angle, end_angle + 1, step):
servo1.angle = angle
servo2.angle = end_angle - angle + start_angle
time.sleep(delay)
# Move servos back to start_angle in steps of step degrees
for angle in range(end_angle, start_angle - 1, -step):
servo1.angle = angle
servo2.angle = end_angle - angle + start_angle
time.sleep(delay)
path = "/sd/dragonSounds/"
is_playing = False
sounds1 = ["dragon-growl.wav", "dragon-howl.wav", "dragon-roar.wav", "fire-breath.wav"]
sounds2 = ["dragon-growl.wav", "dragon-howl.wav", "dragon-roar.wav"]
def play_sound1(filename):
with open(path + filename, "rb") as wave_file:
wave = WaveFile(wave_file)
audio.play(wave)
while audio.playing:
move_servos_face_to_face(servo_1, servo_2, start_angle, end_angle, step, delay)
servo_1.angle = start_angle
servo_2.angle = start_angle
def play_sound2(filename):
with open(path + filename, "rb") as wave_file:
wave = WaveFile(wave_file)
audio.play(wave)
while audio.playing:
breath_fire()
def play_sound3(filename):
with open(path + filename, "rb") as wave_file:
wave = WaveFile(wave_file)
audio.play(wave)
while audio.playing:
breath_blue_fire()
while True:
if touch_pad[0].value:
print("TOUCHBAD 0 PRESSED")
random_sound1 = random.choice(sounds2)
play_sound1(random_sound1)
flash_winner_strip()
if touch_pad[5].value:
print("TOUCHBAD 5 PRESSED")
random_sound2 = random.choice(sounds1)
play_sound2(random_sound2)
if touch_pad[6].value:
print("TOUCHBAD 6 PRESSED")
random_sound3 = random.choice(sounds1)
play_sound3(random_sound3)