# Creating Custom LED Animations

## Overview

https://www.youtube.com/watch?v=1m1hOwQRY5w

The [Adafruit LED Animation Library](https://learn.adafruit.com/circuitpython-led-animations "LED Animation Learn Guide") provides a quick and easy way to get strands or arrays of RGB LEDs blinking in concert. There are several dazzling animations built into the library that are ready to use and can be adapted to different behaviors with configuration arguments. But if none of those built-in animations fits the exact vision you have for your next great project, the LED Animation library also provides a framework for you to create your own custom animations.

This will require more than just a small bit of configuration, but is well within reach if you've slightly comfortable with Python. This guide will explain what goes into making custom animations and show some examples to illustrate different aspects of them.

## Parts

Any Neopixel or DotStar compatible RGB LEDs.

### Adafruit NeoPixel LED Dots Strand - 20 LEDs at 2" Pitch

[Adafruit NeoPixel LED Dots Strand - 20 LEDs at 2" Pitch](https://www.adafruit.com/product/3630)
Attaching NeoPixel strips to your costume can be a struggle as the flexible PCBs can crack when bent too much. So how to add little dots of color? Use these stranded NeoPixel dots! They're very small, so they're easy to embed into any structure, costume, or wearable. Each dot is...

In Stock
[Buy Now](https://www.adafruit.com/product/3630)
[Related Guides to the Product](https://learn.adafruit.com/products/3630/guides)
![Adafruit NeoPixel LED Dots Strand - 20 LEDs at 2 inch Pitch](https://cdn-shop.adafruit.com/640x480/3630-02.jpg)

### Adafruit NeoPixel LED Dots Strand - 20 LED 4" Pitch

[Adafruit NeoPixel LED Dots Strand - 20 LED 4" Pitch](https://www.adafruit.com/product/3631)
Attaching NeoPixel strips to your costume can be a struggle as the flexible PCBs can crack when bent too much. So how to add little dots of color? Use these stranded NeoPixel dots! They're very small, so they're easy to embed into any structure, costume, or wearable. Each dot is...

In Stock
[Buy Now](https://www.adafruit.com/product/3631)
[Related Guides to the Product](https://learn.adafruit.com/products/3631/guides)
![Adafruit NeoPixel LED Dots Strand - 20 LEDs at 4 inch Pitch](https://cdn-shop.adafruit.com/640x480/3631-04.jpg)

### Adafruit DotStar Digital LED Strip - Black 144 LED/m - 0.5 Meter

[Adafruit DotStar Digital LED Strip - Black 144 LED/m - 0.5 Meter](https://www.adafruit.com/product/2328)
Move over NeoPixels, there's a new LED strip in town! These fancy new DotStar LED strips are a great upgrade for people who have loved and used NeoPixel strips for a few years but want something even better. DotStar LEDs use generic 2-wire SPI, so you can push data much faster than with...

Out of Stock
[Buy Now](https://www.adafruit.com/product/2328)
[Related Guides to the Product](https://learn.adafruit.com/products/2328/guides)
![Curved NeoPixel LED strip with each LED a different color](https://cdn-shop.adafruit.com/640x480/2328-06.jpg)

### NeoPixel FeatherWing - 4x8 RGB LED Add-on For All Feather Boards

[NeoPixel FeatherWing - 4x8 RGB LED Add-on For All Feather Boards](https://www.adafruit.com/product/2945)
A Feather board without ambition is a Feather board without FeatherWings! This is the&nbsp; **NeoPixel FeatherWing, a&nbsp;4x8 RGB LED Add-on For All Feather Boards**!&nbsp;Using our&nbsp;[Feather Stacking Headers](https://www.adafruit.com/products/2830)&nbsp;or&nbsp;<a...></a...>

In Stock
[Buy Now](https://www.adafruit.com/product/2945)
[Related Guides to the Product](https://learn.adafruit.com/products/2945/guides)
![Video of a NeoPixel FeatherWing lighting various colors. ](https://cdn-shop.adafruit.com/product-videos/640x480/2945-05.jpg)

# Creating Custom LED Animations

## Extend Animation Class

If you aren't already familiar with the `adafruit_led_animation` library, then you should head over to the [primary guide for that library](https://learn.adafruit.com/circuitpython-led-animations) to learn the basics about it first and practice using some of the built-in animations on your device.

Once you've done that then you can come back here and have an easier time understanding the class that we'll be working with, and how to instantiate and use it from user code in the&nbsp; **code.py** file.

## The Minimum Requirements

The main thing that we need to do in order to create our custom animations is to define a new&nbsp;class that extends `adafruit_led_animation.Animation`. In our class we'll implement a few key functions and fill in the behavior that we want for the desired blinking.

To start, create a new Python file on your **CIRCUITPY** drive, you can place it at the root of the drive or inside of the **lib** folder. Try to give at a name that describes what the animation is, hopefully something that your future self will recognize and remember the meaning of. I'll use **demo\_animation.py** , yours should be specific to your project or animation effect.

### **demo\_animation.py**
```auto
from adafruit_led_animation.animation import Animation

# class definiation named similarly to the filename,
# extend the Animation class from the library
class DemoAnimation(Animation):
	
    # init function definition called by user 
    # code to create an instance of the class
    def __init__(self, pixel_object, speed, color):
    
        # call the init function for the super class Animation,
        # pass through all of the arguments that came to us
        super().__init__(pixel_object, speed, color)
        
        # initialize any other variables you need for your
        # custom animation here
        # i.e. self.my_var = "something"
    
    # draw function will get called from animate when the time
    # comes for it based on the configured speed
    def draw(self):
        # do something with self.pixel_object
        self.pixel_object.fill(self.color)
```

That is the bare minimum required for your custom `Animation`. It won't produce anything particularly interesting or blinky, but it can be initialized and you can call `animate()` on it in order to test.

Lets break down what the different parts of this code do:

`class DemoAnimation(Animation):`&nbsp;

This line defines our class, we get to name it whatever want, I've used `DemoAnimation`, yours should try to describe your own animation effect. The `(Animation)` in parentheses means that our class will extend the `Animation` class from the `adafruit_led_animation` library. Extending that class will give us access to all of the behavior that is in the `Animation` class without us having to write it inside of our own class. We can rely on that&nbsp;`Animation` super class to provide most of what we need, we'll be able to just focus on the specific ways we want the RGB lights to turn on and off, and leave the rest up to it.

`def __init__ (self, pixel_object, speed, color):`

This starts the definition for our ` __init__ ` function which is what will be called when someone makes a new instance of our class. It accepts the same arguments as the super class `Animation`, namely `pixel_objects`, `speed`, and `color`. If we wanted to, we could add additional arguments for our specific custom animation.&nbsp;

`super(). __init__ (pixel_object, speed, color)`

This calls the ` __init__ ` function for the super class `Animation`, it will do all of the internal setup required for it to provide it's behavior. We pass through the same argument values that were passed to our class's ` __init__ ` function.

`def draw(self):`

This starts the definition for the `draw()` function. It's the place where we will put the code that controls when and how the lights turn on and off. The `Animation` super class that we are using will take care of checking how much time has passed and calling `draw()` at the appropriate times based on the `speed` configuration. Inside of `draw()` we can access `self.pixel_object` and use it to manipulate the RGB pixels.&nbsp;

### **code.py**
```auto
import board
import neopixel
from demo_animation import DemoAnimation

# Update to match the pin connected to your NeoPixels
pixel_pin = board.D10
# Update to match the number of NeoPixels you have connected
pixel_num = 32

pixels = neopixel.NeoPixel(pixel_pin, pixel_num, brightness=0.1, auto_write=False)

demo_anim = DemoAnimation(pixels, 0.5, (255, 0, 255))

while True:
	demo_anim.animate()
```

If you run this **code.py** file using the `DemoAnimation` class shown above it will simply turn all of the LEDs on to a pink color (assuming they are RGB color order). To do something more interesting we would expand upon the code inside of the `draw()` function to make it do other stuff like turning LEDs off sometimes, or setting some to a color and others to different colors, or perhaps changing the color they're showing with each successive call to `draw()`.&nbsp;There are examples on the following pages that illustrate different possibles ideas and are thoroughly commented to explain how they work.

## Optional Functionality

&nbsp;

The rest of the features of the `Animation` class are optional. Certain animations or projects might find some usage for them, but others may be able to work perfectly fine with only the pieces shown above.

### `on_cycle_complete_supported`

The cycle complete receiver is a way for user code to get a callback whenever a full cycle of the animation is complete. This allows the user code to insert some customized functionality when that time comes. For example maybe you have a project that wants to play a short audio effect each time the LED animation reaches its loop point. In order to be able to use the cycle complete receiver the specific&nbsp;`Animation` class in use must set `on_cycle_complete_supported = True`. It must also set `self.cycle_complete = True` somewhere inside of the `draw()` function at the appropriate time based on how it's cycle works. The logic used for determining when the cycle is complete is up to the specific usages within the custom `Animation`.

```auto
class DemoAnimation(Animation):
	on_cycle_complete_supported = True
    def draw(self):
    	if &lt;your cycle logic here&gt;:
    		self.cycle_complete = True
    
	# ... rest of the Animation definition ...
```

### **code.py**
```auto
def play_sound():
	print("cycle complete play the sound")
    # ... your audio code here ...

demo_anim = DemoAnimation(pixelmap_up, speed=.1, color=AMBER)
demo_anim.add_cycle_complete_receiver(play_sound)

while True:
	demo_anim.animate()
```

### `reset()`

The `reset()` function can be overridden by subclasses of `Animation` in order to insert some customized behavior that happens at the end of a full cycle of the `Animation` and before the next cycle begins. A good example of this is the built-in `Comet` animation which has an overridden `reset()` function that carries out the required behavior for it's `reverse` and `ring` features.

If your custom Animation has some behavior it needs to do when the animation loops then you need to do two things in your custom class: 1) override the `reset()` function to put your behavior inside of it, and 2) add some code into the&nbsp;`draw()` function that calls `reset()` at the appropriate time.

Info: Reset is a similar concept to the cycle complete receiver discussed above. The main difference is reset() is meant for use internally within the Animation. While the cycle complete reciever is intended for user code that is outside of our custom Animation class, but is going to make an instance of our class and call animate() on it.

```auto
class DemoAnimation(Animation):

    def __init__(self, pixel_object, speed, color,):
        super().__init__( pixel_object, speed, color)
        self.index = 0

    def reset(self):
        self.pixel_object.fill((0, 0, 0))
        self.index = 0

    def draw(self):
        if self.index &gt;= len(self.pixel_object):
            self.reset()
        self.pixel_object[self.index] = self.color
        self.index += 1
```

This example DemoAnimation uses a custom variable&nbsp;`index` to store the current index within the full strip of pixels. The overridden `reset()` function sets `index` back to zero and turns off all of the pixels. The `draw()` function calls `reset()` when the index has reached to the length of the `pixel_object`. The result is the animation will turn on one additional pixel per frame. Once all pixels are on, they will be turned off and cycle will repeat back at the beginning of the strip.

### `after_draw()`

The `after_draw()` function can be overridden by subclasses of `Animation` to insert customized behavior that will occur after each animation frame. For example the built-in `Sparkle` animation overrides the `after_draw()` function to set some of the pixels to a dimmer color in order to create the sparkling visual effect. `after_draw()` will get called automatically at the conclusion of the `draw()` function, you do not need to manually call it yourself inside `draw()` or anywhere else.

```auto
class DemoAnimation(Animation):

    def __init__(self, pixel_object, speed, color,):
        super().__init__( pixel_object, speed, color)
        self.drawn_pixels = []

    def draw(self):
        random_index = random.randint(0, len(self.pixel_object)-1)
        self.pixel_object[random_index] = self.color
        self.drawn_pixels.append(random_index)
    
    def after_draw(self):
        if len(self.drawn_pixels) &gt; 5:
            oldest_index = self.drawn_pixels.pop(0)
            self.pixel_object[oldest_index] = (0,0,0)
```

This example `DemoAnimation` turns on random LEDs one at a time until there are 5 LEDs on. After 5 LEDs are on, the `after_draw()` function is used to turn off the LED that has been on the longest. The result is that random LEDs turn on, and stay on for 5 frames of the animation and then turn off. It uses the custom variable `drawn_pixels` to store a list of indexes of the LEDs that are currently on.

With all of the tools discussed on this page we have everything we need to create dazzling and delightful animations. On the next page we'll look at some some other specific examples of custom animations.

# Creating Custom LED Animations

## Custom Animation Examples

There are more example animations on this page that you can look at in order to get ideas about how you can manipulate the LEDs from your custom `Animation`. Another really great place to look is the existing built-in [Animations from the adafruit\_led\_animation library.](https://github.com/adafruit/Adafruit_CircuitPython_LED_Animation/tree/main/adafruit_led_animation/animation "Link to built-in animations") The examples in this guide are commented thoroughly detailing the purpose of each line of code. If you'd like to try these on your own device simply click the 'Download Project Bundle' button at the top of the code files. It will download the custom `Animation` class, a **code.py** file that uses it, and all required libraries it needs to run.

### Starting from existing animations

When you'd like to create your own custom Animation it's helpful if you can find an existing animation that is similar in some way to the animation you have in mind. If there is one with any similarities then you can copy it's code to start yours from instead of needing to start with an absolute "blank canvas". For instance, if you know that you want a rainbow animation you can re-use the internal color wheel generator from one of the built-in animations.

## Sweep Animation

The `SweepAnimation` will sweep across the strand, turning 1 pixel on with each animation frame. Once all of the pixels are on it will then sweep across again the same direction turning them back off. It uses custom variables to keep track of whether it's currently sweeping on or off, as well as the current index within the strand.

![](https://cdn-learn.adafruit.com/assets/assets/000/133/402/medium800thumb/leds_sweep.jpg?1730474585)

https://github.com/adafruit/Adafruit_Learning_System_Guides/blob/main/Custom_LED_Animations/sweep/sweep.py

## Zipper Animation

The `ZipperAnimation` will start lighting up every other LED from both ends of the strand, passing each other in the middle and resulting in the full strand being lit at the end of the cycle. It uses custom variables to keep track of the current step within the animation. The `reset()` is used to turn off the LEDs and reset the variables back to their initial values.

![](https://cdn-learn.adafruit.com/assets/assets/000/133/403/medium800thumb/leds_zipper.jpg?1730475016)

https://github.com/adafruit/Adafruit_Learning_System_Guides/blob/main/Custom_LED_Animations/zipper/zipper.py

## RainbowSweep Animation

The `RainbowSweepAnimation` shimmers the whole strand with a rainbow and then sweeps across it with another specified color. You can use `BLACK` or `0x000000` to turn LEDs off during the sweep. This animation uses a generator function internally to iterate through colors of the rainbow with help some colorwheel helpers. Many of the built-in Rainbow animation use this technique.

![](https://cdn-learn.adafruit.com/assets/assets/000/133/405/medium800thumb/leds_rainbowsweep.jpg?1730475464)

https://github.com/adafruit/Adafruit_Learning_System_Guides/blob/main/Custom_LED_Animations/rainbow_sweep/rainbowsweep.py

## All in Sequence

The following **code.py** file will play all 3 animations one after another in an `AnimationSequence`. Click the download project button to try it out. Remember to update the pin referenced by the code to match the pin your Neopixels are connected to.&nbsp;

https://github.com/adafruit/Adafruit_Learning_System_Guides/blob/main/Custom_LED_Animations/strand_sequence/code.py

# Creating Custom LED Animations

## 2D Grid Examples

The `adafruit_led_animation` library [contains a built-in helper class](https://github.com/adafruit/Adafruit_CircuitPython_LED_Animation/blob/main/adafruit_led_animation/grid.py "Link to grid helper class") for dealing with 2D Grids of pixels, `PixelGrid`. We can use this class inside of our custom Animation to be able to refer to the pixels with x, y coordinates in a grid rather than just an index within a strand like normal. This will only make sense to use if your pixels are also physically arranged in a grid, the [Neopixel FeatherWing](https://www.adafruit.com/product/2945) or [Dotstar FeatherWing](https://www.adafruit.com/product/3449) provide an easy to use grid to run them on.

## Snake Animation

The `SnakeAnimation` will make a snake of the specified size and color that will slither around the grid in random directions. If the snake gets stuck in a corner a new one will spawn and carry on slithering around. The current snake segment locations are stored in a list variable. During each animation step the snake will decide randomly whether to continue the direction it's going, or to change to a different random direction. Much of the movement logic is delegated into helper functions&nbsp;`_can_move()` and `_choose_direction()`.

![](https://cdn-learn.adafruit.com/assets/assets/000/133/410/medium800thumb/leds_snake.jpg?1730479903)

https://github.com/adafruit/Adafruit_Learning_System_Guides/blob/main/Custom_LED_Animations/snake/snake.py

## Conways Game Of Life Animation

The `ConwaysLifeAnimation`&nbsp; is an implementation of [Conway's Game of Life](https://en.wikipedia.org/wiki/Conway's_Game_of_Life). It is a basic simulation of cells that live and die based on simple rules about how many neighbors they have. You get to set the location of a set of live cells at the start of the simulation and then it will step through simulation ticks applying the population rules. During each step the code will iterate over every pixel in the grid and count the number of live and dead neighbor cells, deciding based on the giving rules the fate of the current cell and storing it in a list. After it's made it through the whole grid then it works it's way through the lists created above doing the actual turning on and off of pixels to signify cells spawning and dying.&nbsp;

![](https://cdn-learn.adafruit.com/assets/assets/000/133/409/medium800thumb/leds_conways_sm.jpg?1730479342)

https://github.com/adafruit/Adafruit_Learning_System_Guides/blob/main/Custom_LED_Animations/conways/conways.py

## Both Together

The following **code.py** will run both animations at the same time. By default it expects to find one [Neopixel Featherwing](https://www.adafruit.com/product/2945), and one [Dotstar Featherwing](https://www.adafruit.com/product/3449). You can update the code to use a different configuration of featherwings, or some other compatible grid. Remember to update the pins referenced and initialization as needed.&nbsp;

https://github.com/adafruit/Adafruit_Learning_System_Guides/blob/main/Custom_LED_Animations/grid_both/code.py


## Featured Products

### Adafruit DotStar FeatherWing - 6 x 12 RGB LEDs

[Adafruit DotStar FeatherWing - 6 x 12 RGB LEDs](https://www.adafruit.com/product/3449)
A Feather board without ambition is a Feather board without FeatherWings! This is the **DotStar FeatherWing, a 6x12 RGB LED Add-on For All Feather Boards**!&nbsp;Using our&nbsp;[Feather Stacking Headers](https://www.adafruit.com/products/2830)&nbsp;or&nbsp;<a...></a...>

No Longer Stocked
[Buy Now](https://www.adafruit.com/product/3449)
[Related Guides to the Product](https://learn.adafruit.com/products/3449/guides)
### Adafruit NeoPixel LED Dots Strand - 20 LEDs at 2" Pitch

[Adafruit NeoPixel LED Dots Strand - 20 LEDs at 2" Pitch](https://www.adafruit.com/product/3630)
Attaching NeoPixel strips to your costume can be a struggle as the flexible PCBs can crack when bent too much. So how to add little dots of color? Use these stranded NeoPixel dots! They're very small, so they're easy to embed into any structure, costume, or wearable. Each dot is...

In Stock
[Buy Now](https://www.adafruit.com/product/3630)
[Related Guides to the Product](https://learn.adafruit.com/products/3630/guides)
### Adafruit NeoPixel LED Dots Strand - 20 LED 4" Pitch

[Adafruit NeoPixel LED Dots Strand - 20 LED 4" Pitch](https://www.adafruit.com/product/3631)
Attaching NeoPixel strips to your costume can be a struggle as the flexible PCBs can crack when bent too much. So how to add little dots of color? Use these stranded NeoPixel dots! They're very small, so they're easy to embed into any structure, costume, or wearable. Each dot is...

In Stock
[Buy Now](https://www.adafruit.com/product/3631)
[Related Guides to the Product](https://learn.adafruit.com/products/3631/guides)
### Adafruit DotStar Digital LED Strip - Black 144 LED/m - 0.5 Meter

[Adafruit DotStar Digital LED Strip - Black 144 LED/m - 0.5 Meter](https://www.adafruit.com/product/2328)
Move over NeoPixels, there's a new LED strip in town! These fancy new DotStar LED strips are a great upgrade for people who have loved and used NeoPixel strips for a few years but want something even better. DotStar LEDs use generic 2-wire SPI, so you can push data much faster than with...

Out of Stock
[Buy Now](https://www.adafruit.com/product/2328)
[Related Guides to the Product](https://learn.adafruit.com/products/2328/guides)
### NeoPixel FeatherWing - 4x8 RGB LED Add-on For All Feather Boards

[NeoPixel FeatherWing - 4x8 RGB LED Add-on For All Feather Boards](https://www.adafruit.com/product/2945)
A Feather board without ambition is a Feather board without FeatherWings! This is the&nbsp; **NeoPixel FeatherWing, a&nbsp;4x8 RGB LED Add-on For All Feather Boards**!&nbsp;Using our&nbsp;[Feather Stacking Headers](https://www.adafruit.com/products/2830)&nbsp;or&nbsp;<a...></a...>

In Stock
[Buy Now](https://www.adafruit.com/product/2945)
[Related Guides to the Product](https://learn.adafruit.com/products/2945/guides)

## Related Guides

- [Adafruit NeoPixel FeatherWing](https://learn.adafruit.com/adafruit-neopixel-featherwing.md)
- [StarFlower NeoPixel Strand with MakeCode](https://learn.adafruit.com/starflower-neopixel-strand.md)
- [Simple and Beautiful NeoPixel Holiday Lights](https://learn.adafruit.com/simple-beautiful-color-changing-light-strand.md)
- [Easy NeoPixel Graphics with the CircuitPython Pixel Framebuf Library](https://learn.adafruit.com/easy-neopixel-graphics-with-the-circuitpython-pixel-framebuf-library.md)
- [Easy Alexa (Echo) Control of your ESP8266 Huzzah](https://learn.adafruit.com/easy-alexa-or-echo-control-of-your-esp8266-huzzah.md)
- [Sparkle Skirt Playground](https://learn.adafruit.com/sparkle-skirt-playground.md)
- [CircuitPython LED Animations](https://learn.adafruit.com/circuitpython-led-animations.md)
- [LED Bullwhip with Motion & Sound Reactivity](https://learn.adafruit.com/led-bullwhip.md)
- [Color-sensor Driven NeoPixel Dress](https://learn.adafruit.com/color-sensor-driven-neopixel-dress.md)
- [Make It Glow - Your First NeoPixel Project](https://learn.adafruit.com/make-it-glow-your-first-neopixel-project.md)
- [Light-Up Costumes in Harsh Environments](https://learn.adafruit.com/light-up-costumes-in-harsh-environments.md)
- [Wireless NeoPixel Controller](https://learn.adafruit.com/neotrellis-neopixel-controller.md)
- [NeoPixel Aquarium with Submersible Lights](https://learn.adafruit.com/neopixel-aquarium-with-submersible-lights.md)
- [No-Solder LED Disco Tie with Bluetooth](https://learn.adafruit.com/no-solder-circuit-playground-bluetooth-disco-tie.md)
- [Remote Effects Trigger Box](https://learn.adafruit.com/remote-effects-trigger.md)
- [Numpad 4000 Mechanical Keyswitch Data Entry Device](https://learn.adafruit.com/numpad-4000-mechanical-keyswitch-data-entry-device.md)
