Permalink
Browse files

Make Pulser arbitrarily smooth (with no state but dT). Update demo.

  • Loading branch information...
1 parent f53c527 commit 198377ffe602cb80953621ae44371a452b374444 @markfickett committed Mar 7, 2012
Showing with 51 additions and 72 deletions.
  1. +1 −2 examples/frompy/patterns.py
  2. +50 −70 python/ledcontroller/patterns/Pulser.py
View
3 examples/frompy/patterns.py
@@ -32,8 +32,7 @@
# speed=15))
sender.append(InterpolatedMarquee(
Sequences.GenerateHueGradient(repeatInterval=10)))
- sender.append(Pulser(addDelay=0.75, moveDelay=0.05,
- color=Color(rgb=(0, 0, 1)), width=2, reverse=True))
+ sender.append(Pulser(color=Color(rgb=(0, 0, 1)), reverse=True))
# Open the serial device (connection to the Arduino).
if DUMMY_SERIAL:
View
120 python/ledcontroller/patterns/Pulser.py
@@ -3,91 +3,71 @@
class Pulser(Pattern):
"""
- Every sendDelay seconds, create a new Color at one end of the strip.
- Every moveDelay seconds it's on the strip, advance each dot by one LED.
- @param width number of LEDs lit by a pulse
+ Send pulses of a color along the LED strip.
+ @param color the color of the center (maximally intense part) of a pulse
+ @param width the maximum number of LEDs affected by a pulse (diameter)
+ @param addDelay the number of seconds between new pulses
+ @param speed the number of LEDs down the strip a pulse travels / second
+ @param reverse If True, pulses travel in the opposite direction; by
+ default, the start from index 0.
"""
- def __init__(self, addDelay=0.75, moveDelay=0.05,
- color=Color(rgb=(1,1,1)), width=1,
+ def __init__(self, addDelay=1.0, speed=14.0,
+ color=Color(rgb=(1,1,1)), width=6.0,
reverse=False):
Pattern.__init__(self)
if addDelay <= 0:
raise ValueError('addDelay value %s is not > 0.'
- % sendDelay)
- if moveDelay <= 0:
- raise ValueError('moveDelay value %s is not > 0.'
- % sendDelay)
- if width < 1:
- raise ValueError('width value %s is not >= 1.'
+ % addDelay)
+ if speed == 0:
+ raise ValueError('speed value %s is 0.')
+ if width <= 0:
+ raise ValueError('width value %s is not > 0.'
% width)
- self.__addDelay = addDelay
- self.__moveDelay = moveDelay
- self.__width = int(width)
- self.__lastAddTime = None
+ self.__addDelay = float(addDelay)
+ self.__speed = float(speed)
+ self.__interval = self.__speed * self.__addDelay
+ self.__radius = width/2.0
self.__reverse = reverse
self.__color = color
- self.__pulses = []
- def __addAndUpdatePulses(self):
- """
- Add new pulses and move existing pulses.
- If applicable, call _setChanged().
- """
- t = time.time()
-
- # move pulses
- for pulse in self.__pulses:
- pos, lastMoveTime = pulse
- moveDt = t - lastMoveTime
- changed = False
- while moveDt >= self.__moveDelay:
- pos += 1
- moveDt -= self.__moveDelay
- lastMoveTime += self.__moveDelay
- changed = True
- if changed:
- self._setChanged()
- pulse[0] = pos
- pulse[1] = lastMoveTime
-
- # add new pulses
- addDt = 0
- force = False
- if self.__lastAddTime is None:
- self.__lastAddTime = t - self.__addDelay
- addDt = t - self.__lastAddTime
- while addDt >= self.__addDelay:
- addTime = self.__lastAddTime + self.__addDelay
- self.__pulses.append([0, addTime])
- self.__lastAddTime += self.__addDelay
- addDt -= self.__addDelay
- self._setChanged()
+ self.__t0 = None
def isChanged(self):
- self.__addAndUpdatePulses()
- return Pattern.isChanged(self)
+ return True
+
+ def __generatePositions(self, maxIndex):
+ t = time.time()
+ if self.__t0 is None:
+ self.__t0 = t
+ dt = t - self.__t0
+ maxPos = maxIndex + self.__radius
+ repeats = int(dt / self.__addDelay)
+ dt -= repeats*self.__addDelay
+ i = 0
+ p = -self.__radius + self.__speed*dt
+ while i <= repeats and p <= maxPos:
+ yield p
+ p += self.__interval
+ i += 1
def apply(self, colorBuffer):
"""
- Add the pulses at their current locations to the Buffer.
- Remove any pulses which are past the end of the Buffer.
+ Recalculate pulse positions for the current time and add pulses.
"""
- self.__addAndUpdatePulses()
Pattern.apply(self, colorBuffer)
colors = colorBuffer.getColors()
- pastEnd = []
- for pulse in self.__pulses:
- startPos, _ = pulse
- inStrip = False
- for i in xrange(startPos, startPos + self.__width):
- pos = i
- if self.__reverse:
- pos = (len(colors) - 1) - pos
- if pos >= 0 and pos < len(colors):
- colors[pos].add(self.__color)
- inStrip = True
- if not inStrip:
- pastEnd.append(pulse)
- for pulse in pastEnd:
- self.__pulses.remove(pulse)
+ n = len(colors)
+ for rawCenter in self.__generatePositions(n-1):
+ center = rawCenter
+ if self.__reverse:
+ center = (n - 1) - center
+ minIndex = int(1 + center - self.__radius)
+ maxIndex = int(center + self.__radius)
+ for i in xrange(minIndex, maxIndex+1):
+ if i < 0 or i >= n:
+ continue
+ dx = abs(center - i)
+ f = min(1.0, dx / self.__radius)
+ colors[i] = colors[i].scaled(f)
+ colors[i].add(self.__color.scaled(1.0 - f))

0 comments on commit 198377f

Please sign in to comment.