Parcourir la source

support multiple chained panels. color remapping for differing panel brightness.

Thomas Buck il y a 1 an
Parent
révision
91cc703efc
8 fichiers modifiés avec 144 ajouts et 31 suppressions
  1. 1
    4
      README.md
  2. 6
    6
      draw.py
  3. 45
    0
      mapper.py
  4. 38
    9
      pi.py
  5. 32
    3
      solid.py
  6. 13
    8
      splash.py
  7. 4
    0
      test.py
  8. 5
    1
      util.py

+ 1
- 4
README.md Voir le fichier

@@ -14,10 +14,7 @@ and go from there.
14 14
 
15 15
 You always need:
16 16
 
17
-    pip install pil
18
-    pip install bdfparser
19
-    pip install "qrcode[pil]"
20
-    pip install evdev
17
+    pip install Pillow bdfparser "qrcode[pil]" evdev
21 18
 
22 19
 For evdev to find all devices you may need to add your user to the `input` group or run the scripts as root.
23 20
 

+ 6
- 6
draw.py Voir le fichier

@@ -166,17 +166,17 @@ if __name__ == "__main__":
166 166
     m = Manager(t)
167 167
 
168 168
     m.add(ScrollText(t, "tom-thumb Abcdefgh tom-thumb", "tom-thumb",
169
-                     1, 75, (0, 255, 0), (0, 0, 255)))
169
+                     1, 75, (0, 255, 0), (0, 0, 25)))
170 170
     m.add(ScrollText(t, "antidote Abcdefgh antidote", "antidote",
171
-                     1, 75, (0, 255, 0), (0, 0, 255)))
171
+                     1, 75, (0, 255, 0), (0, 0, 25)))
172 172
     m.add(ScrollText(t, "uushi Abcdefgh uushi", "uushi",
173
-                     1, 75, (0, 255, 0), (0, 0, 255)))
173
+                     1, 75, (0, 255, 0), (0, 0, 25)))
174 174
     m.add(ScrollText(t, "lemon Abcdefgh lemon", "lemon",
175
-                     1, 75, (0, 255, 0), (0, 0, 255)))
175
+                     1, 75, (0, 255, 0), (0, 0, 25)))
176 176
     m.add(ScrollText(t, "ib8x8u Abcdefgh ib8x8u", "ib8x8u",
177
-                     1, 75, (0, 255, 0), (0, 0, 255)))
177
+                     1, 75, (0, 255, 0), (0, 0, 25)))
178 178
     m.add(ScrollText(t, "iv18x16u Abcdefgh iv18x16u", "iv18x16u",
179
-                     1, 75, (0, 255, 0), (0, 0, 255)))
179
+                     1, 75, (0, 255, 0), (0, 0, 25)))
180 180
 
181 181
     m.restart()
182 182
     t.debug_loop(m.draw)

+ 45
- 0
mapper.py Voir le fichier

@@ -0,0 +1,45 @@
1
+#!/usr/bin/env python3
2
+
3
+# ----------------------------------------------------------------------------
4
+# "THE BEER-WARE LICENSE" (Revision 42):
5
+# <xythobuz@xythobuz.de> wrote this file.  As long as you retain this notice
6
+# you can do whatever you want with this stuff. If we meet some day, and you
7
+# think this stuff is worth it, you can buy me a beer in return.   Thomas Buck
8
+# ----------------------------------------------------------------------------
9
+
10
+# Does nothing. Take this as an example for new Mappers.
11
+class MapperNull:
12
+    def __init__(self, g):
13
+        self.gui = g
14
+        self.width = self.gui.width
15
+        self.height = self.gui.height
16
+        self.multiplier = self.gui.multiplier
17
+        self.panelW = self.gui.panelW
18
+        self.panelH = self.gui.panelH
19
+
20
+    def loop_start(self):
21
+        return self.gui.loop_start()
22
+
23
+    def loop_end(self):
24
+        self.gui.loop_end()
25
+
26
+    def debug_loop(self, func = None):
27
+        self.gui.debug_loop(func)
28
+
29
+    def set_pixel(self, x, y, color):
30
+        self.gui.set_pixel(x, y, color)
31
+
32
+# For some reason the red and green LEDs on newer Pimoroni panels
33
+# are far brighter than on older panels.
34
+# Adjust this by multiplying rg channels with 0.75, depending
35
+# on hard-corded coordinate ranges.
36
+class MapperColorAdjust(MapperNull):
37
+    def set_pixel(self, x, y, color):
38
+        # right-most panel, with maximum x coordinates,
39
+        # is "old" type with less bright LEDs.
40
+        # rest of panels to the left are brighter.
41
+        # so adjust brightness of left panel rg channels down.
42
+        if x < self.gui.panelW:
43
+            color = (int(color[0] * 0.75), int(color[1] * 0.75), color[2])
44
+
45
+        self.gui.set_pixel(x, y, color)

+ 38
- 9
pi.py Voir le fichier

@@ -6,6 +6,21 @@
6 6
 # And the pillow Python Imaging Library:
7 7
 # https://github.com/python-pillow/Pillow
8 8
 #
9
+# For the wiring of multiple panels, check out:
10
+# https://github.com/hzeller/rpi-rgb-led-matrix/blob/master/wiring.md#chains
11
+#
12
+# Basically each chain only stretches in the X-direction.
13
+# For the Y-direction, multiple parallel chains are used.
14
+# Up to 3 are theoretically possible with the Pi, but my hardware only supports
15
+# one.
16
+#
17
+# The physical layout of the chained panels can be different of course.
18
+# For four panels, you could do 64x64 or 32x128.
19
+# But this PiMatrix object will always present it as 128x32,
20
+# chained in the X-direction.
21
+#
22
+# Use the objects from mapper.py to adjust this.
23
+#
9 24
 # ----------------------------------------------------------------------------
10 25
 # "THE BEER-WARE LICENSE" (Revision 42):
11 26
 # <xythobuz@xythobuz.de> wrote this file.  As long as you retain this notice
@@ -17,15 +32,24 @@ from rgbmatrix import RGBMatrix, RGBMatrixOptions
17 32
 from PIL import Image
18 33
 
19 34
 class PiMatrix:
20
-    def __init__(self, w = 32, h = 32):
21
-        self.width = w
22
-        self.height = h
35
+    def __init__(self, w = 64, h = 32, panelW = 32, panelH = 32):
36
+        self.width = w # x-axis
37
+        self.height = h # y-axis
38
+
39
+        self.panelW = panelW # x-axis
40
+        self.panelH = panelH # y-axis
41
+
42
+        # compatibility to TestGUI
43
+        self.multiplier = 1.0
23 44
 
24 45
         options = RGBMatrixOptions()
25
-        options.rows = w
26
-        options.cols = h
27
-        options.chain_length = 1
28
-        options.parallel = 1
46
+
47
+        options.cols = self.panelW # x-axis
48
+        options.rows = self.panelH # y-axis
49
+
50
+        options.chain_length = int(self.width / options.cols) # x-axis
51
+        options.parallel = int(self.height / options.rows) # y-axis
52
+
29 53
         options.row_address_type = 0
30 54
         options.multiplexing = 0
31 55
         options.pwm_bits = 11
@@ -33,8 +57,13 @@ class PiMatrix:
33 57
         options.pwm_lsb_nanoseconds = 130
34 58
         options.led_rgb_sequence = 'RGB'
35 59
         #options.hardware_mapping = 'regular'  # If you have an Adafruit HAT: 'adafruit-hat'
36
-        options.gpio_slowdown = 2
37
-        options.pixel_mapper_config = "Rotate:270"
60
+        #options.gpio_slowdown = 2
61
+        #options.pixel_mapper_config = "Rotate:270"
62
+
63
+        # newer Pimoroni 32x32 panels require this setting for additional
64
+        # initialization of the shift-registers on there.
65
+        # fortunately this also works for the older type of panels.
66
+        options.panel_type = "FM6126A"
38 67
 
39 68
         self.matrix = RGBMatrix(options = options)
40 69
 

+ 32
- 3
solid.py Voir le fichier

@@ -13,9 +13,12 @@ class Solid:
13 13
     def __init__(self, g, t = 1.0, c = (0, 0, 0)):
14 14
         self.gui = g
15 15
         self.time = t
16
-        self.color = c
16
+        self.setColor(c)
17 17
         self.restart()
18 18
 
19
+    def setColor(self, c):
20
+        self.color = c
21
+
19 22
     def restart(self):
20 23
         self.start = time.time()
21 24
 
@@ -31,5 +34,31 @@ if __name__ == "__main__":
31 34
     import util
32 35
     t = util.getTarget()
33 36
 
34
-    d = Solid(t, 1.0, (0, 255, 0))
35
-    t.debug_loop(d.draw)
37
+    colors = [
38
+        (251, 72, 196), # camp23 pink
39
+        (63, 255, 33), # camp23 green
40
+        (255, 0, 0),
41
+        (0, 255, 0),
42
+        (0, 0, 255),
43
+        (255, 255, 0),
44
+        (0, 255, 255),
45
+        (255, 0, 255),
46
+        (255, 255, 255),
47
+    ]
48
+    ci = 0
49
+
50
+    d = Solid(t, 1.0, colors[ci])
51
+
52
+    s = time.time()
53
+    def helper():
54
+        global s, colors, ci
55
+
56
+        if (time.time() - s) >= 1.0:
57
+            s = time.time()
58
+            ci = (ci + 1) % len(colors)
59
+            c = colors[ci]
60
+            d.setColor(c)
61
+
62
+        d.draw()
63
+
64
+    t.debug_loop(helper)

+ 13
- 8
splash.py Voir le fichier

@@ -14,16 +14,21 @@ class SplashScreen:
14 14
         self.height = height
15 15
 
16 16
     def draw(self):
17
-        self.gui.set_pixel(             0,               0, (255, 255, 255))
18
-        self.gui.set_pixel(             0, self.height - 1, (  0,   0, 255))
19
-        self.gui.set_pixel(self.width - 1,               0, (255,   0,   0))
20
-        self.gui.set_pixel(self.width - 1, self.height - 1, (  0, 255,   0))
17
+        for x in range(0, int(self.gui.width / self.width)):
18
+            for y in range(0, int(self.gui.height / self.height)):
19
+                self.drawOnce(x * self.width, y * self.height)
20
+
21
+    def drawOnce(self, x, y):
22
+        self.gui.set_pixel(             x,               y, (255, 255, 255))
23
+        self.gui.set_pixel(             x, self.height - 1 + y, (  0,   0, 255))
24
+        self.gui.set_pixel(self.width - 1 + x,               y, (255,   0,   0))
25
+        self.gui.set_pixel(self.width - 1 + x, self.height - 1 + y, (  0, 255,   0))
21 26
 
22 27
         for i in range(0, int(min(self.width, self.height) / 3)):
23
-            self.gui.set_pixel((self.width / 2) - 1 + i, (self.height / 2) - 1 + i, (255, 255, 255))
24
-            self.gui.set_pixel((self.width / 2) - 1 - i, (self.height / 2) - 1 - i, (255, 255, 255))
25
-            self.gui.set_pixel((self.width / 2) - 1 + i, (self.height / 2) - 1 - i, (255, 255, 255))
26
-            self.gui.set_pixel((self.width / 2) - 1 - i, (self.height / 2) - 1 + i, (255, 255, 255))
28
+            self.gui.set_pixel((self.width / 2) - 1 + i + x, (self.height / 2) - 1 + i + y, (255, 255, 255))
29
+            self.gui.set_pixel((self.width / 2) - 1 - i + x, (self.height / 2) - 1 - i + y, (255, 255, 255))
30
+            self.gui.set_pixel((self.width / 2) - 1 + i + x, (self.height / 2) - 1 - i + y, (255, 255, 255))
31
+            self.gui.set_pixel((self.width / 2) - 1 - i + x, (self.height / 2) - 1 + i + y, (255, 255, 255))
27 32
 
28 33
     def finished(self):
29 34
         return True

+ 4
- 0
test.py Voir le fichier

@@ -18,6 +18,10 @@ class TestGUI:
18 18
         self.height = height
19 19
         self.multiplier = multiplier
20 20
 
21
+        # compatibility to PiMatrix
22
+        self.panelW = self.width
23
+        self.panelH = self.height
24
+
21 25
         pygame.display.init()
22 26
         self.screen = pygame.display.set_mode((self.width * self.multiplier, self.height * self.multiplier))
23 27
         self.clock = pygame.time.Clock()

+ 5
- 1
util.py Voir le fichier

@@ -22,7 +22,11 @@ def getTarget():
22 22
     target = None
23 23
     try:
24 24
         from pi import PiMatrix
25
-        target = PiMatrix()
25
+        pi = PiMatrix()
26
+
27
+        # TODO hard-coded adjustments
28
+        from mapper import MapperColorAdjust
29
+        target = MapperColorAdjust(pi)
26 30
 
27 31
         if targetIsPi == None:
28 32
             # only print once

Chargement…
Annuler
Enregistrer