WS2812 LED Strip will not turn off the lights after exiting

Following the example Youtube and diagrams work perfectly but when I execute the CTRL+ C command to stop the program strandled.py the program exits but the LED lights remain on!

James

2 Likes

Hi @James266300

Welcome! Good to have you with us. :slight_smile:

Not sure what WS2812 Leds you have but I bet they have an internal hardware register that stores the most recent instruction.
Ctrl C cuts the stream of instructions, but for as long as there is power that register never updates and the LEDs stay in their last state.

Pressing Ctrl+C in your terminal triggers something called a keyboard interrupt. If you like the LEDS to turn off when you press ctrl+c we can write some code that handles the interrupt.
The pythonic way of doing this is something like the below.

def cleanup():
   #Turn off your leds. <----
   #Maybe zero out any unused GPIO pins.

def main():
   #Your code goes here.
   #Make LEDs go bloop bloop
   #Having a good time; making coffee.

if __name__ == '__main__':
    try:
        main()
    except KeyboardInterrupt: #<----
        cleanup()
        exit()

Does that help answer your question?
Pix :heavy_heart_exclamation:

2 Likes

This is the exact code from your website:

#!/usr/bin/env python3

NeoPixel library strandtest example

Author: Tony DiCola (tony@tonydicola.com)

1 Like

Looks like some code got lost there @James266300

@Pixmusix is on the money here. You just need to use the try, except structure and you will be guaranteed that the lights turn off at the end of the script.

You mentioned the Neopixel strandtest.py example.
The original file already uses the structure Pix recommended. Check right at the bottom where the code is looking for a KeyboardInterrupt exception. Code here runs whenever you hit Ctrl+C to stop the code - and it should clear the strip.

Do you not observe that behaviour when you run the strandtest example?

I’ve commented out a lot of the animation so the example doesn’t take so long to cycle. It ought to just colour wipe between R, G, B.

#!/usr/bin/env python3
# NeoPixel library strandtest example
# Author: Tony DiCola (tony@tonydicola.com)
#
# Direct port of the Arduino NeoPixel library strandtest example.  Showcases
# various animations on a strip of NeoPixels.

import time
from rpi_ws281x import PixelStrip, Color
import argparse

# LED strip configuration:
LED_COUNT = 16        # 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 = 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       # set to '1' for GPIOs 13, 19, 41, 45 or 53


# Define functions which animate LEDs in various ways.
def colorWipe(strip, color, wait_ms=50):
    """Wipe color across display a pixel at a time."""
    for i in range(strip.numPixels()):
        strip.setPixelColor(i, color)
        strip.show()
        time.sleep(wait_ms / 1000.0)


def theaterChase(strip, 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, 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 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)


def rainbow(strip, wait_ms=20, iterations=1):
    """Draw rainbow that fades across all pixels at once."""
    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 rainbowCycle(strip, wait_ms=20, iterations=5):
    """Draw rainbow that uniformly distributes itself across all pixels."""
    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 theaterChaseRainbow(strip, wait_ms=50):
    """Rainbow movie theater light style chaser animation."""
    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)


# Main program logic follows:
if __name__ == '__main__':
    # Process arguments
    parser = argparse.ArgumentParser()
    parser.add_argument('-c', '--clear', action='store_true', help='clear the display on exit')
    args = parser.parse_args()

    # Create NeoPixel object with appropriate configuration.
    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).
    strip.begin()

    print('Press Ctrl-C to quit.')
    if not args.clear:
        print('Use "-c" argument to clear LEDs on exit')

    try:

        while True:
            print('Color wipe animations.')
            colorWipe(strip, Color(255, 0, 0))  # Red wipe
            colorWipe(strip, Color(0, 255, 0))  # Green wipe
            colorWipe(strip, Color(0, 0, 255))  # Blue wipe
            #print('Theater chase animations.')
            #theaterChase(strip, Color(127, 127, 127))  # White theater chase
            #theaterChase(strip, Color(127, 0, 0))  # Red theater chase
            #theaterChase(strip, Color(0, 0, 127))  # Blue theater chase
            #print('Rainbow animations.')
            #rainbow(strip)
            #rainbowCycle(strip)
            #theaterChaseRainbow(strip)

    except KeyboardInterrupt:
        if args.clear:
            colorWipe(strip, Color(0, 0, 0), 10)
3 Likes

Thanks for the reply. I do not observe that behaviour when I run the strandtest example. CTRL+C does not work with the script the lights remain on. I can’t figure out how to turn off. Only when I remove the 5v power does the lights go off.

James

1 Like

Hi James,

Would it be possible to send through the code you are running?
The code Michael sent through includes the try except logic that Pic described and should clear it

In @Michael example i think you need to pass in an argument like this

#in your terminal
strandtest.py --clear

Adding that --clear flag sets args.clear to True.

args.clear must be true, if not the below code that turns the leds off won’t run.

if args.clear:
   colorWipe(strip, Color(0, 0, 0), 10)

A Python programmer did something different to get it to work… a different method. I will retrieve and send to you so you can share… he mentioned something about that code not being recognized

James…

2 Likes