Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Pulse animation #1

Merged
merged 10 commits into from
Dec 10, 2019
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
93 changes: 92 additions & 1 deletion adafruit_led_animation/animation.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ def monotonic_ns():
return int(time.time() * 1000000000)

import random
from math import ceil, sin, radians
from .color import BLACK, RAINBOW

__version__ = "0.0.0-auto.0"
Expand Down Expand Up @@ -339,6 +340,96 @@ def draw(self):
self.show()


class Pulse(Animation):
"""
Pulse all pixels a single color.

:param pixel_object: The initialised LED object.
:param int speed: Animation refresh rate in seconds, e.g. ``0.1``.
:param color: Animation color in ``(r, g, b)`` tuple, or ``0x000000`` hex format.
:param period: Period to pulse the LEDs over. Default 5.
:param max_intensity: The maximum intensity to pulse, between 0 and 1.0. Default 1.
:param min_intensity: The minimum intensity to pulse, between 0 and 1.0. Default 0.
"""

# pylint: disable=too-many-arguments
def __init__(self, pixel_object, speed, color, period=5, max_intensity=1, min_intensity=0):
self.max_intensity = max_intensity
self.min_intensity = min_intensity
self._period = period
self._intensity_delta = max_intensity - min_intensity
self._radians_per_second = radians(180 / period)
self._bpp = len(pixel_object[0])
self._last_update = monotonic_ns()
self._cycle_position = 0
super(Pulse, self).__init__(pixel_object, speed, color)

def draw(self):
now = monotonic_ns()
time_since_last_draw = (now - self._last_update) / 1000000000
self._last_update = now
self._cycle_position = (self._cycle_position + time_since_last_draw) % self._period
intensity = self.min_intensity + (sin(self._radians_per_second * self._cycle_position) * self._intensity_delta)

color = [int(self._color[n] * intensity) for n in range(self._bpp)]
self.fill(color)
self.show()


class Chase(Animation):
"""
Chase pixels in one direction in a single color, like a theater marquee sign.

:param pixel_object: The initialised LED object.
:param int speed: Animation speed rate in seconds, e.g. ``0.1``.
:param color: Animation color in ``(r, g, b)`` tuple, or ``0x000000`` hex format.
:param size: Number of pixels to turn on in a row.
:param spacing: Number of pixels to turn off in a row.
:param reverse: Reverse direction of movement.
"""

# pylint: disable=too-many-arguments
def __init__(self, pixel_object, speed, color, size=2, spacing=3, reverse=False):
self._size = size
self._spacing = spacing
self._repeat_width = size + spacing
self._num_repeats = ceil(len(pixel_object) / self._repeat_width)
self._overflow = len(pixel_object) % self._repeat_width
self._direction = 1 if not reverse else -1
self._reverse = reverse
self._n = 0
super(Chase, self).__init__(pixel_object, speed, color)

@property
def reverse(self):
"""
Whether the animation is reversed
"""
return self._reverse

@reverse.setter
def reverse(self, value):
self._reverse = value
self._direction = -1 if self._reverse else 1

def draw(self):
self.pixel_object.fill((0, 0, 0))
for i in range(self._size):
n = (self._n + i) % self._repeat_width
num = self._num_repeats + (1 if n < self._overflow else 0)
self.pixel_object[n::self._repeat_width] = [self.group_color(n) for n in range(num)]
self._n = (self._n + self._direction) % self._repeat_width
self.show()

def group_color(self, n): # pylint: disable=unused-argument
"""
Generate the color for the n'th group

:param n: The pixel group to get the color for
"""
return self.color


class AnimationSequence:
"""
A sequence of Animations to run in sequence, looping forever.
Expand Down Expand Up @@ -401,7 +492,7 @@ def animate(self):
"""
if not self._paused:
self._auto_advance()
self.current_animation.animate()
return self.current_animation.animate()

@property
def current_animation(self):
Expand Down