|
| 1 | +# SPDX-FileCopyrightText: 2017 John Park for Adafruit Industries |
| 2 | +# Modified 2023 by Erin St Blaine |
| 3 | +# |
| 4 | +# SPDX-License-Identifier: MIT |
| 5 | + |
| 6 | + |
| 7 | +import board |
| 8 | +import pulseio |
| 9 | +import neopixel |
| 10 | +import adafruit_irremote |
| 11 | +from rainbowio import colorwheel |
| 12 | +from adafruit_led_animation.sequence import AnimationSequence |
| 13 | +from adafruit_led_animation.animation.solid import Solid |
| 14 | +from adafruit_led_animation.animation.rainbow import Rainbow |
| 15 | +from adafruit_led_animation.animation.sparkle import Sparkle |
| 16 | +from adafruit_led_animation.animation.rainbowchase import RainbowChase |
| 17 | +from adafruit_led_animation.animation.rainbowcomet import RainbowComet |
| 18 | +from adafruit_led_animation.animation.chase import Chase |
| 19 | +from adafruit_led_animation.animation.comet import Comet |
| 20 | +from adafruit_led_animation.animation.pulse import Pulse |
| 21 | +from adafruit_led_animation.animation.SparklePulse import SparklePulse |
| 22 | +import adafruit_led_animation.color as color |
| 23 | + |
| 24 | +NUMBER_OF_PIXELS = 85 |
| 25 | +pixels = neopixel.NeoPixel(board.D13, NUMBER_OF_PIXELS) |
| 26 | + |
| 27 | +# Define the brightness levels and their corresponding values |
| 28 | +# Start at a non-blinding brightness. |
| 29 | +BRIGHTNESS_LEVELS = (0.025, 0.05, 0.1, 0.2, 0.4, 0.6, 0.7, 0.8, 1.0) |
| 30 | +brightness_index = 2 |
| 31 | +pixels.brightness = BRIGHTNESS_LEVELS[brightness_index] |
| 32 | + |
| 33 | +pulsein = pulseio.PulseIn(board.A0, maxlen=120, idle_state=True) |
| 34 | +decoder = adafruit_irremote.GenericDecode() |
| 35 | + |
| 36 | +SPEEDS = (0.25, 0.125, 0.1, 0.08, 0.05, 0.02, 0.01) # Customize speed levels here |
| 37 | +speed_index = 4 |
| 38 | + |
| 39 | +def setup_animations(): |
| 40 | + """Set up all the available animations.""" |
| 41 | + # Animation Setup |
| 42 | + rainbow = Rainbow(pixels, speed=SPEEDS[speed_index], period=2, name="rainbow", step=3) |
| 43 | + sparkle = Sparkle(pixels, speed=SPEEDS[speed_index], color=color.WHITE, name="sparkle") |
| 44 | + solid = Solid(pixels, color=colorwheel(0), name="solid") |
| 45 | + # Make the Solid animation changeable quickly. |
| 46 | + solid.speed = 0.01 |
| 47 | + off = Solid(pixels, color=color.BLACK, name="off") |
| 48 | + rainbow = Rainbow(pixels, speed=SPEEDS[speed_index], period=6, name="rainbow", step=2.4) |
| 49 | + rainbow_carousel = RainbowChase(pixels, speed=SPEEDS[speed_index], size=4, spacing=1, step=20) |
| 50 | + party_chase = RainbowChase(pixels, speed=SPEEDS[speed_index], size=1, spacing=5, step=6) |
| 51 | + rainbow_chase2 = RainbowChase(pixels, speed=SPEEDS[speed_index], size=10, spacing=1, step=18) |
| 52 | + chase = Chase(pixels, speed=SPEEDS[speed_index], color=color.RED, size=1, spacing=6) |
| 53 | + rainbow_comet2 = RainbowComet( |
| 54 | + pixels, speed=0.02, tail_length=104, colorwheel_offset=80, bounce=False) |
| 55 | + rainbow_comet3 = RainbowComet( |
| 56 | + pixels, speed=SPEEDS[speed_index], tail_length=25, |
| 57 | + colorwheel_offset=128, step=4, bounce=False) |
| 58 | + lava = Comet(pixels, speed=SPEEDS[speed_index], |
| 59 | + color=color.ORANGE, tail_length=40, bounce=False) |
| 60 | + sparkle1 = Sparkle(pixels, speed=SPEEDS[speed_index], color=color.BLUE, num_sparkles=10) |
| 61 | + pulse = Pulse(pixels, speed=0.1, color=color.AMBER, period=3) |
| 62 | + sparkle_pulse = SparklePulse(pixels, speed=0.05, period=2, color=color.JADE, max_intensity=3) |
| 63 | + |
| 64 | + # Animation Sequence Playlist -- rearrange to change the order of animations |
| 65 | + # advance_interval is None, so the animations change only under user control. |
| 66 | + all_animations = AnimationSequence( |
| 67 | + rainbow, |
| 68 | + rainbow_chase2, |
| 69 | + rainbow_carousel, |
| 70 | + party_chase, |
| 71 | + rainbow_comet2, |
| 72 | + rainbow_comet3, |
| 73 | + sparkle_pulse, |
| 74 | + pulse, |
| 75 | + chase, |
| 76 | + rainbow, |
| 77 | + solid, |
| 78 | + sparkle, |
| 79 | + lava, |
| 80 | + sparkle1, |
| 81 | + off, |
| 82 | + auto_clear=True, |
| 83 | + auto_reset=True, |
| 84 | + advance_interval=None, |
| 85 | + ) |
| 86 | + return all_animations |
| 87 | + |
| 88 | +# IR Remote Mapping for the Adafruit mini IR remote |
| 89 | +# https://www.adafruit.com/product/389 |
| 90 | + |
| 91 | +CMD_1 = 247 # 1: [255, 2, 247, 8] |
| 92 | +CMD_2 = 119 # 2: [255, 2, 119, 136] |
| 93 | +CMD_3 = 183 # 3: [255, 2, 183, 72] |
| 94 | +CMD_4 = 215 # 4: [255, 2, 215, 40] |
| 95 | +CMD_5 = 87 # 5: [255, 2, 87, 168] |
| 96 | +CMD_6 = 151 # 6: [255, 2, 151, 104] |
| 97 | +CMD_7 = 231 # 7: [255, 2, 231, 24] |
| 98 | +CMD_8 = 103 # 8: [255, 2, 103, 152] |
| 99 | +CMD_9 = 167 # 9: [255, 2, 167, 88] |
| 100 | +CMD_0 = 207 # 0: [255, 2, 207, 48] |
| 101 | + |
| 102 | +CMD_UP = 95 # ^ : [255, 2, 95, 160] |
| 103 | +CMD_DOWN = 79 # v : [255, 2, 79, 176] |
| 104 | +CMD_RIGHT = 175 # > : [255, 2, 175, 80] |
| 105 | +CMD_LEFT = 239 # < : [255, 2, 239, 16] |
| 106 | + |
| 107 | +CMD_ENTER_SAVE = 111 # Enter/Save: [255, 2, 111, 144] |
| 108 | +CMD_SETUP = 223 # Setup: [255, 2, 223, 32] |
| 109 | +CMD_STOP_MODE = 159 # Stop/Mode: [255, 2, 159, 96] |
| 110 | +CMD_BACK = 143 # Back: [255, 2, 143, 112] |
| 111 | + |
| 112 | +CMD_VOL_DOWN = 255 # Vol - : [255, 2, 255, 0] |
| 113 | +CMD_VOL_UP = 191 # Vol + : [255, 2, 191, 64] |
| 114 | +CMD_PLAY_PAUSE = 127 # Play/Pause: [255, 2, 127, 128] |
| 115 | +CMD_REPEAT = True # short code: repeat of previous command |
| 116 | + |
| 117 | + |
| 118 | +def read_command(): |
| 119 | + """Try to read an IR command. If none seen or if error, return None.""" |
| 120 | + try: |
| 121 | + pulses = decoder.read_pulses(pulsein, blocking=False) |
| 122 | + if pulses: |
| 123 | + code = decoder.decode_bits(pulses) |
| 124 | + if len(code) > 3: |
| 125 | + print("Decoded:", code) |
| 126 | + return code[2] |
| 127 | + # if code is less than or equal to 3 characters long or no pulses received |
| 128 | + return None |
| 129 | + except adafruit_irremote.IRNECRepeatException: # unusual short code! |
| 130 | + print("NEC repeat!") |
| 131 | + return CMD_REPEAT |
| 132 | + except adafruit_irremote.IRDecodeException as e: # failed to decode |
| 133 | + print("Failed to decode:", e) |
| 134 | + return None |
| 135 | + except MemoryError as e: |
| 136 | + print("Memory error: ", e) |
| 137 | + return None |
| 138 | + |
| 139 | +SOLID_COLORS = { |
| 140 | + CMD_0 : color.BLACK, |
| 141 | + CMD_1 : color.RED, |
| 142 | + CMD_2 : color.GREEN, |
| 143 | + CMD_3 : color.WHITE, |
| 144 | + CMD_4 : color.BLUE, |
| 145 | + CMD_5 : color.PINK, |
| 146 | + CMD_6 : color.YELLOW, |
| 147 | + CMD_7 : color.PURPLE, |
| 148 | + CMD_8 : color.TEAL, |
| 149 | + CMD_9 : color.ORANGE, |
| 150 | + } |
| 151 | + |
| 152 | +# main program |
| 153 | + |
| 154 | +animations = setup_animations() |
| 155 | +last_command = None |
| 156 | + |
| 157 | +while True: |
| 158 | + command = read_command() |
| 159 | + if command is None: |
| 160 | + # Nothing read, just keep animating. |
| 161 | + animations.animate() # Run one animation cycle. |
| 162 | + continue |
| 163 | + |
| 164 | + if command == CMD_REPEAT: |
| 165 | + command = last_command |
| 166 | + |
| 167 | + last_command = command |
| 168 | + print("Command", command) |
| 169 | + |
| 170 | + |
| 171 | + # See if the command was a number button. Fetch the animation color if it is. |
| 172 | + solid_color = SOLID_COLORS.get(command, None) |
| 173 | + if solid_color: |
| 174 | + # Jump to the "solid" animation. Set its color to |
| 175 | + # the chosen color. |
| 176 | + animations.activate("solid") |
| 177 | + animations.current_animation.color = solid_color |
| 178 | + elif command == CMD_LEFT: |
| 179 | + animations.previous() |
| 180 | + elif command == CMD_RIGHT: |
| 181 | + animations.next() |
| 182 | + elif command == CMD_DOWN: |
| 183 | + # Slow down current animation |
| 184 | + if speed_index > 0: |
| 185 | + speed_index -= 1 |
| 186 | + animations.current_animation.speed = SPEEDS[speed_index] |
| 187 | + print("speed of current animation is now:", animations.current_animation.speed) |
| 188 | + elif command == CMD_UP: |
| 189 | + if speed_index < len(SPEEDS) - 1: |
| 190 | + speed_index += 1 |
| 191 | + animations.current_animation.speed = SPEEDS[speed_index] |
| 192 | + print("speed of current animation is now:", animations.current_animation.speed) |
| 193 | + elif command == CMD_VOL_DOWN: |
| 194 | + if brightness_index > 0: |
| 195 | + brightness_index -= 1 |
| 196 | + pixels.brightness = BRIGHTNESS_LEVELS[brightness_index] |
| 197 | + print("brightness:", pixels.brightness) |
| 198 | + elif command == CMD_VOL_UP: |
| 199 | + if brightness_index < len(BRIGHTNESS_LEVELS) - 1: |
| 200 | + brightness_index += 1 |
| 201 | + pixels.brightness = BRIGHTNESS_LEVELS[brightness_index] |
| 202 | + print("brightness:", pixels.brightness) |
0 commit comments