A quirk of these LED matrix panels is that they simultaneously update two rows at once, separated by half the panel. So on a 64x64 panel, you update rows 0 & 32, 1 & 33, 2 & 34 etc. However, if you want to sweep one around an axis, you ideally want to update the outer LEDs at a faster rate than the inner ones, and this layout prevents that.
Making parts for this has been a real saga, so while I wait for a faster printer to arrive I tried removing the collimators and running it as a swept volume display. Now I’m thinking maybe that’s what I should have built in the first place.
The thing I've been trying to make creates its 3D effect by displaying a whole different view in every direction, which means it can handle occlusion and fancy lighting at the cost of vertical parallax.
To turn that setup into a swept volume (where it's lighting up the LEDs according to where they are in space - full 3D, but glowy and transparent) I keep everything but the collimators, and just render each view with the near & far clip planes set really close together.
I'll probably make two displays now - finish off the autostereoscopic one, but then rearrange the geometry so that I can sweep through more than just a thickish-walled cylinder.
The nice thing about these LED panels is that they're very high framerate (and cheap!). I'm updating these at 1.5 KHz - with 3 of them in a ring, that's 4.5 KHz. Just driven in software from a (somewhat dizzy) Raspberry Pi.
The depth is smeared more than I want because the collimators are too shallow (because I don't like prints that take more than 16 hours to complete). I want to make them tighter, and spin the whole thing faster to compensate.
I'm arranging it as two rectangular panels arranged with their bottom edges touching on the axis, which lets me update columns at the same radius simultaneously. The outer columns need to be updated more frequently than the inner columns, and one of the nice things about these LED panels is that you choose your own update strategy - you're not stuck with scanning a whole frame each time.
If the lines were completely independent, you could evenly scan a sector with half the number of line updates compared to updating the whole frame. As it is, each line has to be updated in parallel with one that's half a panel further down, so it ends up taking 3/4 of the line updates instead (because some updates have to update the outer line while scanning out black to the inner line).
Scouring Aliexpress for LED panels for the new display, and it seems the higher resolution ones tend to be flexible. I spent a while investigating developable surfaces* to see how I could take advantage of this, but couldn't come up with a layout that offers any advantages over a flat square centred on the axis. Seems disappointingly pedestrian.
Most of the time we don't move our heads up and down very much, so the lack of vertical parallax seemed like it wouldn't be a big limitation. But one of the situations where we do move our heads quite a lot is when presented with a neat little 3D effect sitting on a desk.
The advantages of this approach - occlusion and view-dependent lighting - are undermined by the fact that too much of the colour depth is sacrificed to hitting the necessary framerate. The sort of simple scenes it can display could be displayed better by a swept volume.
It would be convenient to address the voxel data as a stack of horizontal slices, because that's how it's exported from lots of existing tools. I have to rotate it 90 degrees though, because scanning out is faster if each column's data can be addressed as consecutive bytes. It's a small change, but there's a 6.5x difference in speed between the two orientations, which directly translates into voxel density in the final output.
This is still using software bit banging. I'm going to switch it to using DPI, but the current interface board wasn't designed with that in mind, and the GPIO mapping doesn't put all 3 displays on valid DPI pins.
I had the opportunity to give some live demos of this thing recently. It went over well, but the noise was a real killer. I've reworked it to use a belt drive instead of the horrible 3D printed gear - before, it screamed; now it whirrs.
The results I was getting with the new display were so much better than the original that I went back for another pass at it. Turns out there were a couple of stupid bugs limiting the refresh rate. The colour depth is now vastly improved.
New display, new panels. I'm driving these ones using DPI on a Raspberry Pi, which is a handy way of wiggling 24 GPIO lines with precise timing and no CPU involvement.
I had a panel left over, and I thought I should have another stab at an oscillating display. I wanted to give it an undulating motion and came up with what seemed like a nice linkage, but the end result looks like it was designed by Trevithick.
The other problem I have is that to sell the 3D effect I need to move the camera around a lot, so I'm going to have to put some effort into building a studio backdrop.
My target for this display is 600 rpm - lower than that and it's too flickery; higher than that and I can't refresh fast enough to get 400 voxels around the circumference without dropping to 1 bpc. I'm nudging 400 rpm here, and it's still pretty unfilmable and absolutely terrifying to be close to. I have to decide whether the overall approach is worthwhile enough to start spending money on aluminium and polycarbonate.
I've implemented parts of a content pipeline for rendering a scene on the PC and streaming it to this display, but writing video streaming code is so much less fun than playing with voxels that it may take a while to finish. Here, I've stored the animation uncompressed on the display itself, and am updating it as fast as the Pi's SD card can handle. (Not very fast.)
That's the mount for the slip ring. A cylinder carrying a couple of copper bands fits over the pillar, and an M4 bolt goes own the middle to hold it all together. It has very clearly become bent, and without any signs of cracking. Presumably, as it spins, it heats up enough to soften the PLA, and the spring loaded brushes push it out of alignment.
I've reprinted it in ABS; going to see how well that lasts.
It feels as though I'm endlessly rebuilding it, for diminishing improvements. But in the most recent rebuild I finally solved a mystery that has been bugging me. When the display had been running for a while, it would quite abruptly lose balance and start vibrating. After the last occurrence, it was never quite the same. On stripping it down I found this.
In the continuing quest for higher rpm, I've moved the controller down below the screen and across the axis of rotation. It's a lot harder to get at if I need to rewire anything, but it does improve the balance.
If you turn the panels 90 degrees so their scan lines are now columns, you can do a bit better. The update doesn't have to be sequential - instead of stepping one column at a time, you can skip a few each time. As long as you pick a number which is coprime with the number of columns, and you wrap around once you go past the last one, you'll still visit each of them but spread out more evenly throughout the volume.
The real improvement comes when you adjust the update rate for each column to match the length of the track they have to sweep out. Instead of wrapping around when you reach the last column, you wrap around when your counter reaches the square of the number of columns, and you update the column corresponding to the integer square root of the counter. This gets rid of the bright dense region in the middle, and adds more updates out at the edges making them less sparse.
In practice it's complicated by the fact that these panels update two lines at once. Every time you update a column in the outer half, you're also updating one in the inner half. I couldn't find a simple procedural update strategy to spread these evenly, so I ended up generating a lookup table for it using simulated annealing.
First test of the new design, and already I’m happy. Quiet, high refresh rate, and doesn’t feel like it’s seconds away from embedding itself in my face.
This display works by spinning a matrix display rapidly about a vertical axis, lighting up each LED as it passes through part of a 3D image. The way you update the displays has a big impact on the quality of the image. In this gif, each dot represents a column of LEDs - we're looking at the device from above. Here the panel is treated like a 2D display which just happens to be moving. Each scan line is repeatedly visited in turn, sweeping out a set of slices where the image can be displayed.
There’s a fair bit of planning involved in finding the true centre and height of these domes. When I come to make the cut it feels like cleaving the Cullinan diamond.
With the previous dome the cut had a somewhat hand made look to it, so I printed a thin piece of trim to slip over the edge and keep it neat. It was too big for the printer so I used TPU, printing it in a spiral and flexing it back in to the right diameter. An unexpected benefit was that it was way quieter with that isolating the dome from the base. This time the cut went better, but I’m still going to give it a gasket for that reason.
Now thinking I should have filmed the tool I made to press all the clips on this IEC socket so I could get it out of the housing in order to film the satisfying click it makes when it goes in.
So many complaints about the framerate on that last video, so I decided to upload one with a shorter exposure and more flicker. But I still ended up keeping it below 30 fps, so I suspect the complaints will be about both framerate and flicker. Just have to hope the algorithm doesn’t go so large on this one. https://youtu.be/gBfclb9hXCI
New dome! There are many advantages to moving to smaller panels in the new design (momentum etc), but the price drop going to a 300mm dome from 400mm would be justification enough.
There’s now an accelerometer in the base, synced to the rotation of the screen. I’m hoping this will help me get it balanced better. I don’t entirely understand the shape it’s producing, but the line is pointing in roughly the direction I think it should be pointing.