class Canvas(): def __init__(self): # strip = None # self.DotCount = LED_COUNT # Create NeoPixel object with appropriate configuration. self.strip = PixelStrip(LED_COUNT, LED_PIN, LED_FREQ_HZ, LED_DMA, LED_INVERT, LED_BRIGHTNESS, LED_CHANNEL) # Intialize the library (must be called once before other functions). self.strip.begin() self.DotCount = self.strip.numPixels() def FillSolid(self, color): for i in range(self.strip.numPixels()): self.strip.setPixelColor(i, color) # def DrawPixels(self, position, size, color): # dot = int(position) # if dot < 0:return # if dot >= self.DotCount:return # # print("{dot:.2f}, {position:.2f}, {size:.2f}".format(dot=dot, position=position, size=size)) # self.strip.setPixelColor(dot, color) def DrawPixels(self, position, size, color): left_dot = int(position - size / 2) right_dot = int(position + size / 2) if right_dot < 0: return if left_dot < 0: left_dot = 0 if left_dot >= self.DotCount: return if right_dot >= self.DotCount: right_dot = self.DotCount # print("{dot:.2f}, {position:.2f}, {size:.2f}".format(dot=dot, position=position, size=size)) for dot in range(left_dot, right_dot + 1): self.strip.setPixelColor(dot, color)
def dither_fade( strip: ws.PixelStrip, new_color: Union[ws.Color, np.array], leds_to_switch: Optional[Iterable[int]] = None, dither_time: float = 1, ): """ Dither in to a new set of colours by switching small batches of pixels. Parameters --------- strip the LED strip to animate new_color Either a single ws.Color or an array of them. Providing one colour acts as an array of that one colour. leds_to_switch Only dither these LEDs to leave specific elements static. dither_time the time over which to dither. Do not make this too short """ try: iter(new_color) except TypeError: # this is not iterable, therefore it is one colour. # Make an array of that colour. new_color = np.array([new_color for _ in range(strip.numPixels())]) start_time = time.time() if leds_to_switch is None: leds_to_switch = [i for i in range(strip.numPixels())] random.shuffle(leds_to_switch) num_leds = len(leds_to_switch) # As a rough rule of thumb, it takes 0.005 seconds to switch an LED and render an # update. Calculate the group size dynamically to fit into our time budget. min_update_time = 0.005 switches_in_time = int(round(dither_time / min_update_time)) batch_size = int(round((strip.numPixels() / switches_in_time) + 0.5)) if batch_size != 1: num_batches = int(round((strip.numPixels() / batch_size))) batch_size = int(round((strip.numPixels() / num_batches))) while leds_to_switch: these_leds = [leds_to_switch.pop() for _ in range(batch_size) if leds_to_switch] for this_led in these_leds: strip.setPixelColor(this_led, new_color[this_led]) time.sleep(dither_time / (batch_size * num_leds)) strip.show() # Sometimes we go too fast with the switching, as # the batching approximation is horrible. If we # do, just chill here before moving on end_time = time.time() time_diff = end_time - start_time if time_diff < dither_time: time.sleep(dither_time - time_diff)
class Steps(list): def __init__(self): # Create NeoPixel object with appropriate configuration. self.strip = PixelStrip(LED_COUNT, LED_PIN, LED_FREQ_HZ, LED_DMA, LED_INVERT, LED_BRIGHTNESS, LED_CHANNEL) # Intialize the library (must be called once before other functions). self.strip.begin() for i, led_counter in enumerate(NUMBER_OF_LEDS): # get last led start = 0 if i == 0 else (self[-1][-1] + 1) # define step step = Step(self.strip, start, start + led_counter) self.append(step) def __len__(self): return sum(NUMBER_OF_LEDS) def off(self, step_ms=0, led_ms=0): for step in self: step.off(led_ms) wait(step_ms) def color_test(self): for i, step in enumerate(self): color = Color(255, 0, 0) if i % 2 == 0 else Color(0, 255, 0) for led in step: self.strip.setPixelColor(led, color) self.strip.show() def pong(self, ms=10): for step in self: step.pong_init() while True: for step in self: step.pong_loop(ms=0) wait(ms) def rainbow(self, wait_ms=20, iterations=1): """Draw rainbow that fades across all pixels at once.""" for i in range(self.strip.numPixels()): self.strip.setPixelColor(i, wheel(i & 255)) self.strip.show() wait(wait_ms) def rainbowCycle(self, wait_ms=20, iterations=5): """Draw rainbow that uniformly distributes itself across all pixels.""" for j in range(256*iterations): for i in range(self.strip.numPixels()): self.strip.setPixelColor(i, wheel((int(i * 256 / self.strip.numPixels()) + j) & 255)) self.strip.show() wait(wait_ms)
def rainbow_cycle(strip: PixelStrip, wait_ms: int = 20, iterations: int = 5): """Draw rainbow that uniformly distributes itself across all pixels. :param strip: :param wait_ms: :param iterations: :return: """ for j in range(256 * iterations): for i in range(strip.numPixels()): strip.setPixelColor( i, wheel((int(i * 256 / strip.numPixels()) + j) & 255)) strip.show() time.sleep(wait_ms / 1000.0)
def theater_chase_rainbow(strip: PixelStrip, wait_ms: int = 50): """Rainbow movie theater light style chaser animation. :param strip: :param wait_ms: :return: """ for j in range(256): for q in range(3): for i in range(0, strip.numPixels(), 3): strip.setPixelColor(i + q, wheel((i + j) % 255)) strip.show() time.sleep(wait_ms / 1000.0) for i in range(0, strip.numPixels(), 3): strip.setPixelColor(i + q, 0)
class PlasmaWS281X(Plasma): def __init__(self, light_count, gpio_pin=13, strip_type='WS2812', channel=1, brightness=255, freq_hz=800000, dma=10, invert=False): from rpi_ws281x import PixelStrip, ws strip_types = {} for t in ws.__dict__: if '_STRIP' in t: k = t.replace('_STRIP', '') v = getattr(ws, t) strip_types[k] = v strip_type = strip_types[strip_type] self._strip = PixelStrip(light_count, gpio_pin, freq_hz, dma, invert, brightness, channel, strip_type) self._strip.begin() Plasma.__init__(self, light_count) def show(self): """Output the buffer.""" for i in range(self._strip.numPixels()): r, g, b, brightness = self._pixels[i] self._strip.setPixelColorRGB(i, r, g, b) self._strip.show()
class PlasmaWS281X(Plasma): """Class for Plasma light devices in the WS281X/SK6812 family.""" name = "WS281X" options = { 'pixel_count': int, "gpio_pin": int, "strip_type": str, "channel": int, "brightness": int, "freq_hz": int, "dma": int, "invert": bool } option_order = ("gpio_pin", "strip_type", "channel", "brightness", "freq_hz", "dma", "invert") def __init__(self, pixel_count=1, gpio_pin=13, strip_type='WS2812', channel=None, brightness=255, freq_hz=800000, dma=10, invert=False): """Initialise WS281X device. :param pixel_count: Number of individual RGB LEDs :param gpio_pin: BCM GPIO pin for output signal :param strip_type: Strip type: one of WS2812 or SK6812 :param channel: LED channel (0 or 1, or None for automatic) :param brightness: Global WS281X LED brightness scale :param freq_hz: WS281X output signal frequency (usually 800khz) :param dma: DMA channel :param invert: Invert signals for NPN-transistor based level shifters """ from rpi_ws281x import PixelStrip, ws strip_types = {} for t in ws.__dict__: if '_STRIP' in t: k = t.replace('_STRIP', '') v = getattr(ws, t) strip_types[k] = v strip_type = strip_types[strip_type] if channel is None: if gpio_pin in [13]: channel = 1 elif gpio_pin in [12, 18]: channel = 0 self._strip = PixelStrip(pixel_count, gpio_pin, freq_hz, dma, invert, brightness, channel, strip_type) self._strip.begin() Plasma.__init__(self, pixel_count) def show(self): """Output the buffer.""" for i in range(self._strip.numPixels()): r, g, b, brightness = self._pixels[i] self._strip.setPixelColorRGB(i, r, g, b) self._strip.show()
def turn_lights_off(strip: ws.PixelStrip, runtime: float = RUNTIME): print(f"Turning the lights off over {runtime}s") weather = get_weather() WEATHER_ANIMATIONS[weather](strip, runtime, reverse=True) for i in range(strip.numPixels()): strip.setPixelColor(i, ws.Color(0, 0, 0)) strip.show()
def clear_strip(strip: PixelStrip): """Turn all lights off instantly. :return: """ for i in range(strip.numPixels()): strip.setPixelColor(i, color(0, 0, 0)) strip.show()
def getPixels(strip: PixelStrip): num_pixels = strip.numPixels() all_pixels = [] for i in range(num_pixels): c = strip.getPixelColorRGB(i) # all_pixels.append((c.r, c.g, c.b)) all_pixels.append(c) return all_pixels
class RpiWs281xLedstrip(AbstractLight): def __init__(self) -> None: super().__init__(led_count=LED_COUNT) self.pixel_strip = PixelStrip(LED_COUNT, LED_PIN, LED_FREQ_HZ, LED_DMA, LED_INVERT, LED_BRIGHTNESS, LED_CHANNEL) self.pixel_strip.begin() def write(self): assert self.pixel_strip.numPixels() == len(self.leds) # Update the value for each of the pixels in the strip for i in range(startLED, self.pixel_strip.numPixels()): [red, green, blue, brightness] = self.leds[i] colors = (int(c * brightness * 255) for c in (red, green, blue)) self.pixel_strip.setPixelColorRGB(i, *colors, 255) # Flush the new values to the strip self.pixel_strip.show()
def theater_chase( strip: ws.PixelStrip, color: ws.Color, wait_ms: float = 50.0, iterations: int = 10 ): """ Movie theater light style chaser animation. :param strip: the strip to animate :param color: the color to set each pixel to :param wait_ms: the time between animating each pixel, in milliseconds :param iterations: the number of times this animation will play """ for j in range(iterations): for q in range(3): for i in range(0, strip.numPixels(), 3): strip.setPixelColor(i + q, color) strip.show() time.sleep(wait_ms / 1000.0) for i in range(0, strip.numPixels(), 3): strip.setPixelColor(i + q, 0)
def theater_chase(strip: PixelStrip, color: color, wait_ms: int = 50, iterations: int = 10): """Movie theater light style chaser animation. :param strip: :param color: :param wait_ms: :param iterations: :return: """ for j in range(iterations): for q in range(3): for i in range(0, strip.numPixels(), 3): strip.setPixelColor(i + q, color) strip.show() time.sleep(wait_ms / 1000.0) for i in range(0, strip.numPixels(), 3): strip.setPixelColor(i + q, 0)
def color_wipe(strip: PixelStrip, color: color, wait_ms: int = 50): """Wipe color across display a pixel at a time. :param strip: PixelStrip object to apply the effect to :param color: Color to wipe :param wait_ms: blocking time to wait (in ms) before returning :return: """ for i in range(strip.numPixels()): strip.setPixelColor(i, color) strip.show() time.sleep(wait_ms / 1000.0)
def alternate_colors(strip: ws.PixelStrip, colors: Optional[Iterable[ws.Color]] = None): """ Show a set of colours along the strip. :param strip: the strip to show the colors on :param colors: a list of colors to show """ if colors is None: colors = [ws.Color(255, 0, 0), ws.Color(0, 255, 0), ws.Color(0, 0, 255)] for i in range(strip.numPixels()): strip.setPixelColor(i, colors[i % len(colors)]) strip.show()
def color_wipe(strip: ws.PixelStrip, color: ws.Color, wait_ms: float = 50.0): """ Wipe color across display a pixel at a time. :param strip: the strip to animate :param color: the color to set each pixel to :param wait_ms: the time between animating each pixel, in milliseconds """ for i in range(strip.numPixels()): strip.setPixelColor(i, color) strip.show() time.sleep(wait_ms / 1000.0)
def rainbow(strip: PixelStrip, wait_ms: int = 20, iterations: int = 1): """Draw rainbow that fades across all pixels at once. :param strip: :param wait_ms: :param iterations: :return: """ for j in range(256 * iterations): for i in range(strip.numPixels()): strip.setPixelColor(i, wheel((i + j) & 255)) strip.show() time.sleep(wait_ms / 1000.0)
def rainbow(strip: ws.PixelStrip, wait_ms: float = 20.0, iterations: int = 1): """ Draw rainbow that fades across all pixels at once. :param strip: the strip to animate :param wait_ms: the time between each fading step :param iterations: the number of times to play this animation """ for j in range(256 * iterations): for i in range(strip.numPixels()): strip.setPixelColor(i, get_rainbow_color((i + j) & 255)) strip.show() time.sleep(wait_ms / 1000.0)
def set_color(self, color): rgb = int(color, 16) r = int(rgb / 256 / 256) rgb = rgb - r * 256 * 256 g = int(rgb / 256) b = rgb - g * 256 # Create NeoPixel object with appropriate configuration. strip = PixelStrip(LED_COUNT, LED_PIN, LED_FREQ_HZ, LED_DMA, LED_INVERT, LED_BRIGHTNESS) # Intialize the library (must be called once before other functions). strip.begin() for i in range(0, strip.numPixels(), 1): strip.setPixelColor(i, Color(g, r, b)) strip.show()
def run(): prev_animation = None prev_brightness = None strip = PixelStrip(LED_COUNT, LED_PIN, LED_FREQ_HZ, LED_DMA, LED_INVERT, LED_BRIGHTNESS, LED_CHANNEL, LED_STRIP) strip.begin() threading.Thread(target=app.run).start() print('Press Ctrl-C to quit.') len_animations = None try: while True: if len(curr_animations) != len_animations: len_animations = len(curr_animations) clear(strip) generators = [] for animation in curr_animations: generators.append(animation(VStrip(strip))) if curr_brightness != prev_brightness: strip.setBrightness(curr_brightness) prev_brightness = curr_brightness vstrips = [] for gen in generators: vstrips.append(next(gen)) # vstrip.reverse() for pos in range(strip.numPixels()): col = np.array([0., 0., 0.]) transparency = 1 for v in vstrips: cur_col = np.array(v.getPixelColor(pos)) col += cur_col[:3] * transparency transparency *= cur_col[3] col = np.maximum( np.minimum(np.array(np.floor(col), dtype=np.int), 255), 0) strip.setPixelColor(pos, Color(*col.tolist())) strip.show() except KeyboardInterrupt: clear(strip)
class LedManager(object): # TODO: - Log and document this class # LED strip configuration: __LED_COUNT = 3 # Number of LED pixels. __LED_PIN = 18 # GPIO pin connected to the pixels (must support PWM!). __LED_FREQ_HZ = 800000 # LED signal frequency in hertz (usually 800khz) __LED_DMA = 10 # DMA channel to use for generating signal (try 10) __LED_BRIGHTNESS = 255 # Set to 0 for darkest and 255 for brightest __LED_INVERT = False # True to invert the signal (when using NPN transistor level shift) __LED_CHANNEL = 0 __LED_STRIP = ws.WS2812_STRIP __instance = None def __init__(self): if LedManager.__instance is None: LedManager.__instance = self self.strip = PixelStrip(self.__LED_COUNT, self.__LED_PIN, self.__LED_FREQ_HZ, self.__LED_DMA, self.__LED_INVERT, self.__LED_BRIGHTNESS, self.__LED_CHANNEL, self.__LED_STRIP) self.strip.begin() else: raise Exception("This class is a Singleton") @staticmethod def get_instance(): """ :rtype: LedManager """ if LedManager.__instance is None: LedManager() return LedManager.__instance # Define function that colors all LEDs of the given color. def color_wipe(self, led_color, wait_ms=50): for i in range(0, self.strip.numPixels()): self.strip.setPixelColor(i, led_color.value) self.strip.show() time.sleep(wait_ms / 1000.0)
class LedStrip(object): def __init__(self): self.status = 'off' self.strip = PixelStrip(LED_COUNT, LED_PIN, LED_FREQ_HZ, LED_DMA, LED_INVERT, LED_BRIGHTNESS, LED_CHANNEL) self.strip.begin() self.set_color(BLACK) def toggle_light(self): if self.status == STATUS_ON: self.set_color(BLACK) self.status = STATUS_OFF else: self.set_color(SOFT_WHITE) self.status = STATUS_ON def set_color(self, color, wait_ms=200): for i in range(self.strip.numPixels()): self.strip.setPixelColor(i, color) self.strip.show() time.sleep(wait_ms / 1000) def get_status(self): return self.status
class LEDStrip(object): """ An object wrapper for the LED strip. """ def __init__(self, n_led, led_pin): """ Initialize the object. Args ---- n_led: int Number of LEDs on the strip. led_pin: int GPIO bin the data line is connected to. """ # Create the led strip object. if led_pin in [12, 18]: channel = 0 elif led_pin in [13, 19]: channel = 1 else: raise ValueError(('GPIO pin {} can not be used for the LED ' 'strip.').format(led_pin)) self._strip = PixelStrip(n_led, led_pin, channel=channel) self._strip.begin() @property def n_led(self): """ Return the number of LEDs on the strip. """ return self._strip.numPixels() def flush(self, colors): """ Display the colors contained in data on the strip. Args ---- colors: Color, [Color] If a single color is given, the whole strip is colored with that color. If a list is given, colors in the list are set. """ if isinstance(colors, int): for i_led in range(self.n_led): self._strip.setPixelColor(i_led, colors) else: for i_led, color in enumerate(colors): self._strip.setPixelColor(i_led, color) self._strip.show() def clear(self): """ Deactivate all LEDs on the strip. """ self.flush(Color(0, 0, 0)) self._strip.show()
class RGBLight(): "Simple wrapper for a RGB light device " def __init__(self, pin: int, nb_led: int = 5): self.pixels = PixelStrip(nb_led, pin) self.pixels.begin() self._state: bool = False self.delay: float = 0.01 self._mode: int = MODE_RGB self.off() @property def state(self) -> bool: return self._state @state.setter def state(self, state: bool) -> None: self._state = state @property def mode(self) -> int: return self._mode @mode.setter def mode(self, mode) -> None: self._mode = mode def on(self) -> None: self.state = True for i in range(self.pixels.numPixels()): print(i) self.pixels.setPixelColorRGB(i, 50, 50, 50) self.pixels.show() sleep(0.01) def off(self) -> None: self.state = False for i in range(self.pixels.numPixels()): self.pixels.setPixelColorRGB(i, 0, 0, 0) self.pixels.show() sleep(self.delay) def toggle(self) -> None: if self.state is True: self.off() else: self.on() @property def color(self) -> Tuple[int, int, int]: if self.mode != MODE_RGB: raise Exception("Light is not in RGB mode") color_raw = self.pixels.getPixelColorRGB(0) color = (color_raw.r, color_raw.g, color_raw.b) return color @color.setter def color(self, color: Tuple[int, int, int]) -> None: self.state = True self.mode = MODE_RGB for i in range(self.pixels.numPixels()): self.pixels.setPixelColorRGB(i, *color) self.pixels.show() sleep(self.delay) @property def brightness(self) -> int: bri = self.pixels.getBrightness() return bri @brightness.setter def brightness(self, value: int) -> None: self.pixels.setBrightness(value) @property def temperature(self) -> int: if self.mode != MODE_TEMPERATURE: raise Exception("Light is not in temperature mode") color_raw = self.pixels.getPixelColorRGB(0) rgb = (color_raw.r, color_raw.g, color_raw.b) print(rgb) for temp in kelvin_table.keys(): if kelvin_table[temp] == rgb: return temp return 0 @temperature.setter def temperature(self, temp: int) -> None: self.mode = MODE_TEMPERATURE safe_temp = temp - (temp % 100) rgb: Tuple[int, int, int] = kelvin_table[safe_temp] for i in range(self.pixels.numPixels()): self.pixels.setPixelColorRGB(i, *rgb) self.pixels.show() sleep(self.delay)
class LEDController: def __init__(self, LED_COUNT, LED_PIN, LED_FREQ_HZ, LED_DMA, LED_INVERT, LED_BRIGHTNESS, LED_CHANNEL, LED_STRIP): self._strip = PixelStrip(LED_COUNT, LED_PIN, LED_FREQ_HZ, LED_DMA, LED_INVERT, LED_BRIGHTNESS, LED_CHANNEL, LED_STRIP) self._strip.begin() self._step = 0.5 self._start = 0 def color_wipe(self, color, wait_ms=50): for i in range(self._strip.numPixels()): self._strip.setPixelColor(i, color) time.sleep(wait_ms / 1000.0) self._strip.show() #time.sleep(wait_ms / 1000.0) def idle_lighting(self): self.color_wipe(Color(50, 50, 50), 0) def listening_lighting(self): #proximity = ProximityController.get_proximity_data() self.color_wipe(Color(150, 150, 150), 0) def map_range(self, x, inLow, inHigh, outLow, outHigh): inRange = inHigh - inLow outRange = outHigh - outLow inScale = (x - inLow) / inRange return outLow + (inScale * outRange) def breathing_effect(self): while responding: duty = self.map_range(math.sin(self._start), -1, 1, 0, 150) self._start += self._step #self.color_wipe(Color(0,0,0,int(duty)),0) self.color_wipe(Color(int(duty), int(duty), int(duty)), 0) time.sleep(0.05) def alternate_lighting(self, color, wait_ms=50): for i in range(0, self._strip.numPixels(), 2): self._strip.setPixelColor(i, color) time.sleep(wait_ms / 1000.0) self._strip.show() time.sleep(1) def greeting_effetct(self): brightness = self.map_range(-distance, -4000, 0, 0, 150) self.color_wipe( Color(int(brightness), int(brightness), int(brightness), 0), 0) def wave_effect(self, color=Color(50, 50, 50), wait_ms=5): for i in range(0, self._strip.numPixels(), 5): self.switch_off() for j in range(0, 5): self._strip.setPixelColor(i + j, color) time.sleep(wait_ms / 1000.0) self._strip.show() for i in range(self._strip.numPixels(), -1, -5): self.switch_off() for j in range(0, min(5, i)): self._strip.setPixelColor(i - j, color) time.sleep(wait_ms / 1000.0) self._strip.show() def switch_off(self): self.color_wipe(Color(0, 0, 0), 0)
class Light: """ Class that represents a LED light strip connected to a Raspberry PI through a single I/O port. Data going through that I/O port and power supplied externally (because it's too much for the PI to power them if there are too many). """ def __init__(self, name: str): """ Constructor, initializing members with default values. """ print(" ..creating light object: " + name) self._name = name # Human name of the LED strip; self._ledCount = 100 # Number of individually addressable LEDs on the strip; self._redRGB = 1 # RGB Red color value; self._greenRGB = 1 # RGB Green color value; self._blueRGB = 1 # RGB Blue color value; self._ledBrightness = 255 # Set to 0 for darkest and 255 for brightest; self._ledFrequency = 800000 # LED signal frequency in hertz (usually 800khz); self._ledDmaChannel = 10 # DMA channel to use for generating signal (try 10); self._ledInvert = False # True to invert the signal (when using NPN transistor level shift); self._ledChannel = 0 self._stripGpioPin = 18 # RaspberryPI GPIO pin that is used to drive the LED strip; self._stripType = ws.SK6812_STRIP_RGBW # The type of the LED strip (just RGB or does it also include a White LED); self._strip = None # Instance of the rpi_ws281x LED strip; self._lightState = False # Is the light "off" (false) or "on" (true); self._switches = [ ] # Optional list of Switch objects that are linked to this light object; self._debug = False # Debug level logging; def __del__(self): """ Destructor will turn off this light. """ print("destroying light object: " + self._name) self.Off() @property def name(self): """ Return the name of this light. """ return self._name @name.setter def name(self, value: str): """ Set the name for this light. """ self._name = value @property def ledCount(self) -> int: """ Return the number of individual LEDs on the light strip. """ return self._ledCount @ledCount.setter def ledCount(self, value: int): """ Set the number of LEDs to use on this light strip. You can activate fewer than available. """ if not (value > 0): raise Exception("You need to have at least 1 LED on the strip!") self._ledCount = value @property def redRGB(self) -> int: """ Return the current Red RGB color value for the light strip. """ return self._redRGB @redRGB.setter def redRGB(self, value: int): """ Set the red RGB color value of LEDs to use on this light strip. """ if not ((value >= 0) and (value <= 255)): raise Exception("The red RGB value needs to be between 0 and 255!") self._redRGB = value @property def greenRGB(self) -> int: """ Return the current Green RGB color value for the light strip. """ return self._greenRGB @greenRGB.setter def greenRGB(self, value: int): """ Set the green RGB color value of LEDs to use on this light strip. """ if not ((value >= 0) and (value <= 255)): raise Exception( "The green RGB value needs to be between 0 and 255!") self._greenRGB = value @property def blueRGB(self) -> int: """ Return the current Blue RGB color value for the light strip. """ return self._blueRGB @blueRGB.setter def blueRGB(self, value: int): """ Set the blue RGB color value of LEDs to use on this light strip. """ if not ((value >= 0) and (value <= 255)): raise Exception( "The blue RGB value needs to be between 0 and 255!") self._blueRGB = value # @property # def ledColor(self) -> str: # """ Return the RGB color value of the LEDs. """ # return self._ledColor # # @ledColor.setter # def ledColor(self, value: str): # """ Set the RGB color value of the LEDs. """ # self._ledColor=value @property def ledBrightness(self) -> int: """ Return the brightness that the LED have been configured with (0 to 255). """ return self._ledBrightness @ledBrightness.setter def ledBrightness(self, value: int): """ Set the brightness of the LEDs (0 to 255). """ if not ((value > 0) and (value <= 255)): raise Exception("Brightness needs to be between 1 and 255!") self._ledBrightness = value @property def stripGpioPin(self) -> int: """ Return the Raspberry PI GPIO pin the LED strip is connected to (data). """ return self._stripGpioPin @stripGpioPin.setter def stripGpioPin(self, value: int): """ Set the Raspberry PI GPIO pin the LED strip is connected to (data). """ # The number of valid GPIO ports is limited and specific. # A good validator should check the port based on RPi model and throw an exception if the # selected port does not work to drive a LED strip like these. # I've decided to have a very rough validator here that enforces a port between 2 and 26. # I know this is not a great validator and I should probably make it more specific at some point. if not ((value >= 2) and (value <= 26)): raise Exception("The RPi GPIO port needs to be between 2 and 26!") self._stripGpioPin = value @property def state(self) -> bool: """ Show if the light is currently on or off. "True" means "On" and "False" means "Off". """ return self._lightState @property def debug(self) -> bool: """ Return the debug-flag that is set for this light. """ return self._debug @debug.setter def debug(self, flag: bool): """ Set the debug level. """ self._debug = flag @property def switches(self) -> list: """ Return a list of 0 or more Switch objects that have been mapped to this light. """ return self._switches def addSwitch(self, switch): """ Add a new Switch object that can control this light. """ self._switches.append(switch) def delSwitch(self, switch): """ Remove a switch from this light. """ self._switches.remove(switch) del switch def Start(self): """ Initialize the LED strip at the hardware level so that we can start control the individual LEDs. """ self._strip=PixelStrip(self._ledCount, \ self._stripGpioPin, \ self._ledFrequency, \ self._ledDmaChannel, \ self._ledInvert, \ self._ledBrightness, \ self._ledChannel, \ self._stripType) # Initialize the library (must be called once before other functions): self._strip.begin() def On(self): """ Turn the leds on. """ # Set the led color, full brightness: color = Color(self._greenRGB, self._redRGB, self._blueRGB, self._ledBrightness) for i in range(self._strip.numPixels()): self._strip.setPixelColor(i, color) self._strip.show() self._lightState = True def Off(self): """ Turn the leds off. """ color = Color(0, 0, 0, 0) for i in range(self._strip.numPixels()): self._strip.setPixelColor(i, color) self._strip.show() self._lightState = False def Toggle(self): """ Toggle the light on or off. """ if self._lightState: self.Off() else: self.On() def Update(self): """ Apply the Updated LED settings if they are on. """ if self._lightState: self.Off() self.On()
class LEDController: """ Takes care of lighting effects for Voxx @params: LED_COUNT: Number of LEDs to light up LED_PIN : Which pin LED is connected to LED_FREQ_HZ: Signal frequency in Hz LED_DMA: DMA channel for generating the signal - defaults to 10 LED_INVERT: Option to invert signal. Default False LED_BRIGHTNESS: Max brightness of LEDs - set to 10. Max 255 LED_CHANNEL: Defaults to 0 LED_STRIP: LED strip type. 'ws.WS2811_STRIP_RGB' to be used for Voxx """ def __init__(self,LED_COUNT, LED_PIN, LED_FREQ_HZ, LED_DMA,LED_INVERT, LED_BRIGHTNESS, LED_CHANNEL,LED_STRIP): self._strip = PixelStrip(LED_COUNT, LED_PIN, LED_FREQ_HZ, LED_DMA,LED_INVERT, LED_BRIGHTNESS, LED_CHANNEL,LED_STRIP) self._strip.begin() self._step = 0.5 self._start = 0 """Sets all pixels to 'color - Color(R,G,B)' color given by RGB values from 0-255""" def color_wipe(self,color,wait_ms=50): for i in range(0,self._strip.numPixels()): self._strip.setPixelColor(i, color) time.sleep(wait_ms / 1000.0) self._strip.show() #time.sleep(wait_ms / 1000.0) """ Minimum brightness idle state lighting""" def idle_lighting(self): self.color_wipe(Color(50,50,50),0) """ Maximum brightness listening state lighting""" def listening_lighting(self): #proximity = ProximityController.get_proximity_data() self.color_wipe(Color(255,255,255),0) """ Maps 'x' in input range to output range """ def map_range(self,x, inLow, inHigh, outLow, outHigh): inRange = inHigh - inLow outRange = outHigh - outLow inScale = float(x - inLow)/float(inRange) return outLow + (inScale * outRange) """ # Alternate breathing effect if signalling does not work def breathing_effect(self): self._start = 0 has_responded = 0 while True: if tts.responding: duty = self.map_range(math.sin(self._start),-1,1,0,255) self._start += self._step #self.color_wipe(Color(0,0,0,int(duty)),0) self.color_wipe(Color(int(duty),int(duty),int(duty)),0) time.sleep(0.05) has_responded = 1 elif has_responded: break time.sleep(0.1) """ """ Breathing effect for response state lighting""" def breathing_effect(self): self._start = 0 tts.response_available.wait() print("response lighting") while tts.responding: #while True: duty = self.map_range(math.sin(self._start),-1,1,0,200) self._start += self._step #self.color_wipe(Color(0,0,0,int(duty)),0) self.color_wipe(Color(int(duty),int(duty),int(duty)),0) time.sleep(0.2) """ Lights up alternate LEDs """ def alternate_lighting(self,color,wait_ms=50): for i in range(0,self._strip.numPixels(),2): self._strip.setPixelColor(i, color) time.sleep(wait_ms / 1000.0) self._strip.show() time.sleep(1) """ Maps user distance to light intensity """ def greeting_effect(self,distance): if(distance > 2500): brightness = 50 else: brightness = self.map_range(-distance,-2500,0,50,200) print(str(brightness)) #time.sleep(0.1) self.color_wipe(Color(int(brightness),int(brightness),int(brightness)),0) """ Indicates unavailability of internet """ def blink(self): while(True): self.color_wipe(Color(50,50,50),0) time.sleep(1) self.color_wipe(Color(0,0,0),0) time.sleep(1) """ Wave effect to convey that Voxx is 'thinking' """ def wave_effect(self,color=Color(255,255,255),wait_ms=5): while tts.thinking: for i in range(0,self._strip.numPixels(),5): if(tts.thinking == 0): break self.switch_off() for j in range(0,10): self._strip.setPixelColor(i+j, color) time.sleep(wait_ms / 1000.0) self._strip.show() for i in range(self._strip.numPixels(),-1,-5): if(tts.thinking == 0): break self.switch_off() for j in range(0,min(10,i)): self._strip.setPixelColor(i-j, color) time.sleep(wait_ms / 1000.0) self._strip.show() time.sleep(0.1) def switch_off(self): self.color_wipe(Color(0,0,0),0)
class RGBMatrix: def __init__(self): # LED strip configuration: LED_COUNT = 64 # Number of LED pixels. LED_PIN = 12 # GPIO pin connected to the pixels (18 uses $ LED_FREQ_HZ = 800000 # LED signal frequency in hertz (usually 800$ LED_DMA = 10 # DMA channel to use for generating signal ($ LED_BRIGHTNESS = 10 # Set to 0 for darkest and 255 for brightest LED_INVERT = False # True to invert the signal (when using NPN $ LED_CHANNEL = 0 # set to '1' for GPIOs 13, 19, 41, 45 or 53 # TODO: root self.strip = PixelStrip(LED_COUNT, LED_PIN, LED_FREQ_HZ, LED_DMA, LED_INVERT, LED_BRIGHTNESS, LED_CHANNEL) # Intialize the library (must be called once before other functions). self.strip.begin() # 0 1 2 3 4 5 6 7 # 8 9 10 11 12 13 14 15 # 16 17 18 19 20 21 22 23 # 24 25 26 27 28 29 30 31 # 32 33 34 35 36 37 38 39 # 40 41 42 43 44 45 46 47 # 48 49 50 51 52 53 54 55 # 56 57 58 59 60 61 62 63 self.numbers = [ [0, 1, 2, 3, 4, 5, 6, 7, 15, 23, 31, 39, 47, 55, 63, 62, 61, 60, 59, 58, 57, 56, 48, 40, 32, 24, 16, 8], # 0 [3, 11, 19, 27, 35, 43, 51, 59], # 1 [9, 2, 3, 4, 13, 21, 28, 28, 34, 41, 49, 57, 58, 59, 60, 61], # 2 [2, 3, 4, 13, 21, 28, 27, 26, 25, 37, 45, 53, 60, 59, 58, 57], # 3 [1, 9, 17, 25, 33, 41, 42, 43, 44, 45, 46, 47, 28, 36, 52, 60], # 4 [1, 9, 17, 25, 26, 27, 28, 29, 38, 46, 54, 61, 60, 59, 58, 57, 2, 3, 4, 5], # 5 [6, 5, 4, 3, 2, 1, 9, 17, 25, 33, 41, 49, 57, 58, 59, 60, 61, 62, 54, 46, 38, 37, 36, 35, 34], # 6 [1, 2, 3, 4, 5, 6, 7, 15, 22, 29, 36, 44, 52, 60], # 7 [4, 3, 2, 9, 18, 27, 36, 45, 53, 60, 59, 58, 49, 41, 34, 20, 13], # 8 [7, 6, 5, 4, 3, 2, 1, 9, 17, 25, 33, 34, 35, 36, 37, 38, 39, 31, 23, 15, 47, 55, 63, 62, 61, 60, 59, 58, 57], # 9 [16, 17, 18, 19, 20, 21, 22, 23, 40, 41, 42, 43, 44, 45, 46, 47, 2, 10, 26, 34, 50, 58, 5, 13, 29, 37, 53, 61], # 10 # [17, 18, 19, 20, 21, 22, 49, 50, 51, 52, 53, 54], # 11 = [28], # 12 - [26, 27, 28, 19, 35], # 13 + [7, 56, 14, 49, 21, 42, 28, 35], # 14 / [63, 54, 45, 36, 27, 35, 42, 49, 56, 0, 9, 18, 28, 21, 14, 7], # 15 X ] # or # color code #[0, 0, 0, 0, 0, 0, 0, 0, # 0,200, 0, 0, 70, 0, 0, 0, # 0, 0, 0, 0, 60, 0, 0, 0, # 0, 0, 0, 0, 50, 0, 0, 0, # 0, 10, 20, 30, 40, 30, 20, 0, # 0, 0, 0, 80, 0, 0, 0, 0, # 0, 0, 0, 90, 0, 0, 0, 0, # 0, 0, 0,100, 0, 0, 0, 0] def colorWipe(self, color, wait_ms=50): """Wipe color across display a pixel at a time.""" for i in range(self.strip.numPixels()): self.strip.setPixelColor(i, color) self.strip.show() time.sleep(wait_ms / 1000.0) def clear(self, r=0, g=0, b=0): self.colorWipe(Color(r, g, b), 5) def fill(self, col): self.colorWipe(col, 10) def rand(self): l = list(range(self.strip.numPixels())) random.shuffle(l) for i in l: self.strip.setPixelColor(i, Color(random.randint(10, 250), random.randint(10, 250), random.randint(10, 250))) self.strip.show() time.sleep(0.01) def dot(self, num, col): self.strip.setPixelColor(int(num), col) self.strip.show() def show_template(self, num, col): self.clear() for cell in self.numbers[int(num)]: self.strip.setPixelColor(cell, col) self.strip.show()
class neoled: # LED strip configuration: LED_COUNT = 16 # Number of LED pixels. LED_PIN = 10 # GPIO pin connected to the pixels (must support PWM!). LED_FREQ_HZ = 800000 # LED signal frequency in hertz (usually 800khz) LED_DMA = 10 # DMA channel to use for generating signal (try 10) LED_BRIGHTNESS = 255 # Set to 0 for darkest and 255 for brightest LED_INVERT = False # True to invert the signal (when using NPN transistor level shift) LED_CHANNEL = 0 LED_STRIP = ws.SK6812_STRIP_GRBW def __init__(self): # Create NeoPixel object with appropriate configuration. self.strip = PixelStrip(self.LED_COUNT, self.LED_PIN, self.LED_FREQ_HZ, self.LED_DMA, self.LED_INVERT, self.LED_BRIGHTNESS, self.LED_CHANNEL, self.LED_STRIP) # Intialize the library (must be called once before other functions). self.strip.begin() self.colorFill(Color(0, 0, 0, 0)) # Define functions which animate LEDs in various ways. def colorFill(self, color): """Fill strip with color at once.""" for i in range(self.strip.numPixels()): self.strip.setPixelColor(i, color) self.strip.show() def colorWipe(self, color, wait_ms=10): """Wipe color across display a pixel at a time.""" for i in range(self.strip.numPixels()): self.strip.setPixelColor(i, color) self.strip.show() time.sleep(wait_ms / 1000.0) def colorBlink(self, color, blink_ms=20, nblinks=1): for i in range(nblinks): self.colorFill(color) time.sleep(blink_ms / 1000.0) self.colorFill(Color(0, 0, 0, 0)) if i < (nblinks - 1): time.sleep(blink_ms / 1000.0) def colorBlinkPos(self, color, blink_ms=30, nblinks=1, pos=0): for i in range(nblinks): for i in range(self.strip.numPixels()): if ((i + pos) % 7 == 0): self.strip.setPixelColor(i, color) else: self.strip.setPixelColor(i, Color(0, 0, 0, 0)) self.strip.show() time.sleep(blink_ms / 1000.0) self.colorFill(Color(0, 0, 0, 0)) if i < (nblinks - 1): time.sleep(blink_ms / 1000.0) def multColor(self, color, multiplier): white = (color >> 24) & 0xFF red = (color >> 16) & 0xFF green = (color >> 8) & 0xFF blue = color & 0xFF return Color(int(red * multiplier), int(green * multiplier), int(blue * multiplier), int(white * multiplier)) def dualbulb(self, color, pos): dualbulb_pattern = { 0: 0.1, 1: 0.2, 2: 0.5, 3: 1, 4: 0.5, 5: 0.2, 6: 0.5, 7: 1, 8: 0.5, 9: 0.2, 10: 0.1, 11: 0.2, 12: 0.5, 13: 1, 14: 0.5, 15: 0.2, } return self.multColor(color, dualbulb_pattern[pos % 16]) def nightlight(self, color): wait_ms = 25 # Ramp UP 0-0.5 s = 0 for j in range(10): s += 0.05 for i in range(self.strip.numPixels()): self.strip.setPixelColor( i, self.multColor(self.dualbulb(color, i), s)) self.strip.show() time.sleep(wait_ms / 1000.0) for c in range(5): # Ramp UP 0.5-1 s = 0.5 for j in range(10): s += 0.05 for i in range(self.strip.numPixels()): self.strip.setPixelColor( i, self.multColor(self.dualbulb(color, i + c), s)) self.strip.show() time.sleep(wait_ms / 1000.0) # Ramp DOWN 1-05 for j in range(10): s -= 0.05 for i in range(self.strip.numPixels()): self.strip.setPixelColor( i, self.multColor(self.dualbulb(color, i + c), s)) self.strip.show() time.sleep(wait_ms / 1000.0) # Ramp DOWN 0.5-0 for j in range(10): s -= 0.05 for i in range(self.strip.numPixels()): self.strip.setPixelColor( i, self.multColor(self.dualbulb(color, i), s)) self.strip.show() time.sleep(wait_ms / 1000.0) self.colorFill(Color(0, 0, 0)) def wheel(self, pos): """Generate rainbow colors across 0-255 positions.""" if pos < 85: return Color(pos * 3, 255 - pos * 3, 0) elif pos < 170: pos -= 85 return Color(255 - pos * 3, 0, pos * 3) else: pos -= 170 return Color(0, pos * 3, 255 - pos * 3) def rainbow(self, wait_ms=20, iterations=1): """Draw rainbow that fades across all pixels at once.""" for j in range(256 * iterations): for i in range(self.strip.numPixels()): self.strip.setPixelColor(i, wheel((i + j) & 255)) self.strip.show() time.sleep(wait_ms / 1000.0) def rainbowCycle(self, wait_ms=20, iterations=5): """Draw rainbow that uniformly distributes itself across all pixels.""" for j in range(256 * iterations): for i in range(self.strip.numPixels()): self.strip.setPixelColor( i, wheel(((i * 256 // self.strip.numPixels()) + j) & 255)) self.strip.show() time.sleep(wait_ms / 1000.0)
class Led(Thread): # LED strip configuration: LED_COUNT = 95 # Number of LED pixels. LED_PIN = 18 # GPIO pin connected to the pixels (18 uses PWM!). # LED_PIN = 10 # GPIO pin connected to the pixels (10 uses SPI /dev/spidev0.0). LED_FREQ_HZ = 800000 # LED signal frequency in hertz (usually 800khz) LED_DMA = 10 # DMA channel to use for generating signal (try 10) LED_BRIGHTNESS = 170 # Set to 0 for darkest and 255 for brightest LED_INVERT = False # True to invert the signal (when using NPN transistor level shift) LED_CHANNEL = 0 # set to '1' for GPIOs 13, 19, 41, 45 or 53 FRAMERATE = 50 def __init__(self): # Create NeoPixel object with appropriate configuration. self.strip = PixelStrip(self.LED_COUNT, \ self.LED_PIN, \ self.LED_FREQ_HZ, \ self.LED_DMA, \ self.LED_INVERT, \ self.LED_BRIGHTNESS//2, \ self.LED_CHANNEL) # Intialize the library (must be called once before other functions). self.strip.begin() # Variables that store what the LEDs will do self.loop = False # whether the current sequence of frames should be # repeated after completion self.colorSeqs = {} # a dictionary storing color sequences # KEY: the key is arbitrary, to distinguish different color sequences # - It is up to the implementation to determine the key # VAL: a list of colors, stored as integers, that form the sequence # - All values in colorSeqs must have the same length self.seqLen = 0 # the length of color sequences in colorSeqs self.mapping = [] # a list containing integers # these integers correspond to indices in colorSeqs # length of mapping = number of LEDs in the LightBox self.currInd = 0 # an integer marking where in the color sequences the LEDs are self.targetBrightness = self.strip.getBrightness( ) # value storing brightness to be attained # during gradual fade towards it # Initialize these variables for the first time (LEDs off) self.loop = False self.colorSeqs[0] = [0x000000] self.seqLen = 1 self.mapping = [0] * self.strip.numPixels() self.currInd = 0 # These settings will cause the LED's to switch to #000000 (off) once # Start thread that will handle LED changes in the background Thread.__init__(self) self.daemon = True print("Led Strip Initialized") # Continuous loop that handles LED changes registered in mapping and colorSeqs def run(self): while True: refreshStrip = True time.sleep(1.0 / self.FRAMERATE) if self.currInd == self.seqLen: #reached end of sequence if self.loop: self.currInd = 0 #loop to beginning of sequence else: refreshStrip = False if refreshStrip: try: for i in range(self.strip.numPixels()): self.strip.setPixelColor( i, self.colorSeqs[self.mapping[i]][self.currInd]) except KeyError: print("Error: invalid key %d" % self.mapping[i]) continue self.currInd += 1 if self.strip.getBrightness() != self.targetBrightness: self.strip.setBrightness( max( min( self.strip.getBrightness() + (self.FRAMERATE//25) * \ (1 if self.targetBrightness > self.strip.getBrightness() else -1) \ , 255), 0) \ ) if (abs(self.targetBrightness - self.strip.getBrightness())) < (self.FRAMERATE // 25): self.strip.setBrightness(self.targetBrightness) refreshStrip = True if refreshStrip: self.strip.show() # Color Manipulation functions... def solidColor(self, color): ''' Changes LightBox to a solid color, defined by color ''' colorSeqs = {} mapping = [0] * self.strip.numPixels() # Iterate through each led in the strip for currLed in range(self.strip.numPixels()): # Add entry to mapping for the color sequence mapping[currLed] = self.strip.getPixelColor(currLed) # Add sequence to colorSeqs if it doesn't exist already if mapping[currLed] not in colorSeqs: colorSeqs[mapping[currLed]] = \ colorUtil.linear_gradient(mapping[currLed], \ color, \ self.FRAMERATE//4) self.loop = False self.seqLen = self.FRAMERATE // 4 self.currInd = 0 self.mapping = mapping self.colorSeqs = colorSeqs def clear(self): '''clears all leds''' self.solidColor(0) def changeBrightness(self, newBrightnessValue): '''sets brightness of LEDs (0-100)''' self.targetBrightness = int(self.LED_BRIGHTNESS * newBrightnessValue**1.5 / 1000) #1000=100^1.5 def rainbow(self): '''creates a rainbow sequence that loops''' #generates list of colors that cycle in hue numFrames = self.FRAMERATE * 10 # the number is how many seconds per rainbow cycle rainbowColors = [ colorUtil.HSV_to_hex(k / numFrames * 360, 1, 1) for k in range(0, numFrames, 1) ] colorSeqs = {} seqLen = len(rainbowColors) mapping = [0] * self.strip.numPixels() for led in range(self.strip.numPixels()): mapping[led] = led #unique mapping for each led colorSeqs[led] = [0] * seqLen for colorPos in range(seqLen): for led in range(self.strip.numPixels()): colorSeqs[led][colorPos] = rainbowColors[(colorPos + led) % seqLen] self.loop = True self.seqLen = seqLen self.currInd = 0 self.colorSeqs = colorSeqs self.mapping = mapping def sparkle(self, seqLenSeconds=30): '''creates a sparkle sequence that loops''' numFrames = self.FRAMERATE * 1 # the number is how many seconds for average flash deviation = self.FRAMERATE // 2 # random deviation of the flash lengths satChoice = ([0.0]) + ([0.5] * 5) + ( [1] * 50) # weighted probability for saturation # prevents too many 'white' LEDs valChoice = ([0.2]) + ([0.5] * 5) + ( [1] * 10) # weighted probability for value # prevents too many dim LED's colorSeqs = {} seqLen = numFrames * seqLenSeconds mapping = [0] * self.strip.numPixels() for led in range(self.strip.numPixels()): mapping[led] = led # unique mapping for each led colorSeqs[led] = [0] * seqLen for colorPos in range(seqLen): for i in range(random.randrange( 0, 4)): # repeat a random number of times # to create variety led = random.randrange(0, self.strip.numPixels()) if colorSeqs[led][colorPos] != 0: # already a flash at that led continue # don't overwrite it duration = random.randint(numFrames - deviation, numFrames + deviation) hue = random.uniform(0, 360) sat = random.choice(satChoice) val = random.choice(valChoice) for k in range(duration): # fill in colorSeqs for the flash, given by the piecewise function # at https://www.desmos.com/calculator/lmsoc2uoif colorSeqs[led][(colorPos+k)%seqLen] = colorUtil.HSV_to_hex(hue, sat, \ val * ( (3/duration)*k if k < duration/3 \ else (-3/(2*duration))*(k-duration) ) \ ) self.loop = True self.seqLen = seqLen self.currInd = 0 self.colorSeqs = colorSeqs self.mapping = mapping