led_pillar

Documentation: http://frombelow.net/projects/led_pillar/
Clone: git clone https://git.frombelow.net/led_pillar.git
Log | Files | Refs | Submodules | README | LICENSE

commit 99e164bfd0c52ca416745e8eab05bc2fefe8d41b
parent d946424604e3872f9e28c087d26e82a22f5100df
Author: Gerd Beuster <gerd@frombelow.net>
Date:   Sat,  1 Aug 2020 11:32:04 +0200

Adapted for Raspberry Pi Zero W

Diffstat:
AREADME.txt | 25+++++++++++++++++++++++++
Mflowing_colors.py | 4++--
Mmain.py | 54+++++++++++++++++++++++++++++++++++-------------------
Mpatterns.py | 19+++++++++----------
Mtemplates/index.html | 15++++++++-------
5 files changed, 79 insertions(+), 38 deletions(-)

diff --git a/README.txt b/README.txt @@ -0,0 +1,25 @@ +Installation +============ + +The following packages are required: +python3-flask python3-pip python3-rpi.gpio python3-pygame xvfb + +Run as root: +pip3 install rpi_ws281x + +Running +======= + +Start manually with +sudo FLASK_APP=main.py flask run --host=0.0.0.0 + +To start automatically, add +cd /home/pi/20191224_raspi_ws2811/; FLASK_APP=main.py nohup flask run --host=0.0.0.0 & +to rc.local. + +BUGS +==== + +When connecting LED strip via SPI (Pin 10), some patterns turn the LED +strip on with full power. Do not use! Add a 5 A fuse in power line of +LED strip! diff --git a/flowing_colors.py b/flowing_colors.py @@ -119,7 +119,7 @@ class FlowingColorsRGB(patterns.Pattern): self.strip.setPixelColor(self.xy2i(x, y), Color(int(r[x][y]), int(g[x][y]), int(b[x][y]))) self.strip.show() - time.sleep(.1) + # time.sleep(.1) def sin_x_y_avg(self, period_offset, m_out): # period_offset are passed as instances of RandomWalker. We have to get the @@ -168,4 +168,4 @@ class FlowingColorsHSV(FlowingColorsRGB): (r, g, b) = hsv2rgb((h[x][y]+self.hue_offset.val) % 360, 1, 1) self.strip.setPixelColor(self.xy2i(x, y), Color(int(r), int(g), int(b))) self.strip.show() - time.sleep(.1) + # time.sleep(.1) diff --git a/main.py b/main.py @@ -36,15 +36,21 @@ LED_MATRIX_WIDTH = 34.7 LED_MATRIX_HEIGHT = 21 LED_STRIP_SNAKE = False -# LED_PIN = 18 # GPIO pin connected to the pixels (18 uses PWM!) - requires root! -LED_PIN = 10 # GPIO pin connected to the pixels (10 uses SPI /dev/spidev0.0) - user must be in group gpio! +LED_PIN = 18 # GPIO pin connected to the pixels (18 uses PWM!) - requires root! +# WARNING! Does not work reliably when connected via SPI interface. +# LED strip turns full power with some patterns! DO NOT USE! +# LED_PIN = 10 # GPIO pin connected to the pixels (10 uses SPI /dev/spidev0.0) - user must be in group gpio! LED_FREQ_HZ = 800000 # LED signal frequency in hertz (usually 800khz) LED_DMA = 10 # DMA channel to use for generating signal (try 10) # Set to 0 for darkest and 255 for brightest # LED_BRIGHTNESS = 255 +# LED_BRIGHTNESS = 128 +# LED_BRIGHTNESS = 96 # Max brightness for 720 LEDs with a 5 A fuse +# LED_BRIGHTNESS = 64 +# LED_BRIGHTNESS = 32 # LED_BRIGHTNESS = 16 -LED_BRIGHTNESS = 8 -# LED_BRIGHTNESS = 4 +# LED_BRIGHTNESS = 8 +LED_BRIGHTNESS = 4 # LED_BRIGHTNESS = 2 # LED_BRIGHTNESS = 1 LED_INVERT = False # True to invert the signal (when using NPN transistor level shift) @@ -59,15 +65,17 @@ LED_CHANNEL = 0 # set to '1' for GPIOs 13, 19, 41, 45 or 53 # numbers can be used to pass additional information for a specific # mode. -MODE_RGB = 0 -MODE_WORM = 1 -MODE_CELLULAR_AUTOMATON = 2 -MODE_BLUE_GREEN_FLAMES = 3 -MODE_FLOW_RGB = 4 -MODE_FLOW_HSV = 5 -MODE_TEST_PATTERN = 6 - -mode = [MODE_BLUE_GREEN_FLAMES] +MODE_OFF = 0 +MODE_RGB = 1 +MODE_WORM = 2 +MODE_CELLULAR_AUTOMATON = 3 +MODE_BLUE_GREEN_FLAMES = 4 +MODE_FLOW_RGB = 5 +MODE_FLOW_HSV = 6 +MODE_TEST_PATTERN = 7 + +mode = [MODE_OFF] +#mode = [MODE_BLUE_GREEN_FLAMES] #mode = [MODE_WORM] #mode = [MODE_CELLULAR_AUTOMATON] #mode = [MODE_FLOW_RGB] @@ -91,6 +99,7 @@ def run(cmd_queue=None): p.stop() current_mode = mode p = { + MODE_OFF : patterns.Off, MODE_RGB : patterns.RGB, MODE_WORM : patterns.Worm, MODE_CELLULAR_AUTOMATON : cellular_automaton.CellularAutomaton, @@ -112,19 +121,27 @@ run.start() # Run webserver in this process app = Flask(__name__) +# Default colors +red = 0 +green = 0 +blue = 0 @app.route('/', methods=['GET', 'POST']) @app.route('/index.php', methods=['GET', 'POST']) def hello_world(): # In general, we accept both GET and POST request, # but for technical reasons, RGB values come only as GET requests. - (r, g, b) = (int(request.args.get('red', '0')), - int(request.args.get('green', '0')), - int(request.args.get('blue', '0'))) + global red + global green + global blue + (red, green, blue) = (int(request.args.get('red', red)), + int(request.args.get('green', green)), + int(request.args.get('blue', blue))) mode = request.args.get('mode', None) if not mode: mode = request.form.get('mode', None) if mode != None: - mode_number = {'rgb': [MODE_RGB, r, g, b], + mode_number = {'off': [MODE_OFF], + 'rgb': [MODE_RGB, red, green, blue], 'worm': [MODE_WORM], 'cellular': [MODE_CELLULAR_AUTOMATON], 'flames': [MODE_BLUE_GREEN_FLAMES], @@ -133,5 +150,4 @@ def hello_world(): 'test': [MODE_TEST_PATTERN] }[mode] cmd_queue.put(mode_number) - # pdb.set_trace() - return render_template('index.html') + return render_template('index.html', red=red, green=green, blue=blue) diff --git a/patterns.py b/patterns.py @@ -43,6 +43,10 @@ class Pattern(): i += x return math.floor(i) +class Off(Pattern): + def __init__(self, strip, led_matrix_width, led_matrix_height, led_strip_snake, opts=None): + Pattern.__init__(self, strip=strip, led_matrix_width=led_matrix_width, led_matrix_height=led_matrix_height, led_strip_snake = led_strip_snake, opts=opts) + self.clear_strip() class TestPattern(Pattern): @@ -52,12 +56,6 @@ class TestPattern(Pattern): def __init__(self, strip, led_matrix_width, led_matrix_height, led_strip_snake, opts=None): Pattern.__init__(self, strip=strip, led_matrix_width=led_matrix_width, led_matrix_height=led_matrix_height, led_strip_snake = led_strip_snake, opts=opts) - # Initialize dummy display - os.environ["SDL_VIDEODRIVER"] = "dummy" - subprocess.Popen(["Xvfb", ":1", "-screen", "0", "1024x768x24"], - stderr=subprocess.DEVNULL) - time.sleep(1) - os.environ["DISPLAY"] = ":1" pygame.display.init() self.x = 0 @@ -81,10 +79,12 @@ class TestPattern(Pattern): class RGB(Pattern): def __init__(self, strip, led_matrix_width, led_matrix_height, led_strip_snake, opts=None): Pattern.__init__(self, strip=strip, led_matrix_width=led_matrix_width, led_matrix_height=led_matrix_height, led_strip_snake = led_strip_snake, opts=opts) - (r, g, b) = opts + (self.r, self.g, self.b) = opts + + def step(self): for i in range(math.ceil(self.led_matrix_width*self.led_matrix_height)): - strip.setPixelColor(i, Color(r, g, b)) - strip.show() + self.strip.setPixelColor(i, Color(self.r, self.g, self.b)) + self.strip.show() @@ -131,4 +131,3 @@ class Worm(Pattern): time.sleep(.04) - diff --git a/templates/index.html b/templates/index.html @@ -2,7 +2,7 @@ <html lang="de"> <head> <meta charset="utf-8"> - <title>LED-Steuerung</title> + <title>LED-Säule</title> <style> button{width:10em;} @media only screen and (max-device-width: 1024px){ @@ -17,16 +17,17 @@ button{font-size : 190%; width:10em;} </style> </head> <body> - <h1>LED-Steuerung</h1> - <form action="/" method="POST"> + <h1>LED-Säule</h1> + <form action="/" method="POST"> <div class="slidecontainer"> - R <input type="range" min="0" max="255" value="0" class="slider" id="slider_red"> + R <input type="range" min="0" max="255" value="{{ red }}" class="slider" id="slider_red"> <label id="label_red"></label><br /> - G <input type="range" min="0" max="255" value="0" class="slider" id="slider_green"> + G <input type="range" min="0" max="255" value="{{ green }}" class="slider" id="slider_green"> <label id="label_green"></label><br /> - B <input type="range" min="0" max="255" value="0" class="slider" id="slider_blue"> + B <input type="range" min="0" max="255" value="{{ blue }}" class="slider" id="slider_blue"> <label id="label_blue"></label><br /> </div><br /> + <button type="submit" name="mode" value="off">Aus</button><br /><br /> <button type="submit" name="mode" value="worm">Wurm</button><br /><br /> <button type="submit" name="mode" value="cellular">Zellulärer Automat</button><br /><br /> <button type="submit" name="mode" value="flames">Feuer</button><br /><br /> @@ -34,9 +35,9 @@ button{font-size : 190%; width:10em;} <button type="submit" name="mode" value="flow_hsv">Flow (HSV)</button><br /><br /> <button type="submit" name="mode" value="test">Testmuster</button><br /><br /> </form> - <p><a href="config.html"</a>Konfigurieren</a></p> <!-- Update slider on the fly --> <script> + <!-- Handle RGB sliders --> var slider_red = document.getElementById("slider_red"); var label_red = document.getElementById("label_red"); var slider_green = document.getElementById("slider_green");