[bouLED] Scaling the icosahedron

Wednesday afternoon, the teachers suggested that we make the icosahedron bigger while keeping the same amount of LEDs. This avoids packing the insides together too much, and holes in the PCBs will improve cooling, which is even more important than we previously thought because we messed up the consumption estimation (too low).

The new sphere will have a 35-ish cm diameter (triangles have 18.5cm sides now). I’m currently changing the way we place LEDs: before, we specified spacing constraints and our OpenSCAD program would then put as many LEDs as possible on the triangle. That’s no longer what we want: we want a fixed number of LEDs on the triangle, and the program’s job is finding the layout. For instance, one can specify a number of rows and a different number of LEDs for each row.

When I’m done with that, I’ll print the triangles on paper as a check and then perhaps build a full-scale model with them (thin cardboard will do the trick, I think). It’ll be useful for designing the inner structure, checking that the LEDs layout is uniform enough, and of course, cluttering our desks !

[bouLED] Update on power consumption

Following the suggestions of the teachers, we measured the maximum power consumption of the LEDs again. We may have misused the power generator the first time, or didn’t set the LEDs at full brightness. Anyway, under rigorous measurements, our first triangle of 133 LEDs uses 4.5A under 5V. This is at a blinding brightness, nevertheless this is a huge power if you have 20 triangles and we’re thinking about how to provide it.

After finishing the 3D visualization (though it’s not merged on master yet and one could argue it’s therefore not finished), I joined Hichem on his work with the MARG. We want it working ASAP, so we can be sure we’ll use this chip, and we can start designing the PCBs. We spent some time today debugging his code. We suspect the I2C timings are the reason why we couldn’t get an acknowledge from the MARG, and we hope to solve it tomorrow.

[bouLED] SPI benchmarking, architecture and component choice

SPI benchmarking

In order to maximize the refresh rate, we’d like the SPIs we control the triangles with to be as parallel as possible, which is done using DMA. For each DMA controller, we can run one SPI in parallel.

I wanted to benchmark this, but I ran into problems using ChibiOS’ HAL on a STM32F7 with 6 SPIs. All my SPIs are used in transmit-only mode, but ChibiOS allocates two DMA streams per SPI: one for transmitting, and one for receiving, which is suboptimal when doing simplex communication. There were stream conflicts: one of the SPIs (SPI1 if I recall correctly) uses the same stream for transmitting as another SPI’s receiver stream. What’s more, ChibiOS’ HAL has no unidirectional SPIs, so I couldn’t fix that easily, but on the other hand ST’s HAL supports simplex mode.

In the end, we chose to ditch ChibiOS for FreeRTOS and ST’s HAL (generated using STM32CubeMX). So far, all SPIs work in blocking mode but it’s not parallel yet (i.e, it doesn’t use DMA). When that’s done, it will give us an idea of the refresh time (and hence of the refresh rate).

Architecture & component choice

We’ve calculated that this project needs a 30A power supply. We obtained this figure by checking one strip’s consumption in the lab and multiplying by 20, and adding 4A as a safety margin. In practice, it should suffice if we avoid making the LEDs too bright. The natural choice is a LiPo battery. A 10Ah 5S (5*3.7V=18.5V) with a 15C (15*10=150A !) maximum current discharge will do, it’d last around 20mn. However, it’s expensive: around 150 euros. The LEDs need 5V and the other components 3.3V, so a regulator is needed.

The 3D printed triangles are annoying: there’s wire everywhere, the precision requirements are very strict and they fall apart without scotch tape. To circumvent this, the triangles should be PCBs, but dumb PCBs: electrically, they shouldn’t be more than a APA102 LED strip and a connector. That’s way cleaner in my humble opinion, but that’s more work.

The main board, inside the icosahedron, will host the main MCU, an ESP32 for WiFi communication, and an AHRS array (Hichem is trying one, we’ll see if it’s good enough). The STM32H743ZI seems perfect for the task at hand: it’s really fast (400MHz), it has more than enough cache, 4 DMA controllers (which means up to 4 parallel SPIs !), a 2MB flash and a 1MB RAM. There’s also a STM32 Nucleo devboard using this MCU. Delivery is due tomorrow !

The last 3D printing

After several tries we finally printed a triangle with the right size for the led strip.

Several tries : 3D priting (black) and laser cutter(brown)

I also used a laser cutter but the led strip could not fit within holes again. To use the laser cutter we need someone trained to insure the safety so it was simpler for us to use the 3D printing. The main issue was the fact that we didn’t have accurate enough data. I measured with caliper and re-written the placement of holes algorithme on openscad. After several tries I printed a triangle with the right size and the data were to be very accurate (~20 micron). I took some times because each printing took 2 hours.

The last triangle (orange because orange is the New Black) 

Lucas soldered the led strip, tied the triangle and the led strip together and we have our prototype.

Now I am working on the programming of the AHRS. We use Ultimate Sensor Fusion Solution designed by Pesky Product. It is made up of EM7180 Sensor Hub coupled with the MPU9250 IMU. The EM7180 uses a Kalman filter and provides in output quaternions.

[bouLED] A pretty triangle and a pretty simulator

Last week we finally printed a triangle of the right size (see Hichem’s post). Hichem cut the led strip into smaller ones, and I re-soldered them to fit the triangle, which was not hard but took some time.

92 welding points

For the final object, we won’t have to solder 20 times as many LEDs. We’ll just put individual LEDs on triangular PCBs -we just started drawing the circuit diagrams. The point of this first triangle is to be able to display stabilized animations before all the PCBs are built.

I also worked on the 3D visualisation. Matthias had re-written the first one with PyQtGraph, because VTK didn’t suit him. But this new one had terrible performance: computing the new LED positions every frame made the framerate drop to around 1fps. Therefore, we had to write another simulator. This time, no more compromises, no more Python, just C++, OpenGL and sweat. Matthias set up the OpenGL context and let me have fun with matrices, geometry, textures and instancing. It’s not quite finished yet (not to mention glitches), but we can dynamically color each LED, rotate the model by feeding the simulator quaternions via stdin, and still get 300 fps on integrated graphics.

Virtual bouLED

When it’s done, we’ll be able to display images on it, and get an idea of the final result. However we haven’t decided yet how we’ll store and project images on the icosahedron. We’re also unsure if displaying text is possible with our relatively low resolution.

[bouLED] 3D printing

After we made a model of our icosahedron’s one equilateral triangle using openscad. This is the first time I used 3D printer. After two hours, the first print has finished.

The first version

As you can see, the main issue was the led strip can not fit within holes because widening holes I didn’t change the spacing’s dimension between two LEDs and two rows. So the alignment doesn’t match with our LED strip. I fixed it and I tried a new print. After two other hours, the second version is here.

The second version

The alignment is more appropriate, but it’s still not perfect. The reason remains to be determined I think we should to have more accurate data (below millimeter) and if it’s possible with 3D printer available. Tomorrow I will fix and retry another 3D printed triangle.

[bouLED] Simulation, math and component choice

Towards a blinky simulator

It’d be convenient if the simulator allowed us to test the projection algorithm. To do this, there should be coloured spheres “stuck” to the facets of the icosahedron, arranged much like the holes in my last post‘s triangle. I haven’t written the sphere layout algorithm yet, but as a proof-of-concept, I put a sphere above the icosahedron and made it orbit the icosahedron when it is rotated. It is done by rotating its position vector using the incoming quaternion. Once all LEDoids are created, for each input quaternion, the software will have to loop through all the spheres and make them rotate around the icosahedron, so that they appear not to move in its frame of reference.

That’s a scene graph: the LEDs are children of the icosahedron, and making the icosahedron rotate makes the LEDs rotate. PyQtGraph doesn’t include scene graph handling, but this is a pretty simple one, so doing it manually will probably be less hassle than picking another library for this (VisPy, for instance).

In the end, the simulated projection algorithm should be able to change the spheres’ colours: this will allow us to test it.

First ideas for a projection algorithm

There is one physical icosahedron, and a virtual, stable icosahedric image, that we’ll call V. To find what facet of V a LED is in, rotate the LED’s position vector using the quaternions from the sensor fusion algorithm, normalize it and find the facet of V whose normalized normal (rolls off the tongue, huh ?) vector has the highest cross-product with our normalized LED position vector.

Once the facet of V is known remains the task of finding the right colour, but I haven’t given it too much thought yet. Finding this triangle for each of the 2000+ LEDs is going to be really computationally expensive, so perhaps we could do some kind of dichotomy algorithm, using a first dot product to find which hemisphere we’re interested in.

MCU choice

So far, we’d like to use a STM32F7 MCU, especially for its FPU and L1 cache (16KB+16KB for instructions and cache in STM32F7x8/9 MCUs !). A specific STM32F7 MCU has not been chosen yet.

[bouLED] More on the LED strip

Yesterday I stopped making knots with the wires: I soldered them to the LED strip on one end, and put pins on the other.

Before / After

The issues I had to control the last LEDs of the strip were actually due to the APA102 datasheet being wrong, in addition to being poorly translated from Chinese into English. The “end frame” of the SPI message it described was indeed required, to supply more clock signals than the length of the payload. But not enough if you have a hundred LEDs, as explained on this very informative blog. The data signal being delayed by half of clock cycle by each LED, the length of the end frame should be proportional to the number of LEDs.

Then there’s the brightness setting, 5 bits on each LED frame, which everyone agrees to set to 0b11111 and forget about.

It turns green on the 100th time

We should soon have a 3D printed triangle that fits the LEDs (see my friends’ posts). The LEDs shall then be rearranged: we’ll cut the ribbon into smaller ones and re-solder them. Then we’ll look at the signal coming out on the end of the ribbon and see if we can put another one in series.

To build the 19 other faces, we might need a few more LED strips. We did some measurements, and one 5V LED strip consumes a bit more more than 1A. Until now our test card could supply enough power when using a reasonable brightness, but with more than 15 times as many LEDs, we’re looking at big batteries for bouLED to be autonomous.


[bouLED] Visualization shenanigans and 3D modeling

A new simulator

I was trying to replace the cube in Lucas’ simulator (see here) by an icosahedron and add some kind of clue of the icosahedron’s orientation, but the Python 3D library we used, VTK, was getting on my nerves. Adding an icosahedron worked fine, but I wasn’t able to change its colors, and what’s worse, even when using the default colours (blue everywhere), one of the model’s facets stayed red, which was pretty jarring. I also added an axes widget that was supposed to rotate with the icosahedron, but to no avail: it wouldn’t rotate. One of us had to go, and it wasn’t going to be me.

Alexis sent us a script 11 days ago that displayed a colorful icosahedron with PyQtGraph, which provides a light abstraction over OpenGL. It made a nice starting point for a new simulator, with a rotating icosahedron, a fixed grid and axes. Behold !

Granted, it’s still ugly, but it works and PyQtGraph is way nicer to deal with than VTK.

3D modeling

We’d like our icosahedron to have 13cm equilateral triangles, which would make it fit snugly inside a 25cm transparent spherical shell for protection.

At first, we wanted to build the icosahedric display with triangular PCBs, but last week, our teachers suggested trying to 3D print a facet and put a LED strip (one the ubiquitous APA102 strips) on it, to check density, and if triangular PCBs are really necessary: perhaps we could have a PCB inside the isocahedron control LED strips glued to the facets.

Hichem and I made a model using OpenSCAD to understand how to lay the LEDs out. It’s a pretty neat piece of software for 3D declarative modeling. I really appreciated that because in this case, we had to be explicit and think about our constraints. So far, here’s what we’ve got:

The LED strips are meant to go under this. Using this model, we see that with the strips and dimensions we chose, there’s 111 LEDs per facet, so 2220 LEDs overall. That’s huge, and we’ll have to discuss whether having that many LEDs is feasible (or desirable, for that matter).

[bouLED] Turning LEDs on

As we want to use led strips for bouLED, trying to turn these LEDs on with our microcontroller would be a good start.

Our STM32L475 luckily happened to have SPI controllers. I used one in the frequency range recommended in the APA102 LED strip datatsheet, that is around 1MHz, to display simple animations on the ribbon. After some playing with the wires and some endianness considerations, I could control almost all of the 133 LEDs (and I’m investigating why some won’t obey). 
Thanks to ChibiOS, the current implementation already makes use of the DMA, so that SPI transactions don’t take up much CPU time.

The next step will be to see if we can increase the frequency. Then we’ll need to consider more LED strips: the SPI controllers can only send data on a few GPIOs, while we might need to plug 20 LED strips (or less if we can put some in series).