Close

Das Blinkenlights

A project log for VoiceBox

Adding a Flask web interface (and other stuff) to the Google AIY Voice Kit.

tmTM 08/02/2018 at 21:040 Comments

I've covered the fiddliest part of setting up a Blinkt server in the previous wiring log, so we may as well launch into a discussion of Blinkter.py, a flask server controlling a Blinkt RGB LED strip.

As discussed, the first thing to do is to make a local copy of blinkt.py, the Pimoroni Blinkt library routine. The Blinkt hardware is expecting a clock signal on the GPIO24 pin of its Pi header, and a data signal on GPIO23.  We're instead going to use GPIO6 (Servo1-PIN on the Voice Hat) and GPIO26 (Servo0-PIN).

DAT = 26 # 23
CLK =  6 # 24

All we have to do is to edit blinkt.py and modify the definitions of CLK & DAT as above.

Now on to Blinkter.py, the server proper.  The main program is very simple:

if __name__ == "__main__":
    global pattern, thread
    blinkt.set_clear_on_exit()
    blinkt.set_brightness(0.1)

    pattern = LIGHTS

    thread = threading.Thread(target=BlinkterThread)
    thread.start()
    app.run(host='0.0.0.0', port=9013, debug=False)

There's a global variable "pattern" which determines which pattern the server should be showing on the Blinkt. By default, pattern is set to LIGHTS, meaning show an array of 8 red (for now) or off LEDs.  At startup the state of the eight lights is set to False, and the server will display nothing.

Next up, the main program starts a thread running BlinkterThread(), before launching a flask web-interface in the current thread. 

def BlinkterThread():
    global pattern, h, s
    print 'THREAD: starting with pattern ', pattern
    h = 0.0 # used in pulse
    s = 1.0 # used in pulse
    last_pattern = pattern
    last_time = time.time()
    while True:
        current_pattern = pattern
        if current_pattern != last_pattern:
            last_time = time.time()
            print 'THREAD: pattern changed from ', last_pattern, ' to ', current_pattern
            blinkt.clear()
        if current_pattern == LIGHTS:
            show_lights()
        elif current_pattern == LARSON:
            larson(last_time)
        elif current_pattern == BLINK:
            blink()
        elif current_pattern == PULSE:
            pulse()
        elif current_pattern == RAINBOW:
            rainbow()
        elif current_pattern == MORSE:
            morse()
        else:
            break
        last_pattern = current_pattern

After a little initialization, the BlinkterThread just loops, on each iteration displaying an animation frame for the current pattern. (Modified versions of the Pimoroni examples.)

The flask routines in the main thread are very similar to piHole. If they seem cryptic, read through Matt Richardson's Flask Tutorial

(This bit is pure Mumbo Jumbo, and can be safely ignored.)

func = request.environ.get('werkzeug.server.shutdown')

Installation is the same as for piHole.zip and sysinfo.zip

Unzip Blinkter.zip to /home/pi/Python, then:

sudo cp /home/pi/Python/Blinkter/Blinkter.service /lib/systemd/system
sudo chmod 644 /lib/systemd/system/Blinkter.service
sudo systemctl daemon-reload
sudo systemctl enable Blinkter.service

Browse to <your-pi's-address>:9013 to test. 

You should see a root menu like this:

Click "Change light pattern" to bring up the pattern menu:

Select "rainbow" from the list box to get some bling:

Discussions