Raspberry PI controllable Christmas Tree











up vote
19
down vote

favorite
1












After having the scales, thermometer and a coffeemaker connected to the internet, it is finally time for Christmas Tree to become smarter.



Hardware




  • 6ft Christmas Tree


  • An addressable WS2811 LED strip (3x50 was good enough for this tree size)


  • Raspberry Pi Zero W


  • Voltage level shifter (3.3V to 5V)

  • Power Supply


Software




  • used rpi_ws281x Python samples as a base library for controlling the LEDs


  • Flask app served at a specific port which is forwarded to the internet (to control via IFTTT)


  • webcolors library to map between color names and RGB values




Currently, I've only implemented a few actions/patterns:




  • wipe with a specific color (given as a color name)

  • "rainbow" pattern

  • "crazy" pattern (also called "theater chase" in the rpi_ws281x samples)


  • "stop" - turn off - all LEDs black



The Code



Flask part



from flask import Flask

from libs import LEDStrip


app = Flask(__name__)
led_strip = LEDStrip(count=150)


@app.route('/wipe/<color>')
def wipe_color(color):
led_strip.color_wipe(color)

return "Wipe with {color} - success!".format(color=color)


@app.route('/rainbow')
def rainbow():
led_strip.rainbow()
led_strip.rainbow_cycle()

return "Rainbow animation executed successfully!"


@app.route('/crazy')
def crazy():
led_strip.theater_chase_rainbow()

return "Crazy christmas tree animation executed successfully!"


@app.route('/stop')
def stop():
led_strip.clear()

return "Christmas tree was turned off!"


libs.py



import time

from webcolors import name_to_rgb
from neopixel import *

from exceptions import ColorNotFoundException


def wheel(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)


class LEDStrip:
def __init__(self, count,
pin=18, frequency=800000,
dma=5, brightness=255,
invert=False, channel=0,
strip_type=ws.WS2811_STRIP_RGB):
"""
LED strip abstraction class.

:param count: number of LED pixels
:param pin: GPIO pin connected to the pixels (18 uses PWM!)
:param frequency: LED signal frequency in hertz (usually 800khz)
:param dma: DMA channel to use for generating signal
:param brightness: set to 0 for darkest and 255 for brightest
:param invert: True to invert the signal (when using NPN transistor level shift)
:param channel: set to '1' for GPIOs 13, 19, 41, 45 or 53
:param strip_type: strip type and colour ordering
"""

self.led_count = count
self.strip = Adafruit_NeoPixel(count, pin, frequency, dma, invert, brightness, channel, strip_type)
self.strip.begin()

def clear(self):
self.color_wipe("black")

def color_wipe(self, color, wait_ms=30):
"""Wipe color across display a pixel at a time."""
try:
color_value = Color(*name_to_rgb(color))
except ValueError:
raise ColorNotFoundException("Color {color} not found.".format(color=color))

for led_number in range(self.led_count):
self.strip.setPixelColor(led_number, color_value)
self.strip.show()
time.sleep(wait_ms / 1000.0)

def theater_chase(self, color, wait_ms=50, iterations=10):
"""Movie theater light style chaser animation."""
for j in range(iterations):
for q in range(3):
for i in range(0, self.led_count, 3):
self.strip.setPixelColor(i + q, color)

self.strip.show()
time.sleep(wait_ms / 1000.0)

for led_number in range(0, self.led_count, 3):
self.strip.setPixelColor(led_number + q, 0)

def rainbow(self, wait_ms=20, iterations=1):
"""Draw rainbow that fades across all pixels at once."""
for j in range(256 * iterations):
for led_number in range(self.led_count):
self.strip.setPixelColor(led_number, wheel((led_number + j) & 255))

self.strip.show()
time.sleep(wait_ms / 1000.0)

def rainbow_cycle(self, wait_ms=20, iterations=5):
"""Draw rainbow that uniformly distributes itself across all pixels."""
for j in range(256 * iterations):
for led_number in range(self.led_count):
self.strip.setPixelColor(led_number, wheel((int(led_number * 256 / self.led_count) + j) & 255))

self.strip.show()
time.sleep(wait_ms / 1000.0)

def theater_chase_rainbow(self, wait_ms=50):
"""Rainbow movie theater light style chaser animation."""
for j in range(256):
for q in range(3):
for led_number in range(0, self.led_count, 3):
self.strip.setPixelColor(led_number + q, wheel((led_number + j) % 255))

self.strip.show()
time.sleep(wait_ms / 1000.0)

for led_number in range(0, self.led_count, 3):
self.strip.setPixelColor(led_number + q, 0)


exceptions.py



class ChristmasError(BaseException):
pass


class ColorNotFoundException(ChristmasError):
pass


Aside from Google Home & Alexa voice control abilities like "Okay Google - Turn the Christmas Tree green" and "Okay Google - Make a rainbow", it is a lot of fun connecting that with motion sensors and other smart devices.



What do you think about the overall design of the LEDStrip class and the flask app? What do you think I can improve? I would also appreciate any ideas about the ways I can continue making it more fun this Christmas.



Note that there is already a plenty of things to address security-wise.










share|improve this question
























  • I'm wondering why your ColourNotFoundException needs to call Christmas Error. Can it not be just set up as class ColourNotFoundException(BaseException): pass. P.S Sorry if the question is stupid, I didn't even know you could do that.
    – 13ros27
    Dec 23 '17 at 9:43










  • Or could you do ColourNotFoundException = Exception("")
    – 13ros27
    Dec 23 '17 at 10:02










  • @13ros27 I've just a got a habit of defining custom exceptions this way, to ease debugging and to provide better readability in error-handling and modularity. In my case, it's just one custom exception except the base one but I expect (pun intended) the module to grow and accounted for that..thanks!
    – alecxe
    Dec 23 '17 at 20:23

















up vote
19
down vote

favorite
1












After having the scales, thermometer and a coffeemaker connected to the internet, it is finally time for Christmas Tree to become smarter.



Hardware




  • 6ft Christmas Tree


  • An addressable WS2811 LED strip (3x50 was good enough for this tree size)


  • Raspberry Pi Zero W


  • Voltage level shifter (3.3V to 5V)

  • Power Supply


Software




  • used rpi_ws281x Python samples as a base library for controlling the LEDs


  • Flask app served at a specific port which is forwarded to the internet (to control via IFTTT)


  • webcolors library to map between color names and RGB values




Currently, I've only implemented a few actions/patterns:




  • wipe with a specific color (given as a color name)

  • "rainbow" pattern

  • "crazy" pattern (also called "theater chase" in the rpi_ws281x samples)


  • "stop" - turn off - all LEDs black



The Code



Flask part



from flask import Flask

from libs import LEDStrip


app = Flask(__name__)
led_strip = LEDStrip(count=150)


@app.route('/wipe/<color>')
def wipe_color(color):
led_strip.color_wipe(color)

return "Wipe with {color} - success!".format(color=color)


@app.route('/rainbow')
def rainbow():
led_strip.rainbow()
led_strip.rainbow_cycle()

return "Rainbow animation executed successfully!"


@app.route('/crazy')
def crazy():
led_strip.theater_chase_rainbow()

return "Crazy christmas tree animation executed successfully!"


@app.route('/stop')
def stop():
led_strip.clear()

return "Christmas tree was turned off!"


libs.py



import time

from webcolors import name_to_rgb
from neopixel import *

from exceptions import ColorNotFoundException


def wheel(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)


class LEDStrip:
def __init__(self, count,
pin=18, frequency=800000,
dma=5, brightness=255,
invert=False, channel=0,
strip_type=ws.WS2811_STRIP_RGB):
"""
LED strip abstraction class.

:param count: number of LED pixels
:param pin: GPIO pin connected to the pixels (18 uses PWM!)
:param frequency: LED signal frequency in hertz (usually 800khz)
:param dma: DMA channel to use for generating signal
:param brightness: set to 0 for darkest and 255 for brightest
:param invert: True to invert the signal (when using NPN transistor level shift)
:param channel: set to '1' for GPIOs 13, 19, 41, 45 or 53
:param strip_type: strip type and colour ordering
"""

self.led_count = count
self.strip = Adafruit_NeoPixel(count, pin, frequency, dma, invert, brightness, channel, strip_type)
self.strip.begin()

def clear(self):
self.color_wipe("black")

def color_wipe(self, color, wait_ms=30):
"""Wipe color across display a pixel at a time."""
try:
color_value = Color(*name_to_rgb(color))
except ValueError:
raise ColorNotFoundException("Color {color} not found.".format(color=color))

for led_number in range(self.led_count):
self.strip.setPixelColor(led_number, color_value)
self.strip.show()
time.sleep(wait_ms / 1000.0)

def theater_chase(self, color, wait_ms=50, iterations=10):
"""Movie theater light style chaser animation."""
for j in range(iterations):
for q in range(3):
for i in range(0, self.led_count, 3):
self.strip.setPixelColor(i + q, color)

self.strip.show()
time.sleep(wait_ms / 1000.0)

for led_number in range(0, self.led_count, 3):
self.strip.setPixelColor(led_number + q, 0)

def rainbow(self, wait_ms=20, iterations=1):
"""Draw rainbow that fades across all pixels at once."""
for j in range(256 * iterations):
for led_number in range(self.led_count):
self.strip.setPixelColor(led_number, wheel((led_number + j) & 255))

self.strip.show()
time.sleep(wait_ms / 1000.0)

def rainbow_cycle(self, wait_ms=20, iterations=5):
"""Draw rainbow that uniformly distributes itself across all pixels."""
for j in range(256 * iterations):
for led_number in range(self.led_count):
self.strip.setPixelColor(led_number, wheel((int(led_number * 256 / self.led_count) + j) & 255))

self.strip.show()
time.sleep(wait_ms / 1000.0)

def theater_chase_rainbow(self, wait_ms=50):
"""Rainbow movie theater light style chaser animation."""
for j in range(256):
for q in range(3):
for led_number in range(0, self.led_count, 3):
self.strip.setPixelColor(led_number + q, wheel((led_number + j) % 255))

self.strip.show()
time.sleep(wait_ms / 1000.0)

for led_number in range(0, self.led_count, 3):
self.strip.setPixelColor(led_number + q, 0)


exceptions.py



class ChristmasError(BaseException):
pass


class ColorNotFoundException(ChristmasError):
pass


Aside from Google Home & Alexa voice control abilities like "Okay Google - Turn the Christmas Tree green" and "Okay Google - Make a rainbow", it is a lot of fun connecting that with motion sensors and other smart devices.



What do you think about the overall design of the LEDStrip class and the flask app? What do you think I can improve? I would also appreciate any ideas about the ways I can continue making it more fun this Christmas.



Note that there is already a plenty of things to address security-wise.










share|improve this question
























  • I'm wondering why your ColourNotFoundException needs to call Christmas Error. Can it not be just set up as class ColourNotFoundException(BaseException): pass. P.S Sorry if the question is stupid, I didn't even know you could do that.
    – 13ros27
    Dec 23 '17 at 9:43










  • Or could you do ColourNotFoundException = Exception("")
    – 13ros27
    Dec 23 '17 at 10:02










  • @13ros27 I've just a got a habit of defining custom exceptions this way, to ease debugging and to provide better readability in error-handling and modularity. In my case, it's just one custom exception except the base one but I expect (pun intended) the module to grow and accounted for that..thanks!
    – alecxe
    Dec 23 '17 at 20:23















up vote
19
down vote

favorite
1









up vote
19
down vote

favorite
1






1





After having the scales, thermometer and a coffeemaker connected to the internet, it is finally time for Christmas Tree to become smarter.



Hardware




  • 6ft Christmas Tree


  • An addressable WS2811 LED strip (3x50 was good enough for this tree size)


  • Raspberry Pi Zero W


  • Voltage level shifter (3.3V to 5V)

  • Power Supply


Software




  • used rpi_ws281x Python samples as a base library for controlling the LEDs


  • Flask app served at a specific port which is forwarded to the internet (to control via IFTTT)


  • webcolors library to map between color names and RGB values




Currently, I've only implemented a few actions/patterns:




  • wipe with a specific color (given as a color name)

  • "rainbow" pattern

  • "crazy" pattern (also called "theater chase" in the rpi_ws281x samples)


  • "stop" - turn off - all LEDs black



The Code



Flask part



from flask import Flask

from libs import LEDStrip


app = Flask(__name__)
led_strip = LEDStrip(count=150)


@app.route('/wipe/<color>')
def wipe_color(color):
led_strip.color_wipe(color)

return "Wipe with {color} - success!".format(color=color)


@app.route('/rainbow')
def rainbow():
led_strip.rainbow()
led_strip.rainbow_cycle()

return "Rainbow animation executed successfully!"


@app.route('/crazy')
def crazy():
led_strip.theater_chase_rainbow()

return "Crazy christmas tree animation executed successfully!"


@app.route('/stop')
def stop():
led_strip.clear()

return "Christmas tree was turned off!"


libs.py



import time

from webcolors import name_to_rgb
from neopixel import *

from exceptions import ColorNotFoundException


def wheel(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)


class LEDStrip:
def __init__(self, count,
pin=18, frequency=800000,
dma=5, brightness=255,
invert=False, channel=0,
strip_type=ws.WS2811_STRIP_RGB):
"""
LED strip abstraction class.

:param count: number of LED pixels
:param pin: GPIO pin connected to the pixels (18 uses PWM!)
:param frequency: LED signal frequency in hertz (usually 800khz)
:param dma: DMA channel to use for generating signal
:param brightness: set to 0 for darkest and 255 for brightest
:param invert: True to invert the signal (when using NPN transistor level shift)
:param channel: set to '1' for GPIOs 13, 19, 41, 45 or 53
:param strip_type: strip type and colour ordering
"""

self.led_count = count
self.strip = Adafruit_NeoPixel(count, pin, frequency, dma, invert, brightness, channel, strip_type)
self.strip.begin()

def clear(self):
self.color_wipe("black")

def color_wipe(self, color, wait_ms=30):
"""Wipe color across display a pixel at a time."""
try:
color_value = Color(*name_to_rgb(color))
except ValueError:
raise ColorNotFoundException("Color {color} not found.".format(color=color))

for led_number in range(self.led_count):
self.strip.setPixelColor(led_number, color_value)
self.strip.show()
time.sleep(wait_ms / 1000.0)

def theater_chase(self, color, wait_ms=50, iterations=10):
"""Movie theater light style chaser animation."""
for j in range(iterations):
for q in range(3):
for i in range(0, self.led_count, 3):
self.strip.setPixelColor(i + q, color)

self.strip.show()
time.sleep(wait_ms / 1000.0)

for led_number in range(0, self.led_count, 3):
self.strip.setPixelColor(led_number + q, 0)

def rainbow(self, wait_ms=20, iterations=1):
"""Draw rainbow that fades across all pixels at once."""
for j in range(256 * iterations):
for led_number in range(self.led_count):
self.strip.setPixelColor(led_number, wheel((led_number + j) & 255))

self.strip.show()
time.sleep(wait_ms / 1000.0)

def rainbow_cycle(self, wait_ms=20, iterations=5):
"""Draw rainbow that uniformly distributes itself across all pixels."""
for j in range(256 * iterations):
for led_number in range(self.led_count):
self.strip.setPixelColor(led_number, wheel((int(led_number * 256 / self.led_count) + j) & 255))

self.strip.show()
time.sleep(wait_ms / 1000.0)

def theater_chase_rainbow(self, wait_ms=50):
"""Rainbow movie theater light style chaser animation."""
for j in range(256):
for q in range(3):
for led_number in range(0, self.led_count, 3):
self.strip.setPixelColor(led_number + q, wheel((led_number + j) % 255))

self.strip.show()
time.sleep(wait_ms / 1000.0)

for led_number in range(0, self.led_count, 3):
self.strip.setPixelColor(led_number + q, 0)


exceptions.py



class ChristmasError(BaseException):
pass


class ColorNotFoundException(ChristmasError):
pass


Aside from Google Home & Alexa voice control abilities like "Okay Google - Turn the Christmas Tree green" and "Okay Google - Make a rainbow", it is a lot of fun connecting that with motion sensors and other smart devices.



What do you think about the overall design of the LEDStrip class and the flask app? What do you think I can improve? I would also appreciate any ideas about the ways I can continue making it more fun this Christmas.



Note that there is already a plenty of things to address security-wise.










share|improve this question















After having the scales, thermometer and a coffeemaker connected to the internet, it is finally time for Christmas Tree to become smarter.



Hardware




  • 6ft Christmas Tree


  • An addressable WS2811 LED strip (3x50 was good enough for this tree size)


  • Raspberry Pi Zero W


  • Voltage level shifter (3.3V to 5V)

  • Power Supply


Software




  • used rpi_ws281x Python samples as a base library for controlling the LEDs


  • Flask app served at a specific port which is forwarded to the internet (to control via IFTTT)


  • webcolors library to map between color names and RGB values




Currently, I've only implemented a few actions/patterns:




  • wipe with a specific color (given as a color name)

  • "rainbow" pattern

  • "crazy" pattern (also called "theater chase" in the rpi_ws281x samples)


  • "stop" - turn off - all LEDs black



The Code



Flask part



from flask import Flask

from libs import LEDStrip


app = Flask(__name__)
led_strip = LEDStrip(count=150)


@app.route('/wipe/<color>')
def wipe_color(color):
led_strip.color_wipe(color)

return "Wipe with {color} - success!".format(color=color)


@app.route('/rainbow')
def rainbow():
led_strip.rainbow()
led_strip.rainbow_cycle()

return "Rainbow animation executed successfully!"


@app.route('/crazy')
def crazy():
led_strip.theater_chase_rainbow()

return "Crazy christmas tree animation executed successfully!"


@app.route('/stop')
def stop():
led_strip.clear()

return "Christmas tree was turned off!"


libs.py



import time

from webcolors import name_to_rgb
from neopixel import *

from exceptions import ColorNotFoundException


def wheel(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)


class LEDStrip:
def __init__(self, count,
pin=18, frequency=800000,
dma=5, brightness=255,
invert=False, channel=0,
strip_type=ws.WS2811_STRIP_RGB):
"""
LED strip abstraction class.

:param count: number of LED pixels
:param pin: GPIO pin connected to the pixels (18 uses PWM!)
:param frequency: LED signal frequency in hertz (usually 800khz)
:param dma: DMA channel to use for generating signal
:param brightness: set to 0 for darkest and 255 for brightest
:param invert: True to invert the signal (when using NPN transistor level shift)
:param channel: set to '1' for GPIOs 13, 19, 41, 45 or 53
:param strip_type: strip type and colour ordering
"""

self.led_count = count
self.strip = Adafruit_NeoPixel(count, pin, frequency, dma, invert, brightness, channel, strip_type)
self.strip.begin()

def clear(self):
self.color_wipe("black")

def color_wipe(self, color, wait_ms=30):
"""Wipe color across display a pixel at a time."""
try:
color_value = Color(*name_to_rgb(color))
except ValueError:
raise ColorNotFoundException("Color {color} not found.".format(color=color))

for led_number in range(self.led_count):
self.strip.setPixelColor(led_number, color_value)
self.strip.show()
time.sleep(wait_ms / 1000.0)

def theater_chase(self, color, wait_ms=50, iterations=10):
"""Movie theater light style chaser animation."""
for j in range(iterations):
for q in range(3):
for i in range(0, self.led_count, 3):
self.strip.setPixelColor(i + q, color)

self.strip.show()
time.sleep(wait_ms / 1000.0)

for led_number in range(0, self.led_count, 3):
self.strip.setPixelColor(led_number + q, 0)

def rainbow(self, wait_ms=20, iterations=1):
"""Draw rainbow that fades across all pixels at once."""
for j in range(256 * iterations):
for led_number in range(self.led_count):
self.strip.setPixelColor(led_number, wheel((led_number + j) & 255))

self.strip.show()
time.sleep(wait_ms / 1000.0)

def rainbow_cycle(self, wait_ms=20, iterations=5):
"""Draw rainbow that uniformly distributes itself across all pixels."""
for j in range(256 * iterations):
for led_number in range(self.led_count):
self.strip.setPixelColor(led_number, wheel((int(led_number * 256 / self.led_count) + j) & 255))

self.strip.show()
time.sleep(wait_ms / 1000.0)

def theater_chase_rainbow(self, wait_ms=50):
"""Rainbow movie theater light style chaser animation."""
for j in range(256):
for q in range(3):
for led_number in range(0, self.led_count, 3):
self.strip.setPixelColor(led_number + q, wheel((led_number + j) % 255))

self.strip.show()
time.sleep(wait_ms / 1000.0)

for led_number in range(0, self.led_count, 3):
self.strip.setPixelColor(led_number + q, 0)


exceptions.py



class ChristmasError(BaseException):
pass


class ColorNotFoundException(ChristmasError):
pass


Aside from Google Home & Alexa voice control abilities like "Okay Google - Turn the Christmas Tree green" and "Okay Google - Make a rainbow", it is a lot of fun connecting that with motion sensors and other smart devices.



What do you think about the overall design of the LEDStrip class and the flask app? What do you think I can improve? I would also appreciate any ideas about the ways I can continue making it more fun this Christmas.



Note that there is already a plenty of things to address security-wise.







python python-2.x flask raspberry-pi






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Dec 23 '17 at 15:51

























asked Dec 23 '17 at 4:30









alecxe

14.7k53378




14.7k53378












  • I'm wondering why your ColourNotFoundException needs to call Christmas Error. Can it not be just set up as class ColourNotFoundException(BaseException): pass. P.S Sorry if the question is stupid, I didn't even know you could do that.
    – 13ros27
    Dec 23 '17 at 9:43










  • Or could you do ColourNotFoundException = Exception("")
    – 13ros27
    Dec 23 '17 at 10:02










  • @13ros27 I've just a got a habit of defining custom exceptions this way, to ease debugging and to provide better readability in error-handling and modularity. In my case, it's just one custom exception except the base one but I expect (pun intended) the module to grow and accounted for that..thanks!
    – alecxe
    Dec 23 '17 at 20:23




















  • I'm wondering why your ColourNotFoundException needs to call Christmas Error. Can it not be just set up as class ColourNotFoundException(BaseException): pass. P.S Sorry if the question is stupid, I didn't even know you could do that.
    – 13ros27
    Dec 23 '17 at 9:43










  • Or could you do ColourNotFoundException = Exception("")
    – 13ros27
    Dec 23 '17 at 10:02










  • @13ros27 I've just a got a habit of defining custom exceptions this way, to ease debugging and to provide better readability in error-handling and modularity. In my case, it's just one custom exception except the base one but I expect (pun intended) the module to grow and accounted for that..thanks!
    – alecxe
    Dec 23 '17 at 20:23


















I'm wondering why your ColourNotFoundException needs to call Christmas Error. Can it not be just set up as class ColourNotFoundException(BaseException): pass. P.S Sorry if the question is stupid, I didn't even know you could do that.
– 13ros27
Dec 23 '17 at 9:43




I'm wondering why your ColourNotFoundException needs to call Christmas Error. Can it not be just set up as class ColourNotFoundException(BaseException): pass. P.S Sorry if the question is stupid, I didn't even know you could do that.
– 13ros27
Dec 23 '17 at 9:43












Or could you do ColourNotFoundException = Exception("")
– 13ros27
Dec 23 '17 at 10:02




Or could you do ColourNotFoundException = Exception("")
– 13ros27
Dec 23 '17 at 10:02












@13ros27 I've just a got a habit of defining custom exceptions this way, to ease debugging and to provide better readability in error-handling and modularity. In my case, it's just one custom exception except the base one but I expect (pun intended) the module to grow and accounted for that..thanks!
– alecxe
Dec 23 '17 at 20:23






@13ros27 I've just a got a habit of defining custom exceptions this way, to ease debugging and to provide better readability in error-handling and modularity. In my case, it's just one custom exception except the base one but I expect (pun intended) the module to grow and accounted for that..thanks!
– alecxe
Dec 23 '17 at 20:23












1 Answer
1






active

oldest

votes

















up vote
12
down vote



accepted
+50











  • I would suggest to separate the concerns of coloring and animating. Now, in particular theater_chase_rainbow duplicates code from other methods. Instead, have theater_chase take a color array as parameter. If you then add some animation styles and color schemes you can have $O(n^2)$ amount of fun trying all combinations.


  • It seems to me that in this code i + q can overflow led_count if it is not a multiple of 3:



    for i in range(0, self.led_count, 3):
    self.strip.setPixelColor(i + q, color)


    Instead, I would use



    for i in range(q, self.led_count, 3):
    self.strip.setPixelColor(i, color)







share|improve this answer























    Your Answer





    StackExchange.ifUsing("editor", function () {
    return StackExchange.using("mathjaxEditing", function () {
    StackExchange.MarkdownEditor.creationCallbacks.add(function (editor, postfix) {
    StackExchange.mathjaxEditing.prepareWmdForMathJax(editor, postfix, [["\$", "\$"]]);
    });
    });
    }, "mathjax-editing");

    StackExchange.ifUsing("editor", function () {
    StackExchange.using("externalEditor", function () {
    StackExchange.using("snippets", function () {
    StackExchange.snippets.init();
    });
    });
    }, "code-snippets");

    StackExchange.ready(function() {
    var channelOptions = {
    tags: "".split(" "),
    id: "196"
    };
    initTagRenderer("".split(" "), "".split(" "), channelOptions);

    StackExchange.using("externalEditor", function() {
    // Have to fire editor after snippets, if snippets enabled
    if (StackExchange.settings.snippets.snippetsEnabled) {
    StackExchange.using("snippets", function() {
    createEditor();
    });
    }
    else {
    createEditor();
    }
    });

    function createEditor() {
    StackExchange.prepareEditor({
    heartbeatType: 'answer',
    autoActivateHeartbeat: false,
    convertImagesToLinks: false,
    noModals: true,
    showLowRepImageUploadWarning: true,
    reputationToPostImages: null,
    bindNavPrevention: true,
    postfix: "",
    imageUploader: {
    brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
    contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
    allowUrls: true
    },
    onDemand: true,
    discardSelector: ".discard-answer"
    ,immediatelyShowMarkdownHelp:true
    });


    }
    });














    draft saved

    draft discarded


















    StackExchange.ready(
    function () {
    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f183485%2fraspberry-pi-controllable-christmas-tree%23new-answer', 'question_page');
    }
    );

    Post as a guest















    Required, but never shown

























    1 Answer
    1






    active

    oldest

    votes








    1 Answer
    1






    active

    oldest

    votes









    active

    oldest

    votes






    active

    oldest

    votes








    up vote
    12
    down vote



    accepted
    +50











    • I would suggest to separate the concerns of coloring and animating. Now, in particular theater_chase_rainbow duplicates code from other methods. Instead, have theater_chase take a color array as parameter. If you then add some animation styles and color schemes you can have $O(n^2)$ amount of fun trying all combinations.


    • It seems to me that in this code i + q can overflow led_count if it is not a multiple of 3:



      for i in range(0, self.led_count, 3):
      self.strip.setPixelColor(i + q, color)


      Instead, I would use



      for i in range(q, self.led_count, 3):
      self.strip.setPixelColor(i, color)







    share|improve this answer



























      up vote
      12
      down vote



      accepted
      +50











      • I would suggest to separate the concerns of coloring and animating. Now, in particular theater_chase_rainbow duplicates code from other methods. Instead, have theater_chase take a color array as parameter. If you then add some animation styles and color schemes you can have $O(n^2)$ amount of fun trying all combinations.


      • It seems to me that in this code i + q can overflow led_count if it is not a multiple of 3:



        for i in range(0, self.led_count, 3):
        self.strip.setPixelColor(i + q, color)


        Instead, I would use



        for i in range(q, self.led_count, 3):
        self.strip.setPixelColor(i, color)







      share|improve this answer

























        up vote
        12
        down vote



        accepted
        +50







        up vote
        12
        down vote



        accepted
        +50




        +50





        • I would suggest to separate the concerns of coloring and animating. Now, in particular theater_chase_rainbow duplicates code from other methods. Instead, have theater_chase take a color array as parameter. If you then add some animation styles and color schemes you can have $O(n^2)$ amount of fun trying all combinations.


        • It seems to me that in this code i + q can overflow led_count if it is not a multiple of 3:



          for i in range(0, self.led_count, 3):
          self.strip.setPixelColor(i + q, color)


          Instead, I would use



          for i in range(q, self.led_count, 3):
          self.strip.setPixelColor(i, color)







        share|improve this answer















        • I would suggest to separate the concerns of coloring and animating. Now, in particular theater_chase_rainbow duplicates code from other methods. Instead, have theater_chase take a color array as parameter. If you then add some animation styles and color schemes you can have $O(n^2)$ amount of fun trying all combinations.


        • It seems to me that in this code i + q can overflow led_count if it is not a multiple of 3:



          for i in range(0, self.led_count, 3):
          self.strip.setPixelColor(i + q, color)


          Instead, I would use



          for i in range(q, self.led_count, 3):
          self.strip.setPixelColor(i, color)








        share|improve this answer














        share|improve this answer



        share|improve this answer








        edited 12 mins ago









        alecxe

        14.7k53378




        14.7k53378










        answered Dec 23 '17 at 12:37









        Janne Karila

        9,7031430




        9,7031430






























            draft saved

            draft discarded




















































            Thanks for contributing an answer to Code Review Stack Exchange!


            • Please be sure to answer the question. Provide details and share your research!

            But avoid



            • Asking for help, clarification, or responding to other answers.

            • Making statements based on opinion; back them up with references or personal experience.


            Use MathJax to format equations. MathJax reference.


            To learn more, see our tips on writing great answers.





            Some of your past answers have not been well-received, and you're in danger of being blocked from answering.


            Please pay close attention to the following guidance:


            • Please be sure to answer the question. Provide details and share your research!

            But avoid



            • Asking for help, clarification, or responding to other answers.

            • Making statements based on opinion; back them up with references or personal experience.


            To learn more, see our tips on writing great answers.




            draft saved


            draft discarded














            StackExchange.ready(
            function () {
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f183485%2fraspberry-pi-controllable-christmas-tree%23new-answer', 'question_page');
            }
            );

            Post as a guest















            Required, but never shown





















































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown

































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown







            Popular posts from this blog

            Feedback on college project

            Futebolista

            Albești (Vaslui)