OK, people are still coming in but I think we can get started. Hello everyone, thanks for coming out today. I'm Dan and I'll be moderating along with Dusan today as we welcome Garrett Mace to the Hack Chat. We'll be talking about cool tricks to making LED matrix project easier and better.
Hey everyone!
Hi Garrett! Can you tell us a little about how LEDs became your thing?
Hello and welcome!
They always were! I started experimenting with electronics while LEDs existed, so my first circuits of course blinked an LED or two
"Hello world" of hardware, right?
Once you go from one LED to two LEDs, it's a slippery slope. You never come back!
I have some intro material if it's OK to launch it?
Yeah, go for it
macetech.com. I work on lots of projects, but in this chat will focus on LED stuff. Specifically LED matrixes, non-rectangular LED arrays, and LED matrixes in non-rectangular arrays ;) Here are some examples of projects I've worked on:
Hi, I'm Garrett Mace of
So you can see that while some of them involve 1D and 2D LED arrays, they may not confirm to regular grids
Whoa - just the logisitics of installing that ceiling project must be a story worth telling.
This poses several problems, if you want to make your LED animations make sense in the physical world
The ceiling install was a lot of fun: I got to design and order custom extrusion for example!
neat
We used about 35 networked Teensy 3.6's (thanks Paul)
:)
And 3D mapping done with Touch Designer. This was a collab with Tangible Interaction up in Vancouver BC
Who did you design the ceiling light show for?
Nice! Do you have any tips/tricks for LED mapping with TouchDesigner? Or resources that explain it well to beginners? (I'm teaching a workshop on doing LED art with TouchDesigner now and looking for intro resources)
TD definitely seems to be the leader in lots of LED projects I see. They keep popping up. A bit of a learning curve, but it's soooo powerful!
That was a sort of office HQ for a development up in the Squamish wilds. We had a bear alert on site and had to hide!
Steve: On Touch Designer we had someone else do the intense 3D mapping
Gotcha. Understandable, it can get pretty hairy!
Besides TD, any other tools/techniques you find useful for working with non-rectangular matrices?
It was a very complex setup that mapped stick points into 3D space, mapped patterns onto a model of the actual install
@Dan Maloney can we ask questions here or do we have to fill out the Google Sheet (if we still do that)?
I believe he was projecting textures onto the sticks and extracting them to LED colors
@Orlando Hoilett - ask away! No formalities here!
nice ceiling effect! was that mapped to some kind of cartesian space or work on some kind of connection topology?
grcornwe: I have lots of material on that aspect :)
You can draw shapes pretty easily using (x,y) coordinates just like a computer screen. But what if your project isn't a grid? Maybe it's some other shape, or is distributed within 3D space. The coordinates aren't as predictable, may not be regularly spaced integers...or you might not even want to use Cartesian coordinates.
If your grid is still a grid, but has weird shapes (a grid with holes pretty much) I made a tool for that:
@Garrett Mace so would you consider this a "finished" product? I'm curious how the client deals with systems and hardware that are often considered "prototype-friendly" but not necessarily "deployable" friendly, at least in their breakout forms.
https://macetech.github.io/FastLED-XY-Map-Generator/
FastLED XY Map Generator
by Garrett Mace (macetech.com), inspired by Mark Kriegsman Code: https://github.com/macetech/FastLED-XY-Map-Generator Set the maximum x and y dimensions, layout style (how the LEDs are actually wired), and click Rebuild. Then click LEDs to edit the shape of the array by enabling and disabling pixels. The code is updated in realtime.
haha, I think I came across that generator before and didn't know it was you :-)
And I mean the ceiling LED light show. (Sorry for asking out of turn...it's hard to find a good place to jump in).
Orlando: it was a finished install, but yes: we could really have used OTA. There was a startup reset sync issue on the Teensy that was a bit difficult when you need a lift to go fix it
Interesting.
yuck, yeah OTA would be good
Other ways to map LEDs to physical space: you can make a 3D model and find a way to extract the LED point coordinates
I would love to see a picture of the hardware brains. 35 Teensys is pretty intense. Lol.
35 teensy's working together in concert? wow
are the teensy boards are connected to a computer which provides the display data? if so, what interface does that use
directly.In the following case I used Blender to generate some of the geometry, and calculated an X, Y, Z, radius, theta, and phi angle lookup table.
I made an LED project for my house, and modeled it in Blender. Sometimes you can just draw your object in a 3D CAD program and extract the coordinatesAre the LED Matrix Shades a kit or do they come already assembled?
anfractuosity: Yep, all ethernet to a pretty intense server :) SACN was not able to keep up so I had to write my own trimmed down protocol
Simon: those are pre assembled, the RGB Shades are optional assembled
For the 3D model above, the lookup table looks like this:
@Garrett Mace You type so fast! I was gonna answer that one :p
"sACN was not able to keep up"
What pixel count / frame rate were you targeting?
ooh nice, so each teensy board has it's own ethernet jack?
1
// r, phi, theta, x, y, z
2
float spherical_map[32][6] = {
3
{ 19.50, 2.58802, 0.00000, 10.25176, 0.00000, -16.58769 }, // 0
4
{ 15.50, 1.57080, -0.55357, 13.18514, -8.14874, -0.00007 }, // 1
5
{ 19.50, 2.12437, -1.57079, 0.00016, -16.58766, -10.25181 }, // 2
6
{ 23.50, 2.58802, 3.14159, -12.35463, 0.00000, -19.99033 }, // 3
7
{ 19.50, 2.12437, 1.57079, 0.00016, 16.58766, -10.25181 }, // 4
8
{ 19.50, 1.57080, 0.55357, 16.58776, 10.25164, -0.00009 }, // 5
9
{ 27.50, 1.01722, -1.57081, -0.00022, -23.39285, 14.45768 }, // 6
10
{ 19.50, 1.57079, -2.58803, -16.58776, -10.25164, 0.00009 }, // 7
11
{ 15.50, 1.57079, 2.58803, -13.18514, 8.14874, 0.00007 }, // 8
12
{ 27.50, 1.01722, 1.57081, -0.00022, 23.39285, 14.45768 }, // 9
13
{ 23.50, 0.55357, 0.00000, 12.35463, 0.00000, 19.99033 }, // 10
14
{ 19.50, 0.55357, 3.14159, -10.25176, 0.00000, 16.58769 }, // 11
15
{ 23.50, 2.18628, -0.78539, 13.56782, -13.56756, -13.56780 }, // 12
16
{ 27.50, 1.93567, 0.00000, 25.68969, 0.00000, -9.81277 }, // 13
17
{ 27.50, 2.77673, -1.57078, 0.00011, -9.81249, -25.68978 }, // 14
18
{ 15.50, 2.77673, 1.57078, 0.00006, 5.53068, -14.47970 }, // 15
19
{ 15.50, 2.18628, 0.78539, 8.94899, 8.94882, -8.94898 }, // 16
20
{ 19.50, 1.20593, 0.00000, 18.21635, 0.00000, 6.95805 }, // 17
21
{ 27.50, 1.57080, -1.20593, 9.81269, -25.68971, -0.00000 }, // 18
22
{ 15.50, 2.18628, -2.35620, -8.94892, -8.94889, -8.94897 }, // 19
23
{ 23.50, 2.18628, 2.35620, -13.56772, 13.56767, -13.56779 }, // 20
24
{ 23.50, 1.57080, 1.20593, 8.38539, 21.95303, -0.00000 }, // 21
25
{ 23.50, 0.95531, -0.78540, 13.56772, -13.56767, 13.56779 }, // 22
26
{ 23.50, 1.57080, -1.93566, -8.38539, -21.95303, 0.00000 }, // 23
27
{ 27.50, 1.93566, 3.14159, -25.68973, 0.00000, -9.81263 }, // 24
28
{ 27.50, 1.57080, 1.93566, -9.81269, 25.68971, 0.00000 }, // 25
29
{ 15.50, 0.95531, 0.78540, 8.94893, 8.94889, 8.94897 }, // 26
30
{ 15.50, 0.36486, -1.57081, -0.00006, -5.53068, 14.47970 }, // 27
31
{ 15.50, 0.95531, -2.35620, -8.94899, -8.94882, 8.94898 }, // 28
32
{ 19.50, 1.20593, 3.14159, -18.21632, 0.00000, 6.95814 }, // 29
33
{ 23.50, 0.95531, 2.35620, -13.56782, 13.56756, 13.56780 }, // 30
34
{ 27.50, 0.36486, 1.57081, -0.00011, 9.81249, 25.68978 }, // 31
35
};
36
37
int pixels_to_verts_map[] = { 5, 22, 17, 10, 27, 9, 26, 25,
38
21, 4, 13, 0, 14, 18, 16, 12,
39
23, 2, 24, 3, 15, 8, 7, 19,
40
20, 30, 31, 29, 11, 6, 28, 1};
41
42
typedef struct pixel_info {
43
float r;
44
float theta;
45
float phi;
46
float x;
47
float y;
48
float z;
49
} pixel_info;
50
51
52
pixel_info get_pixel_info(int pixel) {
53
pixel_info temp_pix;
54
55
temp_pix.r = spherical_map[pixels_to_verts_map[pixel]][0];
56
temp_pix.theta = spherical_map[pixels_to_verts_map[pixel]][1];
57
temp_pix.phi = spherical_map[pixels_to_verts_map[pixel]][2];
58
temp_pix.x = spherical_map[pixels_to_verts_map[pixel]][3];
59
temp_pix.y = spherical_map[pixels_to_verts_map[pixel]][4];
60
temp_pix.z = spherical_map[pixels_to_verts_map[pixel]][5];
61
62
return temp_pix;
63
}
Currently working on a pi pico based hub75 driver. Great performance overall apart from usb. Only issue is to actually get the data fast enough via usb for actual video.
uart is fast than its onboard usb cdc port... best might be a ft232h with the parallel fifo
Steve: We had about 42,000 pixels, it was pretty hard to stay above 30fps
42,000 is a lot of LEDs.
wow, 42K
How do you manage LED failures at that scale?
Great question
haha
We used a white-white-white strip, and we're only using one channel :)
how do you estimate the framerate you'll be able to get while planning?
We get three chances to fix a burned out LED. If the controller fails though, it's toast and an on-hands repair
https://www.tangibleinteraction.com/artworks/summit
If like me you wanted more photos and info on the ceiling install:Nick: I've never tried. I usually do stuff on a slow mcu and then switch to a Teensy when it's too slow :)
For the 3D spike ball, a lookup table lets you write simple generative patterns based on physical space instead of having to think about rendering shapes to a grid
1
for (int i = 0; i < NUM_LEDS; i++) {
2
pixel_info pix = get_pixel_info(i);
3
uint8_t pixangle = (pix.theta + PI) * 255 / (2*PI);
4
LEDChannels[i] = ColorFromPalette(currentPalette,pixangle+angle,brightness);
5
}
That's an example code that sweeps a pattern from "north pole" to "south pole" on that ball
Can also do an "explode" animation by actuating radius, etc
For my LED nonagon project, based on nine Pink Pixel Purse 16x32 displays, it was a challenge to map the rotated translated nine-sided circular array to coordinates I could use to generate patterns. I ended up using Python to perform affine matrix transformations on the panels. YES, you DO sometimes use that stuff from way back in school!
That was HUB75 panels of course. I think it 4 or 5 thousand pixels?
Are you using Numpy or some other accelerated math?
Great questions! Here's the answer:
@ operator). Transform functions do already exist in Python libraries, but I wanted to understand it a bit better so created the transforms myself.
Basically, if you can get the starting coordinates of all the pixels in your LED matrix and unwrap them into a row of x values, a row of y values, and a row of ones, you can perform rotation, translation, and scaling operations with a simple matrix multiplication (which in Python is the
1
def rot_matrix(angle, matrix):
2
rot_sin = np.sin(angle*np.pi/180)
3
rot_cos = np.cos(angle*np.pi/180)
4
rot = np.array([[rot_cos, -rot_sin, 0],
5
[rot_sin, rot_cos, 0],
6
[0, 0, 1]])
7
return rot @ matrix
8
9
def trans_matrix(x, y, matrix):
10
trans = np.array([[1, 0, x],
11
[0, 1, y],
12
[0, 0, 1]])
13
return trans @ matrix
For a 2x2 matrix, you can do a transform and watch how the numbers start simple
Ah, wow, more built-in than I expected. I mean, it's Python so I should have expected that. Guess I need to get good at matrix math (I already knew that)
https://www.instagram.com/p/BLmbo7IDnrD/ (Sorry, I didn't have a gif of this to attach)
This is my favorite LED matrix Garrett has made:Crank up the resolution and you can see it's not something you'd just tweak to look right. If you want to generate a pattern on a tilted matrix
That's more of a spiral Jason ha
@Jason Moungey that's a disco stick if
Discussions
Become a Hackaday.io Member
Create an account to leave a comment. Already have an account? Log In.