neopixel_demo.py 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220
  1. #!/usr/bin/env python
  2. # -*- coding: utf-8 -*-
  3. # Copyright (c) 2017-18 Richard Hull and contributors
  4. # See LICENSE.rst for details.
  5. # Portions of this script were adapted from:
  6. # https://github.com/pimoroni/unicorn-hat/blob/master/examples/demo.py
  7. import math
  8. import time
  9. import colorsys
  10. from luma.led_matrix.device import neopixel
  11. from luma.core.render import canvas
  12. from luma.core.legacy import text, show_message
  13. from luma.core.legacy.font import proportional, TINY_FONT
  14. # create matrix device
  15. device = neopixel(width=8, height=4)
  16. # twisty swirly goodness
  17. def swirl(x, y, step):
  18. x -= (device.width / 2)
  19. y -= (device.height / 2)
  20. dist = math.sqrt(pow(x, 2) + pow(y, 2)) / 2.0
  21. angle = (step / 10.0) + (dist * 1.5)
  22. s = math.sin(angle)
  23. c = math.cos(angle)
  24. xs = x * c - y * s
  25. ys = x * s + y * c
  26. r = abs(xs + ys)
  27. r = r * 64.0
  28. r -= 20
  29. return (r, r + (s * 130), r + (c * 130))
  30. # roto-zooming checker board
  31. def checker(x, y, step):
  32. x -= (device.width / 2)
  33. y -= (device.height / 2)
  34. angle = (step / 10.0)
  35. s = math.sin(angle)
  36. c = math.cos(angle)
  37. xs = x * c - y * s
  38. ys = x * s + y * c
  39. xs -= math.sin(step / 200.0) * 40.0
  40. ys -= math.cos(step / 200.0) * 40.0
  41. scale = step % 20
  42. scale /= 20
  43. scale = (math.sin(step / 50.0) / 8.0) + 0.25
  44. xs *= scale
  45. ys *= scale
  46. xo = abs(xs) - int(abs(xs))
  47. yo = abs(ys) - int(abs(ys))
  48. l = 0 if (math.floor(xs) + math.floor(ys)) % 2 else 1 if xo > .1 and yo > .1 else .5
  49. r, g, b = colorsys.hsv_to_rgb((step % 255) / 255.0, 1, l)
  50. return (r * 255, g * 255, b * 255)
  51. # weeee waaaah
  52. def blues_and_twos(x, y, step):
  53. x -= (device.width / 2)
  54. y -= (device.height / 2)
  55. # xs = (math.sin((x + step) / 10.0) / 2.0) + 1.0
  56. # ys = (math.cos((y + step) / 10.0) / 2.0) + 1.0
  57. scale = math.sin(step / 6.0) / 1.5
  58. r = math.sin((x * scale) / 1.0) + math.cos((y * scale) / 1.0)
  59. b = math.sin(x * scale / 2.0) + math.cos(y * scale / 2.0)
  60. g = r - .8
  61. g = 0 if g < 0 else g
  62. b -= r
  63. b /= 1.4
  64. return (r * 255, (b + g) * 255, g * 255)
  65. # rainbow search spotlights
  66. def rainbow_search(x, y, step):
  67. xs = math.sin((step) / 100.0) * 20.0
  68. ys = math.cos((step) / 100.0) * 20.0
  69. scale = ((math.sin(step / 60.0) + 1.0) / 5.0) + 0.2
  70. r = math.sin((x + xs) * scale) + math.cos((y + xs) * scale)
  71. g = math.sin((x + xs) * scale) + math.cos((y + ys) * scale)
  72. b = math.sin((x + ys) * scale) + math.cos((y + ys) * scale)
  73. return (r * 255, g * 255, b * 255)
  74. # zoom tunnel
  75. def tunnel(x, y, step):
  76. speed = step / 100.0
  77. x -= (device.width / 2)
  78. y -= (device.height / 2)
  79. xo = math.sin(step / 27.0) * 2
  80. yo = math.cos(step / 18.0) * 2
  81. x += xo
  82. y += yo
  83. if y == 0:
  84. if x < 0:
  85. angle = -(math.pi / 2)
  86. else:
  87. angle = (math.pi / 2)
  88. else:
  89. angle = math.atan(x / y)
  90. if y > 0:
  91. angle += math.pi
  92. angle /= 2 * math.pi # convert angle to 0...1 range
  93. shade = math.sqrt(math.pow(x, 2) + math.pow(y, 2)) / 2.1
  94. shade = 1 if shade > 1 else shade
  95. angle += speed
  96. depth = speed + (math.sqrt(math.pow(x, 2) + math.pow(y, 2)) / 10)
  97. col1 = colorsys.hsv_to_rgb((step % 255) / 255.0, 1, .8)
  98. col2 = colorsys.hsv_to_rgb((step % 255) / 255.0, 1, .3)
  99. col = col1 if int(abs(angle * 6.0)) % 2 == 0 else col2
  100. td = .3 if int(abs(depth * 3.0)) % 2 == 0 else 0
  101. col = (col[0] + td, col[1] + td, col[2] + td)
  102. col = (col[0] * shade, col[1] * shade, col[2] * shade)
  103. return (col[0] * 255, col[1] * 255, col[2] * 255)
  104. def gfx(device):
  105. effects = [tunnel, rainbow_search, checker, swirl]
  106. step = 0
  107. while True:
  108. for i in range(500):
  109. with canvas(device) as draw:
  110. for y in range(device.height):
  111. for x in range(device.width):
  112. r, g, b = effects[0](x, y, step)
  113. if i > 400:
  114. r2, g2, b2 = effects[-1](x, y, step)
  115. ratio = (500.00 - i) / 100.0
  116. r = r * ratio + r2 * (1.0 - ratio)
  117. g = g * ratio + g2 * (1.0 - ratio)
  118. b = b * ratio + b2 * (1.0 - ratio)
  119. r = int(max(0, min(255, r)))
  120. g = int(max(0, min(255, g)))
  121. b = int(max(0, min(255, b)))
  122. draw.point((x, y), (r, g, b))
  123. step += 1
  124. time.sleep(0.01)
  125. effect = effects.pop()
  126. effects.insert(0, effect)
  127. def main():
  128. msg = "Neopixel WS2812 LED Matrix Demo"
  129. show_message(device, msg, y_offset=-1, fill="green", font=proportional(TINY_FONT))
  130. time.sleep(1)
  131. with canvas(device) as draw:
  132. text(draw, (0, -1), txt="A", fill="red", font=TINY_FONT)
  133. text(draw, (4, -1), txt="T", fill="green", font=TINY_FONT)
  134. time.sleep(1)
  135. with canvas(device) as draw:
  136. draw.line((0, 0, 0, device.height), fill="red")
  137. draw.line((1, 0, 1, device.height), fill="orange")
  138. draw.line((2, 0, 2, device.height), fill="yellow")
  139. draw.line((3, 0, 3, device.height), fill="green")
  140. draw.line((4, 0, 4, device.height), fill="blue")
  141. draw.line((5, 0, 5, device.height), fill="indigo")
  142. draw.line((6, 0, 6, device.height), fill="violet")
  143. draw.line((7, 0, 7, device.height), fill="white")
  144. time.sleep(4)
  145. for _ in range(5):
  146. for intensity in range(16):
  147. device.contrast(intensity * 16)
  148. time.sleep(0.1)
  149. device.contrast(0x80)
  150. time.sleep(1)
  151. gfx(device)
  152. if __name__ == "__main__":
  153. try:
  154. main()
  155. except KeyboardInterrupt:
  156. pass