You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

127 lines
5.0 KiB

#!/usr/bin/env python3
# NeoPixel library light-painting example
# Author: Gary Servin (garyservin@gmail.com)
#
# Lightpainting example for displaying images one column at a time and capturing
# it by taking a long exposure photograph.
# Based on https://github.com/scottjgibson/PixelPi
import time
from neopixel import *
import argparse
# Button
import RPi.GPIO as GPIO
# Lightpainting
from PIL import Image
# LED strip configuration:
LED_COUNT = 128 # 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
BUTTON_CHANNEL = 19 # GPIO pin connected to the start button
def UnColor(color):
return ((color >> 24) & 0xFF , (color >> 16) & 0xFF, (color >> 8) & 0xFF, color & 0xFF)
def lightpaint(filename, frame_rate=100, column_rate=1, reverse_x=False, reverse_y=False, loop=False):
img = Image.open(filename).convert("RGB")
# Check that the height of the image is greater than or equal the number of LEDs on the strip
if(img.size[1] < LED_COUNT):
raise Exception("Image height is smaller than led strip size. Required height = {}".format(LED_COUNT))
elif(img.size[1] > LED_COUNT):
print "Resizing image"
new_width = LED_COUNT * img.size[0] / img.size[1]
img = img.resize((new_width, LED_COUNT), Image.ANTIALIAS)
input_image = img.load()
image_width = img.size[0]
column = [0 for x in range(image_width)]
for x in range(image_width):
column[x] = [None] * (LED_COUNT)
for x in range(image_width):
for y in range(LED_COUNT):
value = input_image[x, y]
column[x][y] = Color(value[1], value[0], value[2])
while True:
# Wait for button to be pressed before displaying image
if not loop:
print("Waiting for button to be pressed")
GPIO.wait_for_edge(BUTTON_CHANNEL, GPIO.FALLING)
time.sleep(0.5)
x_range = range(image_width)
if reverse_x:
x_range.reverse()
y_range = range(LED_COUNT)
if reverse_y:
y_range.reverse()
for x in x_range:
led_pos = 0
for y in y_range:
strip.setPixelColor(led_pos, column[x][y])
led_pos += 1
strip.show()
time.sleep(column_rate / 1000.0)
# Wait for `frame_rate` ms before drawing a new frame
time.sleep(frame_rate / 1000.0)
# 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)
# 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')
parser.add_argument('-f', '--file', action='store', help='Filename to display')
parser.add_argument('-r', '--frame_rate', action='store', default=100, help='Rate between each frame. Defines how fast a new frame is displayed')
parser.add_argument('-l', '--column_rate', action='store', default=1, help='Rate between each column. Defines how fast or slow you need to move the stick')
parser.add_argument('-b', '--brightness', action='store', default=10, help='Brightness of the LED. Set to 0 for darkest and 255 for brightest')
parser.add_argument('-x', '--reverse_x', action='store_true', help='Reverse the image in the X direction')
parser.add_argument('-y', '--reverse_y', action='store_true', help='Reverse the image in the Y direction')
parser.add_argument('--loop', action='store_true', help='Play frames in a loop')
args = parser.parse_args()
# Create NeoPixel object with appropriate configuration.
strip = Adafruit_NeoPixel(LED_COUNT, LED_PIN, LED_FREQ_HZ, LED_DMA, LED_INVERT, args.brightness, LED_CHANNEL)
# Intialize the library (must be called once before other functions).
strip.begin()
# Button
GPIO.setmode(GPIO.BOARD)
GPIO.setup(BUTTON_CHANNEL, GPIO.IN, pull_up_down=GPIO.PUD_UP)
print ('Press Ctrl-C to quit.')
if not args.clear:
print('Use "-c" argument to clear LEDs on exit')
try:
while True:
print ('Lightpaint.')
lightpaint(args.file, float(args.frame_rate), float(args.column_rate), args.reverse_x, args.reverse_y, args.loop)
except KeyboardInterrupt:
if args.clear:
colorWipe(strip, Color(0,0,0), 10)
GPIO.cleanup()