|
@@ -0,0 +1,204 @@
|
|
1
|
+title: RGB LED Matrix visualizer
|
|
2
|
+description: For HUB75 modules, running on Raspberry Pi and Pico W
|
|
3
|
+parent: projects
|
|
4
|
+git: https://git.xythobuz.de/thomas/rgb-matrix-visualizer
|
|
5
|
+date: 2023-09-05
|
|
6
|
+comments: true
|
|
7
|
+---
|
|
8
|
+
|
|
9
|
+I initially bought a 32x32 RGB LED matrix in 2018.
|
|
10
|
+Back then the idea was to fit it onto a bag, as some kind of wearable device, for 35C3.
|
|
11
|
+But it never really worked out.
|
|
12
|
+So in preparation for CCCamp23 I noticed the LED panel again and decided to order some more of them.
|
|
13
|
+
|
|
14
|
+These are the [32x32 4mm pitch RGB LED Matrix Panels from Pimoroni](https://shop.pimoroni.com/products/rgb-led-matrix-panel?variant=35962488650), with either the [Interstate 75 W](https://shop.pimoroni.com/products/interstate-75-w?variant=40453881299027) or the [Adafruit RGB Matrix Bonnet](https://shop.pimoroni.com/products/adafruit-rgb-matrix-bonnet-for-raspberry-pi?variant=2257849155594) to run them with a RP2040 or a Raspberry Pi, respectively.
|
|
15
|
+
|
|
16
|
+<!--%
|
|
17
|
+lightgallery([
|
|
18
|
+ [ "img/led_matrix_visual_1.jpg", "Tetris (paused)" ],
|
|
19
|
+ [ "img/cccamp23_matrix_1.jpg", "Someone tries to beat Breakout" ],
|
|
20
|
+ [ "img/led_matrix_3d_1.png", "3D design for panel mounts" ],
|
|
21
|
+])
|
|
22
|
+%-->
|
|
23
|
+
|
|
24
|
+Everything runs from a single Python [codebase](https://git.xythobuz.de/thomas/rgb-matrix-visualizer), either simulated in a GUI window on a development PC, on the Raspbian Python interpreter or directly on the Pico MicroPython environment.
|
|
25
|
+
|
|
26
|
+<!--%
|
|
27
|
+lightgallery([
|
|
28
|
+ [ "img/led_matrix_gui_1.png", "Screenshot of weather widget" ],
|
|
29
|
+ [ "img/led_matrix_portable_1.jpg", "Portable matrix showing a QR code" ],
|
|
30
|
+ [ "img/led_matrix_portable_2.jpg", "Portable matrix showing battery state" ],
|
|
31
|
+])
|
|
32
|
+%-->
|
|
33
|
+
|
|
34
|
+For portability I'm simply using a voltage regulator to connect a 4S LiPo battery.
|
|
35
|
+I made one of them from recycled single-use vape batteries, but I also used some of my RC-model batteries.
|
|
36
|
+
|
|
37
|
+<!--%
|
|
38
|
+lightgallery([
|
|
39
|
+ [ "img/led_matrix_portable_3.jpg", "Recycled vape batteries" ],
|
|
40
|
+ [ "img/led_matrix_portable_4.jpg", "Back side of portable matrix" ],
|
|
41
|
+ [ "img/led_matrix_portable_5.jpg", "Pico without voltage regulator" ],
|
|
42
|
+])
|
|
43
|
+%-->
|
|
44
|
+
|
|
45
|
+On the software side I wrote some code to show static images, GIF animations, scroll text across the matrix, etc.
|
|
46
|
+I also implemented Snake, Tetris and Breakout, as well as some other utilities, like OTA updating for the Pico, a Telegram bot integration, a weather widget and a service checking if a device is reachable on the network.
|
|
47
|
+
|
|
48
|
+<!--%
|
|
49
|
+lightgallery([
|
|
50
|
+ [ "img/led_matrix_visual_2.jpg", "Tetris" ],
|
|
51
|
+ [ "img/led_matrix_visual_3.jpg", "Game of Life" ],
|
|
52
|
+ [ "img/led_matrix_visual_4.jpg", "Aphex Twin logo" ],
|
|
53
|
+])
|
|
54
|
+%-->
|
|
55
|
+
|
|
56
|
+Right now the 64x64 panel is placed next to the TV in my livingroom, randomly cycling through some animations and games.
|
|
57
|
+
|
|
58
|
+<!--%
|
|
59
|
+lightgallery([
|
|
60
|
+ [ "img/led_matrix_visual_5.jpg", "Animated globe" ],
|
|
61
|
+ [ "img/led_matrix_visual_8.jpg", "Animated Sephiroth" ],
|
|
62
|
+ [ "img/led_matrix_visual_9.jpg", "Animated Cloud" ],
|
|
63
|
+])
|
|
64
|
+%-->
|
|
65
|
+
|
|
66
|
+I wasn't really able to get breakout into a playable state before CCCamp23.
|
|
67
|
+But luckily I also got a patch set ([1](https://git.xythobuz.de/thomas/rgb-matrix-visualizer/commit/8e257111464a90a983bd2bc4f6092c12ebf08374), [2](https://git.xythobuz.de/thomas/rgb-matrix-visualizer/commit/8ff126684afb7dfa48a2d7060e390e8233045bb9), [3](https://git.xythobuz.de/thomas/rgb-matrix-visualizer/commit/43d0b92700f2c2a8adf915bb5a020476409e8e08), [4](https://git.xythobuz.de/thomas/rgb-matrix-visualizer/commit/2399961348fefa849d1892cdf5b5001265a28ffd)) from Jannis that fixed the collision behaviour of the ball in breakout!
|
|
68
|
+We met on the camp and had a very nice time together.
|
|
69
|
+And soon afterwards the patches appeared in my inbox and actually made the game playable!
|
|
70
|
+This was really awesome 😊💪
|
|
71
|
+Thanks again!
|
|
72
|
+
|
|
73
|
+<!--%
|
|
74
|
+lightgallery([
|
|
75
|
+ [ "img/cccamp23_matrix_2.jpg", "Another player already scored 80 points" ],
|
|
76
|
+ [ "img/led_matrix_build_1.jpg", "64x64 panel in my livingroom" ],
|
|
77
|
+ [ "img/led_matrix_build_5.jpg", "Backside of 64x64 panel" ],
|
|
78
|
+])
|
|
79
|
+%-->
|
|
80
|
+
|
|
81
|
+Here are my notes for installing everything on a Raspbian OS.
|
|
82
|
+
|
|
83
|
+<pre class="sh_sh">
|
|
84
|
+sudo apt-get update
|
|
85
|
+sudo apt-get upgrade
|
|
86
|
+sudo apt-get install python3-pip git vim htop
|
|
87
|
+git clone https://github.com/adafruit/Raspberry-Pi-Installer-Scripts
|
|
88
|
+cd Raspberry-Pi-Installer-Scripts
|
|
89
|
+sudo ./rgb-matrix.sh
|
|
90
|
+# Answer y, Bonnet, Quality (and solder the mentioned link on the board)
|
|
91
|
+cd ..
|
|
92
|
+
|
|
93
|
+git clone https://git.xythobuz.de/thomas/rgb-matrix-visualizer
|
|
94
|
+sudo pip3 install Pillow bdfparser "qrcode[pil]" evdev
|
|
95
|
+
|
|
96
|
+cd Raspberry-Pi-Installer-Scripts/rpi-rgb-led-matrix/bindings/python
|
|
97
|
+pip3 wheel --no-deps -w dist .
|
|
98
|
+sudo pip3 install dist/rgbmatrix-0.0.1-cp39-cp39-linux_armv7l.whl
|
|
99
|
+
|
|
100
|
+sudo apt-get install libopenjp2-7
|
|
101
|
+
|
|
102
|
+# append isolcpus=3 to /boot/cmdline.txt
|
|
103
|
+cat <<EOF | sudo tee /etc/modprobe.d/blacklist-rgb-matrix.conf
|
|
104
|
+blacklist snd_bcm2835
|
|
105
|
+EOF
|
|
106
|
+
|
|
107
|
+sudo update-initramfs -u
|
|
108
|
+sudo reboot
|
|
109
|
+
|
|
110
|
+# test python bindings work
|
|
111
|
+cd rgb-matrix-visualizer
|
|
112
|
+sudo ./pi.py
|
|
113
|
+
|
|
114
|
+sudo sh -c 'echo enable_uart=1 >> /boot/config.txt'
|
|
115
|
+</pre>
|
|
116
|
+
|
|
117
|
+Although I'm currently still having some problems getting the `wetterdienst` dependency running on the Raspberry Pi.
|
|
118
|
+
|
|
119
|
+<!--%
|
|
120
|
+lightgallery([
|
|
121
|
+ [ "img/led_matrix_build_2.jpg", "Two small panels and materials for the large matrix" ],
|
|
122
|
+ [ "img/led_matrix_build_3.jpg", "Game of Life on four matrices" ],
|
|
123
|
+ [ "img/led_matrix_3d_3.png", "96x32 frame design" ],
|
|
124
|
+])
|
|
125
|
+%-->
|
|
126
|
+
|
|
127
|
+I also want to give a shout-out to [Pimoroni](https://shop.pimoroni.com/).
|
|
128
|
+I managed to rip-off the power connector on one of the panels.
|
|
129
|
+They sent a replacement without any additional cost, but I took the chance and ordered some more spare panels.
|
|
130
|
+
|
|
131
|
+<!--%
|
|
132
|
+lightgallery([
|
|
133
|
+ [ "img/led_matrix_build_4.jpg", "Power connector ripped-off from PCB" ],
|
|
134
|
+])
|
|
135
|
+%-->
|
|
136
|
+
|
|
137
|
+The modules bought this year have pretty consistent color reproduction.
|
|
138
|
+But compared to the one module I bought five years earlier, there is a very noticable difference.
|
|
139
|
+On these pictures both modules show the same RGB values.
|
|
140
|
+
|
|
141
|
+<!--%
|
|
142
|
+lightgallery([
|
|
143
|
+ [ "img/led_matrix_colors_1.jpg", "Color reproduction issue (1)" ],
|
|
144
|
+ [ "img/led_matrix_colors_2.jpg", "Color reproduction issue (2)" ],
|
|
145
|
+])
|
|
146
|
+%-->
|
|
147
|
+
|
|
148
|
+I added some simple compensation to mostly adjust for this issue.
|
|
149
|
+
|
|
150
|
+<pre class="sh_python">
|
|
151
|
+# For some reason the red and green LEDs on older Pimoroni panels
|
|
152
|
+# are far brighter than on newer panels.
|
|
153
|
+# Adjust this by multiplying rg channels with 0.75 and b channel
|
|
154
|
+# with 0.85, depending on hard-corded coordinate ranges.
|
|
155
|
+class MapperColorAdjust(MapperNull):
|
|
156
|
+ def set_pixel(self, x, y, color):
|
|
157
|
+ # second panel from the left, with 32 <= x,
|
|
158
|
+ # is "old" type with brighter LEDs.
|
|
159
|
+ # rest of panels to the left are less bright.
|
|
160
|
+ # so adjust brightness of other panel channels down.
|
|
161
|
+ if x >= self.gui.panelW:
|
|
162
|
+ color = (int(color[0] * 0.75), int(color[1] * 0.75), color[2] * 0.85)
|
|
163
|
+
|
|
164
|
+ self.gui.set_pixel(x, y, color)
|
|
165
|
+</pre>
|
|
166
|
+
|
|
167
|
+I also planned to build a large LED matrix based on WS2812 LED strips.
|
|
168
|
+They can be [driven easily with a Raspberry Pi](https://iosoft.blog/2020/09/29/raspberry-pi-multi-channel-ws2812/).
|
|
169
|
+
|
|
170
|
+<!--%
|
|
171
|
+lightgallery([
|
|
172
|
+ [ "img/led_matrix_large_5.jpg", "Level shifter for WS2812 strips" ],
|
|
173
|
+ [ "img/led_matrix_large_3.jpg", "Large matrix frame and strips" ],
|
|
174
|
+])
|
|
175
|
+%-->
|
|
176
|
+
|
|
177
|
+I was even able to get a basic frame finished before CCCamp23.
|
|
178
|
+But that's where time ran out.
|
|
179
|
+
|
|
180
|
+<!--%
|
|
181
|
+lightgallery([
|
|
182
|
+ [ "img/led_matrix_large_1.jpg", "Frame for large matrix, back side" ],
|
|
183
|
+ [ "img/led_matrix_large_2.jpg", "Frame for large matrix, front side" ],
|
|
184
|
+ [ "img/led_matrix_3d_2.png", "Corner piece for large 32x32 matrix" ],
|
|
185
|
+])
|
|
186
|
+%-->
|
|
187
|
+
|
|
188
|
+I haven't yet given up that plan completely, but I have to think of a solution for diffusing the light first.
|
|
189
|
+The LEDs are too small and spaced too far apart to look good in this configuration.
|
|
190
|
+
|
|
191
|
+## More Pictures
|
|
192
|
+<a class="anchor" name="more_pictures"></a>
|
|
193
|
+
|
|
194
|
+<div class="collapse">Some more photographs I didn't use above.</div>
|
|
195
|
+<div class="collapsecontent">
|
|
196
|
+<!--%
|
|
197
|
+lightgallery([
|
|
198
|
+ [ "img/led_matrix_visual_7.jpg", "Animated Nintendo 64 logo" ],
|
|
199
|
+ [ "img/led_matrix_visual_6.jpg", "Empty matrix" ],
|
|
200
|
+ [ "img/led_matrix_large_4.jpg", "LED strips for large matrix" ],
|
|
201
|
+ [ "img/led_matrix_colors_3.jpg", "Color reproduction issue (3)" ],
|
|
202
|
+])
|
|
203
|
+%-->
|
|
204
|
+</div>
|