Browse Source

Maker Faire WS2812 Display Source

master
komaspieler 5 years ago
commit
11df21ee51
14 changed files with 565 additions and 0 deletions
  1. +3
    -0
      .gitmodules
  2. +0
    -0
     
  3. BIN
     
  4. BIN
     
  5. BIN
     
  6. BIN
     
  7. BIN
     
  8. BIN
     
  9. BIN
     
  10. BIN
     
  11. BIN
     
  12. +337
    -0
      makerfaire-demos/live_typing.py
  13. +224
    -0
      makerfaire-demos/static_demo.py
  14. +1
    -0
      rpi_ws281x

+ 3
- 0
.gitmodules View File

@@ -0,0 +1,3 @@
[submodule "rpi_ws281x"]
path = rpi_ws281x
url = https://github.com/jgarff/rpi_ws281x.git

+ 0
- 0
View File


BIN
View File


BIN
View File


BIN
View File


BIN
View File


BIN
View File


BIN
View File


BIN
View File


BIN
View File


BIN
View File


+ 337
- 0
makerfaire-demos/live_typing.py View File

@@ -0,0 +1,337 @@
'''
Live typing demo for Maker Faire Berlin 2018

This class enables visitors to type on a USB-Keyboard connected to the
control laptop and have the typed text appear on the 30x30
WS2812-LED-Display immediately (5 letters per line with three lines).

This demo was programmed during the exhibition.

By using pygame, it also provides a live view of the current display
for the operator - after all, we had a lot of kids on the faire and
needed to make sure they didn't type anything 'spicy' ;-)

Also, it was kinda cool to be able to see what's being displayed right
now as opposed to having to walk around to see the front of the
display. It allowed for some 'fake artificial intelligence' chatting
with visitors ;)

@author Thomas Hoffmann
@date 27-05-2018

'''

import pygame, time
import pygame.display
from random import randint

from neopixel import *
from PIL import ImageDraw, ImageFont, Image


#### set up the LED strip
LED_COUNT = 900 # Number of LED pixels.
LED_PIN = 21 # GPIO pin connected to the pixels (18 uses PWM!).
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 transi
LED_CHANNEL = 0 # set to '1' for GPIOs 13, 19, 41, 45 or 53
LED_STRIP = ws.WS2811_STRIP_GRB

strip = Adafruit_NeoPixel(LED_COUNT, LED_PIN, LED_FREQ_HZ, LED_DMA, LED_INVERT, LED_BRIGHTNESS, LED_CHANNEL, LED_STRIP)
strip.begin()

print ('Press Ctrl-C to quit.')

#### set up pygame
pygame.init()
pygame.display.init()
screen = pygame.display.set_mode((50,50)) # create a 50x50 px window

## list of bad words to immediately remove from the display after being typed
badwords = ["AMK", "lots of bad words"]

# use this font to render text
fnt = ImageFont.truetype('/usr/share/fonts/truetype/dejavu/DejaVuSansMono.ttf', 10)

# other variables
str1 = ""
str2 = ""
str3 = ""
cnt = 0
letter = ""
idle = 0
redraw = False

def displayGIF(strip, imageName, wait_ms=500):
'''
Helper function to render GIF files for the display
requires the GIFs to have the same dimensions as the display
'''
im = Image.open(imageName)
width = im.size[0]
height = im.size[1]
try:
while 1:
buf = im.convert('RGB')
i = 0
for y in range(0, height):
for x in range(0, width):
if y%2 != 0:
r,g,b = buf.getpixel((29-x,y))
else:
r,g,b = buf.getpixel((x,y))
strip.setPixelColor(i, Color(r, g, b))
i += 1
strip.show()
im.seek(im.tell()+1)
## this part converts the display contents for the preview window
imgString = buf.tobytes()
pygame_surface = pygame.image.fromstring(imgString, (30,30), 'RGB')
screen.blit(pygame_surface, (10,10))
pygame.display.flip()
## end of part
time.sleep(im.info["duration"]/1000.0)
except EOFError:
pass # end of sequence

def reset_screen():
''' reset strings to empty '''
global str1,str2,str3
str1 = ""
str2 = ""
str3 = ""

def print_screen():
''' take current image data and display it on the LED strip '''
global im
i = 0
for y in range(0, 30):
for x in range(0, 30):
if y%2 != 0:
r,g,b = im.getpixel((29-x,y))
else:
r,g,b = im.getpixel((x,y))
strip.setPixelColor(i, Color(r,g,b))
i += 1
imgString = im.tobytes()
pygame_surface = pygame.image.fromstring(imgString, (30,30), 'RGB')
screen.blit(pygame_surface, (10,10))
pygame.display.flip()
strip.show()


while True:
# create new image every iteration
im = Image.new('RGB', (30, 30), color = (0,0,0))
d = ImageDraw.Draw(im)
# does the screen need to be reprinted? (relevant for profanity filter)
if redraw:
redraw = False
pygame.time.wait(500)
print_screen()
for event in pygame.event.get():
# capture keypress events
if (event.type == pygame.KEYDOWN):
idle = 0
if (event.key == pygame.K_a):
letter = "A"
if (event.key == pygame.K_b):
letter = "B"
if (event.key == pygame.K_c):
letter = "C"
if (event.key == pygame.K_d):
letter = "D"
if (event.key == pygame.K_e):
letter = "E"
if (event.key == pygame.K_f):
letter = "F"
if (event.key == pygame.K_g):
letter = "G"
if (event.key == pygame.K_h):
letter = "H"
if (event.key == pygame.K_i):
letter = "I"
if (event.key == pygame.K_j):
letter = "J"
if (event.key == pygame.K_k):
letter = "K"
if (event.key == pygame.K_l):
letter = "L"
if (event.key == pygame.K_m):
letter = "M"
if (event.key == pygame.K_n):
letter = "N"
if (event.key == pygame.K_o):
letter = "O"
if (event.key == pygame.K_p):
letter = "P"
if (event.key == pygame.K_q):
letter = "Q"
if (event.key == pygame.K_r):
letter = "R"
if (event.key == pygame.K_s):
letter = "S"
if (event.key == pygame.K_t):
letter = "T"
if (event.key == pygame.K_u):
letter = "U"
if (event.key == pygame.K_v):
letter = "V"
if (event.key == pygame.K_w):
letter = "W"
if (event.key == pygame.K_x):
letter = "X"
if (event.key == pygame.K_y):
letter = "Z"
if (event.key == pygame.K_z):
letter = "Y"
if (event.key == pygame.K_0):
letter = "0"
if (event.key == pygame.K_1):
letter = "1"
if (event.key == pygame.K_2):
letter = "2"
if (event.key == pygame.K_3):
letter = "3"
if (event.key == pygame.K_4):
letter = "4"
if (event.key == pygame.K_5):
letter = "5"
if (event.key == pygame.K_6):
letter = "6"
if (event.key == pygame.K_7):
letter = "7"
if (event.key == pygame.K_8):
letter = "8"
if (event.key == pygame.K_9):
letter = "9"
if (event.key == pygame.K_SPACE):
letter = " "
if (event.key == pygame.K_BACKSPACE):
print("backspace")
reset_screen()
print_screen()
cnt = 0
break
if (event.key == pygame.K_RETURN):
if (cnt < 5):
cnt = 4
if (cnt > 5 and cnt < 10):
cnt = 9
if (cnt > 10 and cnt <= 15):
cnt = -1
str1 = str2 = str3 = ""
letter = ""
break
if (event.key != pygame.K_RETURN and letter == ""):
break

if (cnt >= 15):
cnt = 0
str1 = ""
str2 = ""
str3 = ""
cnt += 1
if (cnt > 15):
cnt = 0
str1 = ""
str2 = ""
str3 = ""
if (event.key == pygame.K_RETURN):
continue
if (cnt <= 5):
str1 = "{}{}".format(str1, letter)
print("Adding letter {} to line 1".format(letter))
if (cnt > 5 and cnt <= 10):
str2 = "{}{}".format(str2, letter)
print("Adding letter {} to line 2".format(letter))
if (cnt > 10 and cnt <= 15):
str3 = "{}{}".format(str3, letter)
print("Adding letter {} to line 3".format(letter))
letter = ""
d.text((0,0), str1, font=fnt, fill=(255,255,255))
d.text((0,10), str2, font=fnt, fill=(255,255,255))
d.text((0,20), str3, font=fnt, fill=(255,255,255))
print("Line 1: {}".format(str1))
print("Line 2: {}".format(str2))
print("Line 3: {}".format(str3))
print(" ")
profanity = "{}{}{}".format(str1,str2,str3)
for word in badwords:
if (word in profanity):
print ("Found a naughty word - resetting! - {}".format(profanity))
reset_screen()
cnt = 0
im.paste((255,0,0), [0,0,30,30])
redraw = True

# have a couple of easter eggs to surprise visitors if they type this word (abusing the profanity-filter functionality)
if ("PONG" in profanity):
print("Pong animation")
displayGIF(strip, "pong.gif")
reset_screen()
cnt = 0
print("EOA")

if ("BADAPPLE" in profanity):
print("Bad Apple Animation")
strip.setBrightness(100)
displayGIF(strip, "badapple.gif")
strip.setBrightness(LED_BRIGHTNESS)
reset_screen()
cnt = 0
print("EOA")
if ("MAKERFAIRE" in profanity):
print("MakerFaire Animation")
displayGIF(strip, "makerfaire.gif")
reset_screen()
cnt = 0
print("EOA")
if ("BREADBOARD" in profanity):
print("Breadboarder Animation")
displayGIF(strip, "breadboarder_top.gif")
reset_screen()
cnt = 0
print("EOA")
print_screen()
# have an idle animation to attract visitors when nothing's been typed for a while
if (idle > 5000):
displayGIF(strip, "breadboarder_top.gif")
displayGIF(strip, "breadboarder_bottom.gif")
displayGIF(strip, "pong.gif")
pygame.time.wait(300)
displayGIF(strip, "type.gif")
idle = -5000
str1 = "TYPE"
str2 = "HERE"
str3 = " NOW"
im = Image.new('RGB', (30, 30), color = (0,0,0))
d = ImageDraw.Draw(im)
d.text((0,0), str1, font=fnt, fill=(255,255,255))
d.text((0,10), str2, font=fnt, fill=(255,255,255))
d.text((0,20), str3, font=fnt, fill=(255,255,255))
print_screen()
reset_screen()
cnt = 0
idle += 1
pygame.time.wait(10)

+ 224
- 0
makerfaire-demos/static_demo.py View File

@@ -0,0 +1,224 @@
# 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.

# Extended by custom animations for Maker Faire Berlin 2018

import time

from neopixel import *
from PIL import Image, ImageDraw, ImageFont
import signal
import sys

def signal_handler(signal, frame):
for i in range(0,900):
strip.setPixelColor(i, Color(0,0,0))

strip.show()
print("Canceled Animations")
sys.exit(0)

# LED strip configuration:
LED_COUNT = 900 # Number of LED pixels.
LED_PIN = 21 # GPIO pin connected to the pixels (18 uses PWM!).
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
LED_STRIP = ws.WS2811_STRIP_GRB # Strip type and colour ordering

def displayGIF(strip, imageName, wait_ms=500):
''' Display a GIF identified by imageName frame by frame '''

im = Image.open(imageName)
width = im.size[0]
height = im.size[1]

# To iterate through the entire gif
try:
while 1:
buf = im.convert('RGB')
i = 0

for y in range(0, height):
for x in range(0, width):
if y%2 != 0:
r,g,b = buf.getpixel((29-x,y))
else:
r,g,b = buf.getpixel((x,y))

strip.setPixelColor(i, Color(r, g, b))
i += 1
strip.show()
im.seek(im.tell()+1)
time.sleep(im.info["duration"]/1000.0)
except EOFError:
pass # end of sequence

def displayJpeg(strip, imName, wait_ms=500):
''' Display a JPEG file given by imName '''
img = Image.open(imName)
size = img.size

buf = img.load()
i = 0
print("{},{}".format(size[0],size[1]))
print("{}".format(buf[0,0][0]))
for y in range(0, size[1]):
for x in range(0, size[0]):
if y%2 != 0:
strip.setPixelColor(i, Color(buf[29-x,y][0], buf[29-x,y][1], buf[29-x,y][2]))
else:
strip.setPixelColor(i, Color(buf[x,y][0], buf[x,y][1], buf[x,y][2]))
i += 1
strip.show()
time.sleep(5);

def pixelTest(strip):
''' Flash the three base colors to quickly assess LED functionality '''
strip.setBrightness(128) # we had to adjust brightness due to an underpowered power supply
for i in range(strip.numPixels()):
strip.setPixelColor(i, Color(255,0,0))
strip.show()
time.sleep(1)
for i in range(strip.numPixels()):
strip.setPixelColor(i, Color(0,255,0))
strip.show()
time.sleep(1)
for i in range(strip.numPixels()):
strip.setPixelColor(i, Color(0,0,255))
strip.show()
time.sleep(1)
for i in range(strip.numPixels()):
strip.setPixelColor(i, Color(255,255,255))
strip.show()
time.sleep(1)
strip.setBrightness(LED_BRIGHTNESS) # restore LED_BRIGHTNESS setting


def theaterChase(strip, color, wait_ms=25, iterations=10):
''' This function was predefined as part of the official python wrapper demo '''
"""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):
''' This function was predefined as part of the official python wrapper demo '''
"""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 rainbowCycle(strip, wait_ms=20, iterations=5):
''' This function was predefined as part of the official python wrapper demo '''
"""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 dynamic(strip):
''' This was my first attempt at rendering raw text on the display '''
im = Image.new('RGB', (30, 30), color = (0,0,0))
fnt = ImageFont.truetype('/usr/share/fonts/truetype/dejavu/DejaVuSansMono.ttf', 10)
d = ImageDraw.Draw(im)
d.text((0,0), "abcde", font=fnt, fill=(255,255,255))
d.text((0,10), "fgehi", font=fnt, fill=(255,255,250))
d.text((0,20), "jklmn", font=fnt, fill=(255,250,250))
i = 0

for y in range(0, 30):
for x in range(0, 30):
if y%2 != 0:
r,g,b = im.getpixel((29-x,y))
else:
r,g,b = im.getpixel((x,y))
strip.setPixelColor(i, Color(r,g,b))
i += 1
strip.show()
time.sleep(5);


# Main program logic follows:
if __name__ == '__main__':

# Create NeoPixel object with appropriate configuration.
strip = Adafruit_NeoPixel(LED_COUNT, LED_PIN, LED_FREQ_HZ, LED_DMA, LED_INVERT, LED_BRIGHTNESS, LED_CHANNEL, LED_STRIP)

# Intialize the library (must be called once before other functions).
strip.begin()

print ('Press Ctrl-C to quit.')

while True:
print ('Pixel Test')
pixelTest(strip)

print ('Breadb top')
displayGIF(strip, "breadboarder_top.gif")
strip.setBrightness(128)

print ('White Theater')
theaterChase(strip, Color(127, 127, 127), 60) # White theater chase
strip.setBrightness(LED_BRIGHTNESS)

print ('Makerfaire')
displayGIF(strip, "makerfaire.gif")

print ('Red theater')
strip.setBrightness(128)
theaterChase(strip, Color(127, 0, 0), 60) # Red theater chase
strip.setBrightness(LED_BRIGHTNESS)

print ('Makerfaire Rainbow')
displayGIF(strip, "makerfaire_hue.gif")

print ('Blue Theater')
strip.setBrightness(128)
theaterChase(strip, Color( 0, 0, 127), 60) # Blue theater chase
strip.setBrightness(LED_BRIGHTNESS)

print ('Breadboarder bottom')
displayGIF(strip, "breadboarder_bottom.gif")

print ('Rainbowcycle')
strip.setBrightness(128)
rainbowCycle(strip, 1, 1)
strip.setBrightness(LED_BRIGHTNESS)

print ('Breadboarder rainbow')
displayGIF(strip, "breadboarder_hue.gif")

print ('Color wheel')
for i in range(0,3):
displayGIF(strip, "colorwheel.gif")

displayGIF(strip, "pong.gif")

+ 1
- 0
rpi_ws281x

@@ -0,0 +1 @@
Subproject commit e4a05d6538c02bb9714f2efc6630f2bfdcf35bf6

Loading…
Cancel
Save