/ Glowing_Bottle_Castle / code.py
code.py
1 # SPDX-FileCopyrightText: 2020 Erin St Blaine for Adafruit Industries 2 # SPDX-FileCopyrightText: 2020 Limor Fried for Adafruit Industries 3 # 4 # SPDX-License-Identifier: MIT 5 6 """ 7 Bottle Piano with Capacitive Touch 8 Adafruit invests time and resources providing this open source code. 9 Please support Adafruit and open source hardware by purchasing 10 products from Adafruit! 11 Written by Melissa LeBlanc, Erin St Blaine & Limor Fried for Adafruit Industries 12 Copyright (c) 2019-2020 Adafruit Industries 13 Licensed under the MIT license. 14 All text above must be included in any redistribution. 15 """ 16 17 import time 18 import digitalio 19 import board 20 import neopixel 21 import busio 22 import adafruit_mpr121 23 from audiocore import WaveFile 24 from audiopwmio import PWMAudioOut as AudioOut 25 from adafruit_led_animation.animation.rainbow import Rainbow 26 from adafruit_led_animation.animation.rainbowchase import RainbowChase 27 from adafruit_led_animation.animation.chase import Chase 28 from adafruit_led_animation.animation.rainbowcomet import RainbowComet 29 from adafruit_led_animation.sequence import AnimationSequence 30 from adafruit_led_animation.color import ( 31 BLACK, 32 RED, 33 ORANGE, 34 YELLOW, 35 GREEN, 36 BLUE, 37 MAGENTA, 38 PURPLE, 39 AMBER, 40 TEAL, 41 ) 42 from adafruit_debouncer import Debouncer 43 44 # pylint: disable=global-statement 45 46 # NeoPixel strip setup -- set your total number of pixels here ----------------- 47 PIXEL_NUM = 200 48 pixel_pin = board.A1 49 pixels = neopixel.NeoPixel(pixel_pin, PIXEL_NUM, brightness=1, auto_write=False) 50 LAST_BUTTON = None 51 52 ''' 53 Customize your light strip for individual notes. Each line represents a bottle. 54 Change the numbers to reflect the first and last pixel in each ring. You can also 55 change the colors assigned to each bottle here. 56 ''' 57 58 bottle_lights = ( 59 (0, 10, RED), 60 (15, 30, ORANGE), 61 (31, 52, AMBER), 62 (53, 72, YELLOW), 63 (77, 96, GREEN), 64 (98, 119, TEAL), 65 (120, 145, BLUE), 66 (150, 173, PURPLE), 67 (180, 200, MAGENTA), 68 ) 69 70 # Cap touch board setup ------------------------------------------------------ 71 i2c = busio.I2C(board.SCL, board.SDA) 72 mpr121 = adafruit_mpr121.MPR121(i2c) 73 74 # Demo MODE LED Animations ------------------------------------------------------ 75 rainbow = Rainbow(pixels, speed=0, period=10, name="rainbow", step=1) 76 rainbow_chase = RainbowChase(pixels, speed=0, size=5, spacing=10) 77 chase = Chase(pixels, speed=0.1, color=RED, size=1, spacing=6) 78 rainbow_comet = RainbowComet(pixels, speed=0.01, tail_length=60, bounce=True) 79 80 # Animation Sequence Playlist -- rearrange to change the order of animations 81 82 animations = AnimationSequence( 83 rainbow_chase, 84 chase, 85 rainbow_comet, 86 auto_clear=True, 87 auto_reset=True, 88 ) 89 90 def go_dark(): 91 '''set all pixels to black''' 92 pixels.fill(BLACK) 93 pixels.show() 94 95 96 # Debouncer ------------------------------------------------------ 97 98 buttons = [Debouncer(mpr121[i]) for i in range(12)] 99 100 101 # Audio Setup ------------------------------------------------------ 102 103 spkr_enable = digitalio.DigitalInOut(board.SPEAKER_ENABLE) 104 spkr_enable.direction = digitalio.Direction.OUTPUT 105 spkr_enable.value = True 106 107 audio = AudioOut(board.SPEAKER) 108 109 tracks = ( 110 WaveFile(open("sounds/F2.wav", "rb")), # 0 111 WaveFile(open("sounds/G2.wav", "rb")), # 1 112 WaveFile(open("sounds/A2.wav", "rb")), # 2 113 WaveFile(open("sounds/Bb2.wav", "rb")), # 3 114 WaveFile(open("sounds/C2.wav", "rb")), # 4 115 WaveFile(open("sounds/D3.wav", "rb")), # 5 116 WaveFile(open("sounds/E3.wav", "rb")), # 6 117 WaveFile(open("sounds/F3.wav", "rb")), # 7 118 WaveFile(open("sounds/F1.wav", "rb")), # 7 119 WaveFile(open("sounds/G1.wav", "rb")), # 8 120 WaveFile(open("sounds/A1.wav", "rb")), # 9 121 WaveFile(open("sounds/Bb1.wav", "rb")), # 10 122 WaveFile(open("sounds/C1.wav", "rb")), # 11 123 WaveFile(open("sounds/D2.wav", "rb")), # 12 124 WaveFile(open("sounds/E2.wav", "rb")), # 13 125 WaveFile(open("sounds/F2.wav", "rb")), # 13 126 ) 127 128 # Add or change song track names here. They will play in the order listed. 129 demo_tracks = ( 130 WaveFile(open("sounds/undersea.wav", "rb")), 131 WaveFile(open("sounds/tequila.wav", "rb")), 132 WaveFile(open("sounds/lion.wav", "rb")), 133 ) 134 135 MODE = 0 # Initial mode = OFF 136 SONG = 0 137 138 139 140 141 def light_up(bottle): 142 '''light up the bottles''' 143 lights = bottle_lights[bottle] 144 for pixel_id in range(lights[0], lights[1]): 145 pixels[pixel_id] = lights[2] 146 147 148 def play_bottle(bottle_id, is_octave): 149 ''' play audio tracks and light up bottles''' 150 global MODE 151 go_dark() 152 light_up(bottle_id) 153 if is_octave: 154 audio.play(tracks[bottle_id + 7]) # Start playing sound 155 light_up(8) 156 else: 157 audio.play(tracks[bottle_id]) # Start playing sound 158 pixels.show() 159 MODE = 2 160 161 162 def check_buttons(touched): 163 ''' check to see if buttons have been pressed''' 164 global MODE, LAST_BUTTON 165 octave = touched[11] 166 off = touched[9] 167 if octave: 168 light_up(8) 169 for pad in range(1, 9): 170 if LAST_BUTTON is not None and not touched[LAST_BUTTON]: 171 LAST_BUTTON = None 172 if pad != LAST_BUTTON and touched[pad]: 173 LAST_BUTTON = pad 174 play_bottle(pad - 1, octave) 175 if off: 176 MODE = 9 177 go_dark() 178 if touched[10]: 179 go_dark() 180 audio.play(demo_tracks[SONG]) 181 while audio.playing: 182 animations.animate() 183 184 MODE = 3 185 186 187 while True: 188 # Idle mode: Play a Rainbow animation when nothing's being touched 189 if MODE == 0: 190 pixels.brightness = 0.3 #rainbow mode is much brighter than the other modes, so adjust here 191 rainbow.animate() 192 for button in buttons: 193 button.update() 194 check_buttons(mpr121.touched_pins) 195 time.sleep(0.1) 196 for i in range(12): 197 if buttons[i].fell: 198 MODE = 1 199 # If not idle mode 200 if MODE >= 1: 201 pixels.brightness = 1 202 check_buttons(mpr121.touched_pins) 203 time.sleep(0.1) 204 if MODE == 2: # mode 2 is individual notes 205 if audio.playing: 206 pixels.show() 207 while audio.playing: 208 check_buttons(mpr121.touched_pins) 209 time.sleep(0.07) 210 else: 211 MODE = 0 # Return to idle mode 212 if MODE == 3: 213 SONG = SONG + 1 214 animations.next() 215 if SONG == 3: 216 MODE = 0 217 SONG = 0 218 219 else: 220 MODE = 0 # Return to idle mode 221 if MODE == 9: # MODE 9 is "off" mode, listening for a new button press to wake up. 222 # for button in buttons: 223 # button.update() 224 for i in range(12): 225 if buttons[i].fell: 226 MODE = 1