Dies ist das Repository zu dem auf der Maker Faire Berlin 2018 ausgestellten WS2812 30x30 LED-Displays
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.

338 lines
11 KiB

  1. '''
  2. Live typing demo for Maker Faire Berlin 2018
  3. This class enables visitors to type on a USB-Keyboard connected to the
  4. control laptop and have the typed text appear on the 30x30
  5. WS2812-LED-Display immediately (5 letters per line with three lines).
  6. This demo was programmed during the exhibition.
  7. By using pygame, it also provides a live view of the current display
  8. for the operator - after all, we had a lot of kids on the faire and
  9. needed to make sure they didn't type anything 'spicy' ;-)
  10. Also, it was kinda cool to be able to see what's being displayed right
  11. now as opposed to having to walk around to see the front of the
  12. display. It allowed for some 'fake artificial intelligence' chatting
  13. with visitors ;)
  14. @author Thomas Hoffmann
  15. @date 27-05-2018
  16. '''
  17. import pygame, time
  18. import pygame.display
  19. from random import randint
  20. from neopixel import *
  21. from PIL import ImageDraw, ImageFont, Image
  22. #### set up the LED strip
  23. LED_COUNT = 900 # Number of LED pixels.
  24. LED_PIN = 21 # GPIO pin connected to the pixels (18 uses PWM!).
  25. LED_FREQ_HZ = 800000 # LED signal frequency in hertz (usually 800khz)
  26. LED_DMA = 10 # DMA channel to use for generating signal (try 10)
  27. LED_BRIGHTNESS = 255 # Set to 0 for darkest and 255 for brightest
  28. LED_INVERT = False # True to invert the signal (when using NPN transi
  29. LED_CHANNEL = 0 # set to '1' for GPIOs 13, 19, 41, 45 or 53
  30. LED_STRIP = ws.WS2811_STRIP_GRB
  31. strip = Adafruit_NeoPixel(LED_COUNT, LED_PIN, LED_FREQ_HZ, LED_DMA, LED_INVERT, LED_BRIGHTNESS, LED_CHANNEL, LED_STRIP)
  32. strip.begin()
  33. print ('Press Ctrl-C to quit.')
  34. #### set up pygame
  35. pygame.init()
  36. pygame.display.init()
  37. screen = pygame.display.set_mode((50,50)) # create a 50x50 px window
  38. ## list of bad words to immediately remove from the display after being typed
  39. badwords = ["AMK", "lots of bad words"]
  40. # use this font to render text
  41. fnt = ImageFont.truetype('/usr/share/fonts/truetype/dejavu/DejaVuSansMono.ttf', 10)
  42. # other variables
  43. str1 = ""
  44. str2 = ""
  45. str3 = ""
  46. cnt = 0
  47. letter = ""
  48. idle = 0
  49. redraw = False
  50. def displayGIF(strip, imageName, wait_ms=500):
  51. '''
  52. Helper function to render GIF files for the display
  53. requires the GIFs to have the same dimensions as the display
  54. '''
  55. im = Image.open(imageName)
  56. width = im.size[0]
  57. height = im.size[1]
  58. try:
  59. while 1:
  60. buf = im.convert('RGB')
  61. i = 0
  62. for y in range(0, height):
  63. for x in range(0, width):
  64. if y%2 != 0:
  65. r,g,b = buf.getpixel((29-x,y))
  66. else:
  67. r,g,b = buf.getpixel((x,y))
  68. strip.setPixelColor(i, Color(r, g, b))
  69. i += 1
  70. strip.show()
  71. im.seek(im.tell()+1)
  72. ## this part converts the display contents for the preview window
  73. imgString = buf.tobytes()
  74. pygame_surface = pygame.image.fromstring(imgString, (30,30), 'RGB')
  75. screen.blit(pygame_surface, (10,10))
  76. pygame.display.flip()
  77. ## end of part
  78. time.sleep(im.info["duration"]/1000.0)
  79. except EOFError:
  80. pass # end of sequence
  81. def reset_screen():
  82. ''' reset strings to empty '''
  83. global str1,str2,str3
  84. str1 = ""
  85. str2 = ""
  86. str3 = ""
  87. def print_screen():
  88. ''' take current image data and display it on the LED strip '''
  89. global im
  90. i = 0
  91. for y in range(0, 30):
  92. for x in range(0, 30):
  93. if y%2 != 0:
  94. r,g,b = im.getpixel((29-x,y))
  95. else:
  96. r,g,b = im.getpixel((x,y))
  97. strip.setPixelColor(i, Color(r,g,b))
  98. i += 1
  99. imgString = im.tobytes()
  100. pygame_surface = pygame.image.fromstring(imgString, (30,30), 'RGB')
  101. screen.blit(pygame_surface, (10,10))
  102. pygame.display.flip()
  103. strip.show()
  104. while True:
  105. # create new image every iteration
  106. im = Image.new('RGB', (30, 30), color = (0,0,0))
  107. d = ImageDraw.Draw(im)
  108. # does the screen need to be reprinted? (relevant for profanity filter)
  109. if redraw:
  110. redraw = False
  111. pygame.time.wait(500)
  112. print_screen()
  113. for event in pygame.event.get():
  114. # capture keypress events
  115. if (event.type == pygame.KEYDOWN):
  116. idle = 0
  117. if (event.key == pygame.K_a):
  118. letter = "A"
  119. if (event.key == pygame.K_b):
  120. letter = "B"
  121. if (event.key == pygame.K_c):
  122. letter = "C"
  123. if (event.key == pygame.K_d):
  124. letter = "D"
  125. if (event.key == pygame.K_e):
  126. letter = "E"
  127. if (event.key == pygame.K_f):
  128. letter = "F"
  129. if (event.key == pygame.K_g):
  130. letter = "G"
  131. if (event.key == pygame.K_h):
  132. letter = "H"
  133. if (event.key == pygame.K_i):
  134. letter = "I"
  135. if (event.key == pygame.K_j):
  136. letter = "J"
  137. if (event.key == pygame.K_k):
  138. letter = "K"
  139. if (event.key == pygame.K_l):
  140. letter = "L"
  141. if (event.key == pygame.K_m):
  142. letter = "M"
  143. if (event.key == pygame.K_n):
  144. letter = "N"
  145. if (event.key == pygame.K_o):
  146. letter = "O"
  147. if (event.key == pygame.K_p):
  148. letter = "P"
  149. if (event.key == pygame.K_q):
  150. letter = "Q"
  151. if (event.key == pygame.K_r):
  152. letter = "R"
  153. if (event.key == pygame.K_s):
  154. letter = "S"
  155. if (event.key == pygame.K_t):
  156. letter = "T"
  157. if (event.key == pygame.K_u):
  158. letter = "U"
  159. if (event.key == pygame.K_v):
  160. letter = "V"
  161. if (event.key == pygame.K_w):
  162. letter = "W"
  163. if (event.key == pygame.K_x):
  164. letter = "X"
  165. if (event.key == pygame.K_y):
  166. letter = "Z"
  167. if (event.key == pygame.K_z):
  168. letter = "Y"
  169. if (event.key == pygame.K_0):
  170. letter = "0"
  171. if (event.key == pygame.K_1):
  172. letter = "1"
  173. if (event.key == pygame.K_2):
  174. letter = "2"
  175. if (event.key == pygame.K_3):
  176. letter = "3"
  177. if (event.key == pygame.K_4):
  178. letter = "4"
  179. if (event.key == pygame.K_5):
  180. letter = "5"
  181. if (event.key == pygame.K_6):
  182. letter = "6"
  183. if (event.key == pygame.K_7):
  184. letter = "7"
  185. if (event.key == pygame.K_8):
  186. letter = "8"
  187. if (event.key == pygame.K_9):
  188. letter = "9"
  189. if (event.key == pygame.K_SPACE):
  190. letter = " "
  191. if (event.key == pygame.K_BACKSPACE):
  192. print("backspace")
  193. reset_screen()
  194. print_screen()
  195. cnt = 0
  196. break
  197. if (event.key == pygame.K_RETURN):
  198. if (cnt < 5):
  199. cnt = 4
  200. if (cnt > 5 and cnt < 10):
  201. cnt = 9
  202. if (cnt > 10 and cnt <= 15):
  203. cnt = -1
  204. str1 = str2 = str3 = ""
  205. letter = ""
  206. break
  207. if (event.key != pygame.K_RETURN and letter == ""):
  208. break
  209. if (cnt >= 15):
  210. cnt = 0
  211. str1 = ""
  212. str2 = ""
  213. str3 = ""
  214. cnt += 1
  215. if (cnt > 15):
  216. cnt = 0
  217. str1 = ""
  218. str2 = ""
  219. str3 = ""
  220. if (event.key == pygame.K_RETURN):
  221. continue
  222. if (cnt <= 5):
  223. str1 = "{}{}".format(str1, letter)
  224. print("Adding letter {} to line 1".format(letter))
  225. if (cnt > 5 and cnt <= 10):
  226. str2 = "{}{}".format(str2, letter)
  227. print("Adding letter {} to line 2".format(letter))
  228. if (cnt > 10 and cnt <= 15):
  229. str3 = "{}{}".format(str3, letter)
  230. print("Adding letter {} to line 3".format(letter))
  231. letter = ""
  232. d.text((0,0), str1, font=fnt, fill=(255,255,255))
  233. d.text((0,10), str2, font=fnt, fill=(255,255,255))
  234. d.text((0,20), str3, font=fnt, fill=(255,255,255))
  235. print("Line 1: {}".format(str1))
  236. print("Line 2: {}".format(str2))
  237. print("Line 3: {}".format(str3))
  238. print(" ")
  239. profanity = "{}{}{}".format(str1,str2,str3)
  240. for word in badwords:
  241. if (word in profanity):
  242. print ("Found a naughty word - resetting! - {}".format(profanity))
  243. reset_screen()
  244. cnt = 0
  245. im.paste((255,0,0), [0,0,30,30])
  246. redraw = True
  247. # have a couple of easter eggs to surprise visitors if they type this word (abusing the profanity-filter functionality)
  248. if ("PONG" in profanity):
  249. print("Pong animation")
  250. displayGIF(strip, "pong.gif")
  251. reset_screen()
  252. cnt = 0
  253. print("EOA")
  254. if ("BADAPPLE" in profanity):
  255. print("Bad Apple Animation")
  256. strip.setBrightness(100)
  257. displayGIF(strip, "badapple.gif")
  258. strip.setBrightness(LED_BRIGHTNESS)
  259. reset_screen()
  260. cnt = 0
  261. print("EOA")
  262. if ("MAKERFAIRE" in profanity):
  263. print("MakerFaire Animation")
  264. displayGIF(strip, "makerfaire.gif")
  265. reset_screen()
  266. cnt = 0
  267. print("EOA")
  268. if ("BREADBOARD" in profanity):
  269. print("Breadboarder Animation")
  270. displayGIF(strip, "breadboarder_top.gif")
  271. reset_screen()
  272. cnt = 0
  273. print("EOA")
  274. print_screen()
  275. # have an idle animation to attract visitors when nothing's been typed for a while
  276. if (idle > 5000):
  277. displayGIF(strip, "breadboarder_top.gif")
  278. displayGIF(strip, "breadboarder_bottom.gif")
  279. displayGIF(strip, "pong.gif")
  280. pygame.time.wait(300)
  281. displayGIF(strip, "type.gif")
  282. idle = -5000
  283. str1 = "TYPE"
  284. str2 = "HERE"
  285. str3 = " NOW"
  286. im = Image.new('RGB', (30, 30), color = (0,0,0))
  287. d = ImageDraw.Draw(im)
  288. d.text((0,0), str1, font=fnt, fill=(255,255,255))
  289. d.text((0,10), str2, font=fnt, fill=(255,255,255))
  290. d.text((0,20), str3, font=fnt, fill=(255,255,255))
  291. print_screen()
  292. reset_screen()
  293. cnt = 0
  294. idle += 1
  295. pygame.time.wait(10)