Now we're going to take a look at the code behind our LED trampoline light show!
Copy the following file to your Itsy Bitsy CIRCUITPY drive, and rename it to code.py. Or copy and paste it into your current code.py, replacing its current contents. Save your file, and you're ready to go!
# SPDX-FileCopyrightText: 2018 Kattni Rembor for Adafruit Industries # # SPDX-License-Identifier: MIT import random import time import board import digitalio import neopixel pixel_pin = board.D10 # The pin the NeoPixels are connected to button_switch_pin = board.D9 # Pin button is attached to vibration_switch_pin = board.D7 # Pin vibration switch is attached to. pixel_count = 40 # Number of pixels in your strip chase_color_duration = 3 # Seconds each color lasts in the color chase mode pixels = neopixel.NeoPixel(pixel_pin, pixel_count, brightness=.4, auto_write=False) button_switch = digitalio.DigitalInOut(button_switch_pin) button_switch.direction = digitalio.Direction.INPUT button_switch.pull = digitalio.Pull.UP vibration_switch = digitalio.DigitalInOut(vibration_switch_pin) vibration_switch.direction = digitalio.Direction.INPUT vibration_switch.pull = digitalio.Pull.UP led = digitalio.DigitalInOut(board.D13) led.direction = digitalio.Direction.OUTPUT # Colors: RED = (255, 0, 0) YELLOW = (255, 150, 0) ORANGE = (255, 40, 0) GREEN = (0, 255, 0) TEAL = (0, 255, 120) CYAN = (0, 255, 255) BLUE = (0, 0, 255) PURPLE = (180, 0, 255) MAGENTA = (255, 0, 20) WHITE = (255, 255, 255) # Sparkle colors: GOLD = (255, 222, 30) PINK = (242, 90, 255) AQUA = (50, 255, 255) JADE = (0, 255, 40) AMBER = (255, 100, 0) def cycle_sequence(seq): while True: yield from seq def fade_control(): brightness_value = iter([r / 15 for r in range(15, -1, -1)]) while True: # pylint: disable=stop-iteration-return pixels.brightness = next(brightness_value) pixels.show() yield def sparkle_code(color_values): (red_value, green_value, blue_value) = color_values p = random.randint(0, (pixel_count - 2)) pixels[p] = (red_value, green_value, blue_value) pixels.show() pixels[p] = (red_value // 2, green_value // 2, blue_value // 2) pixels.show() pixels[p + 1] = (red_value // 10, green_value // 10, blue_value // 10) pixels.show() fade = fade_control() flash_color = cycle_sequence([RED, YELLOW, ORANGE, GREEN, TEAL, CYAN, BLUE, PURPLE, MAGENTA, WHITE]) sparkle_color_list = (MAGENTA, PINK, GOLD, AQUA, JADE, AMBER) sparkle_color_index = 0 chase_color_list = (RED, ORANGE, YELLOW, GREEN, BLUE, PURPLE) chase_color_index = 0 chase_color_cycle = chase_color_list[chase_color_index] offset = 0 chase_last_color = time.monotonic() chase_next_color = chase_last_color + chase_color_duration button_state = None mode = 0 print("Mode:", mode) initial_time = time.monotonic() while True: try: now = time.monotonic() if not button_switch.value and button_state is None: button_state = "pressed" if button_switch.value and button_state == "pressed": print("Mode Change") led.value = True pixels.fill((0, 0, 0)) mode += 1 button_state = None if mode > 2: mode = 0 print("Mode:,", mode) else: led.value = False if mode == 0: try: if not vibration_switch.value: print("Flash and fade mode activate!") fade = fade_control() pixels.fill(next(flash_color)) pixels.show() next(fade) except StopIteration: pass if mode == 1 and not vibration_switch.value: print("Sparkle mode activate!") pixels.brightness = 1 sparkle_color_index = (sparkle_color_index + 1) \ % len(sparkle_color_list) sparkle_code(sparkle_color_list[sparkle_color_index]) if mode == 2 and not vibration_switch.value: print("Chase mode activate!") pixels.brightness = 1 for i in range(0, pixel_count): c = 0 if ((offset + i) % 8) < 4: c = chase_color_cycle pixels[i] = c pixels[(pixel_count - 1) - i] = c pixels.show() offset += 1 if now >= chase_next_color: chase_color_index = (chase_color_index + 1) % len(chase_color_list) chase_color_cycle = chase_color_list[chase_color_index] pixels.fill((0, 0, 0)) chase_last_color = now chase_next_color = chase_last_color + chase_color_duration except MemoryError: pass
Setup
The first thing we do after importing the libraries we'll be using is set up the pins so our code knows where to look for the switches and LEDs.
Then we set the pixel_count = 40
. This project uses 80 pixels total. However, there were hardware limitations with running 80 pixels. So, we've cut the strip into two, and attached the two strips of 40 to the same pin. Since they're attached to the same pin, the code doesn't know the difference and sends the same data to both strips. That's why the total is set to 40!
We also set the chase_color_duration = 3
which determines how long in seconds each color lasts in the color chase mode. You can change this number if you'd like your colors to last a longer or shorter time.
Next we setup our switches, and the red LED which we will be using as a status light for mode changes.
Next up is a list of color variables. We have a lot of color in this project! Since we reuse the colors multiple times, we've created a variable for each color so we can call it by a name instead of the (R, G, B)
color tuple.
Helper Functions
Then we have a few functions that we'll be using. cycle_sequence
is a helper function we use with generators. You can learn about how generators work in the Generate Your Colors section of the Hacking Ikea Lamps with CPX guide. In the LED Trampoline project, we're using a generator with our Flash and Fade mode. The fade takes a certain amount of time, and it's possible you could try to jump faster than the fade animation takes. In this case, the generator allows for the fade animation to be interrupted and a new color fade to begin.
We have fade_control
which is what handles our flash and fade. Each time we call it, it starts with the brightness at 100 percent and then steps down 15 times to 0. This is how the fade works!
The sparkle_code
handles the Sparkle mode. It sets a random pixel to a color and then sets one next to it to a faded version of that color. That is how we achieve a sparkle effect. This continues and once they're all full, will continue to randomly overwrite lit pixels. The sparkle code is super fast! This means that each time you jump, you'll trigger more than one sparkle at a time. It looks amazing!
We set fade = fade_control()
so we can later call fade_control
using fade
.
Next we setup the list of colors we're going to use in Flash and Fade. flash_color
uses the cycle_sequence
generator to go through the list of colors and start over endlessly. This way you can jump as long as you want on the Flash and Fade mode and the colors keep right on changing!
Color Setup
We set the colors for the Sparkle mode using sparkle_color_list
and the six special colors chosen for the Sparkle mode. They're slightly different than the main color list because these colors look especially great with the way the sparkle_code works. You can feel free to change these to any of the other colors or add more if you like!
sparkle_color_index
is used to tell the code to start with the first color on the list. Remember, in CircuitPython, counting begins with 0, so 0 represents the first color in the list!
We set the colors for the Color Chase mode using chase_color_list
and six of our color variables. You could add to this and change which colors are used if you like!
chase_color_index
is the same as the sparkle version - it tells the code to start with the first color on the list.
The next few lines setup the chase color changing. We use time.monotonic()
because we'd like to be able to set the amount of time the chase mode is a certain color, but we want the code to continue waiting in case we decide to jump or change modes. time.monotonic()
is called non-blocking, meaning the code is not stopped by it. Learn more about non-blocking code in the Passing Time section of the Hacking Ikea Lamps with CPX guide.
We set mode = 0
. This tells the code to begin with the first mode. We'll start with Flash and Fade! We print("Mode:", mode)
which is "Mode:" and the current mode, which is 0
before we start. So if you are connected to the serial console during testing, you'll see Mode: 0
.
To use time.monotonic()
, you always set a start time. That's the last thing we do before we start our main loop!
try
and except
while True:
says to run the code indented beneath it forever.
The first and last thing inside our while True:
loop, are try:
and except MemoryError: pass
. This is due to a very rare situation where the code returns a memory error and stops.
try:
says to first try running all of the code indented under the try
. If there is an error, the code moves to the except:
and completes the code underneath. In this case it will pass
which says to just keep right on going and start again with the try.
Since this project is meant to be attached to a trampoline and continue to run while you have fun jumping, we've included this try
and except
code so if it does run into that problem, it will keep going. This way you can keep on jumping even if the code runs into this problem! Otherwise, you'd have to reset the board. And what's the fun in that!
Main Loop
First, we make it so the button must be pressed and released before the code switches modes. This way you cannot accidentally skip modes by holding down the button too long.
Each time the mode is switched, it turns off the LEDs so you're starting your new mode with a clean slate. It blinks the little red LED, which can't be seen once the project is assembled, but is super handy when you're testing the project while still attached to your computer. Each time the button is pressed and released, it increases the mode by 1. Once that number is greater than 2 (remember we start counting at 0, so 2 is the third mode!) it resets to 0. This way we cycle through each of the three modes and then begin again with the first! Each time it prints
the mode to the serial output, which you can see if you're connected while testing the project on your computer.
Flash and Fade Mode
If the mode is 0, we start the Flash and Fade code. Here we have another try
and except
. This is due to the way that the flash_control
generator works. flash_control
begins at 100 percent and ends at 0, and would normally simply stop here as it has iterated through all possible values. We want it to keep going so we can jump again, flash again and fade again. So, we've included except StopIteration: pass
to keep the Flash and Fade mode moving.
Inside our try
, we have if not vibration_switch.value:
. The vibration switch defaults to "True" when not triggered, and becomes "False" when triggered. So, if we're looking to do a thing when the switch is triggered, we want to refer to when it is False
which is done by using if not
. This way, when we jump, we trigger the next set of events to happen. We print
that the mode is activated! We call fade
, we fill
the pixels with the next color from our flash_color
list, and we call pixels.show()
which tells the pixels to light up with whatever we just set. In this case, it will flash the color and fade to black. Then we call next(fade)
which tells the fade_control to start again.
Sparkle Mode
If the mode is 1 and we've triggered the vibration switch, then we start the Sparkle code. We print
the mode is activated!
When you change modes in the middle of the Flash and Fade code, the brightness stays at the level it was at the exact moment that you switched modes. This means you could switch modes when the brightness is set to 0. If that happened, you'd get no sparkles at all! That's no good. So, we set pixel.brightness = 1
to set it back to 100%, so you get all the sparkle goodness regardless of where the brightness was when you switched.
The next line tells the sparkle code that sparkle_color_list
should cycle through all the colors. And the last line says run the sparkle code repeatedly, cycling through the list of colors as you jump, and to keep doing this until you change modes!
Color Chase Mode
If the mode is 2 and we've triggered the vibration switch, we start the Color Chase code. We print
the mode is activated! And, for the same reason as in Sparkle mode, we set the brightness to 100%.
The next bit is the core of the Chase mode. This is the chase code. This tells the strips to light up every 4 LEDs with 4 off between. Then it says, each time the switch is triggered, move the groups of lit LEDs towards the middle. In our case, since we've split our LED strips into 2, the chase will happen in two parts, one on each half, moving towards the middle of that half. They meet and meld in the middle!
The last section is what tells the chase code to change colors. We told it at the beginning to change colors every 3 seconds. So, every time 3 seconds passes, chase mode changes color. It forever cycles through the list of colors we provided during color setup. This happens whether or not you're jumping, because it's entirely based on time!
And that's it!
Page last edited January 22, 2025
Text editor powered by tinymce.