4
\$\begingroup\$

Below is a python script that I wrote to flash neopixel leds at a very fast rate using a raspberry pi0. The main while loops runs at a semi reasonable rate, although faster would be much better. In addition, the button thread slows down the script considerably. Any ideas on how to make this run faster? While running, it uses 96% of my CPU already.

I am especially hoping for input on how to make this faster.

import time
import csv
from pprint import pprint
from neopixel import *
import RPi.GPIO as GPIO
import threading

B1 = 23
B2 = 24
B3 = 25
GPIO.setmode(GPIO.BCM)
GPIO.setup(B1, GPIO.IN)
GPIO.setup(B2, GPIO.IN)
GPIO.setup(B3, GPIO.IN)

numpats = 4
cpat = 0
DELAY = 0
shuffle = False

def ButtonThread():
    global cpat
    global DELAY
    global shuffle

    while True:
        if GPIO.input(B1):
            cpat = cpat + 1
            if cpat >= numpats:
                cpat = 0
            print(cpat)
            time.sleep(0.5)

        if GPIO.input(B2):
            DELAY = DELAY + .0001
            time.sleep(0.1)

            if DELAY > .05:
                DELAY = 0

        if GPIO.input(B3):
            shuffle = not shuffle
            print(shuffle)
            time.sleep(0.5)


LED_COUNT      = 300      # Number of LED pixels.
NUMPIX =  100
LED_PIN        = 18      # GPIO pin connected to the pixels (18 uses PWM!).
LED_FREQ_HZ    = 800000  # LED signal frequency in hertz (usually 800khz)
LED_DMA        = 5       # DMA channel to use for generating signal (try 5)
LED_BRIGHTNESS = 25     # 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
LED_STRIP      = ws.WS2811_STRIP_GRB   # Strip type and colour ordering

#LOAD PATTERNS
text = []
pattern = []
with open('patterns.txt')as inputfile:
    for line in inputfile:
        text.append(line.strip().split(','))
    for p in text:
    pattern.append([])
        for d in p:
            pattern[cpat].append(int(float(d)))
    cpat = cpat + 1

cpat = 0
colors = []
r,g,b = 0.0,0.0,0.0
for p in pattern:
    cnt=0
    colors.append([])
        for x in p:
            if cnt%3 == 0:
            r = x
        elif cnt %3 == 1:
            g = x
        else :
            b = x
            colors[cpat].append(Color(r,g,b))
        cnt = cnt + 1
    cpat = cpat + 1

if __name__ == '__main__':
    cpat = 0
    strip = Adafruit_NeoPixel(LED_COUNT, LED_PIN, LED_FREQ_HZ, LED_DMA, LED_INVERT, LED_BRIGHTNESS, LED_CHANNEL, LED_STRIP)
    strip.begin()

    buttThread = threading.Thread(target=ButtonThread, args=())
    buttThread.daemon = True
    buttThread.start()


    cpat = 0
    print(strip.numPixels())

    while True:
        cnt=0
        for x in colors[cpat]:
            led = cnt%(NUMPIX)
            strip.setPixelColor(led, x)
            strip.setPixelColor(NUMPIX + led, x)
            strip.setPixelColor(2*NUMPIX + led, x)
            cnt = cnt +1

            if led == NUMPIX-1:
                strip.show()
                cnt=0
                time.sleep(DELAY)
\$\endgroup\$
  • \$\begingroup\$ I'm not too worried about the high CPU usage, as it is an embedded situation where the unit will be doing nothing but running this script. There were no prints inside any loops, but I did remove them any way. \$\endgroup\$ – banielbow Jun 11 '17 at 23:39
1
\$\begingroup\$

A couple of suggestions.

Throttle Infinite Loops:

The button loop has no throttle on its CPU usage. If no buttons are pressed it is constantly doing IO. If you reformulate the loop without any of the buttons being pressed the effective code looks like:

while True:
    GPIO.input(B1)
    GPIO.input(B2)
    GPIO.input(B3)

This code never gives the CPU a rest. It should probably be more like:

while True:
    GPIO.input(B1)
    GPIO.input(B2)
    GPIO.input(B3)
    time.sleep(0.05)

Picking the actual sleep() time will depend on the system, but hopefully this demonstrates the likely problem.

So the loop with the if statements will look like:

while True:
    if GPIO.input(B1):
        ...

    if GPIO.input(B2):
        ...

    if GPIO.input(B3):
        ...

    time.sleep(0.05)

Use List Properties for Length Management

This code is using a variable to get the current pattern:

cpat = cpat + 1
if cpat >= numpats:
    cpat = 0

This can be more cleanly done with:

cpat = (cpat + 1) % len(colors)

The change removes two lines of code, and sets the variable limit based on the list indices, which can avoid bugs later.

| improve this answer | |
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.