[bouLED] Finishing the main PCB

Last time, I routed the power supply. Since then, I placed and routed all the components and added the ground planes. We’re now waiting for the teachers to review the boards. Below is a screenshot of Xpedition PCB showing what I’ve got so far (ground planes are not displayed, but they’re there):

The green traces are VCC (3.3V). It’s not obvious from the colouring, but some parts of these VCC traces are on the back of the PCB. U3 (the tiny chip above D2) is a LDO regulator (LT1762) that drops the 14.8V VBAT voltage from the LiPo battery (J2) to 5V for the U5 3.3V-to-5V level shifter used for the SPIs (the connectors on the left). U1 is a LT1765 switching power supply for the 3.3V rail. U2 is the STM32H7 MCU. Finally, there’s an SD card (J1) and an ESP32-DevkitC for network connectivity (U4).

[bouLED] Starting placement and routing for the main board

I started placing the 3V3 buck converter first. Here’s what it looks like on the schematic:

The LT1765 switches at a high frequency (1.25MHz), which constrains the routing. The datasheet explains that the most important thing is to make the path from pin 3 to pin 2 through D2 and C2 as short as possible. My layout looks like that so far:



Vias to the ground plane aren’t pictured, but the path I was talking about is really short, and I think it will do the trick. The layout and schematics have yet to be reviewed, though.

[bouLED] Drawing the main board’s schematics

Today, I started drawing the main board’s schematics. It’s not finished yet: the decoupling capacitors have yet to be chosen and I’m not done with the STM32H7 (pins like VBAT, VREF, BOOT0, etc.). As a teaser, here’s the power supply:

It takes a 14.80V input (from a 4S LiPo) and steps it down to 3.3V. That’s not the right buck converter (it should be a LT1765-3.3), but the pinout is the same, so when it’s done I’ll only have to change U1. The SDHDN_n pin is left floating on purpose, according to the datasheet.

Here’s a sneak peek at the unfinished parts of the schematic:


[bouLED] Designing the main board

I’m currently designing the main board. First, I had to create a routing table for the STM32H743VIT6 using one Alexis made as a base. We’re only able to have 5 SPIs, a SD card in 1-bit mode and an UART. Programming and debugging will be done over SWD.

The next step is the power supply, using an LT1765-3.3 buck converter. Using the datasheet, I started choosing ratings for its peripheral components, but it’s getting late so I’ll finish that tomorrow. Next step: drawing the schematic.

[bouLED] LED layout redux and component choice

LED layout

We settled for a layout with 78 LEDs per facet, with a slightly modified border clearance. It looks pretty great on the simulator:

Don’t pay attention to that triangle with white LEDs, it’s coplanar with the z=0 plane, as a reference. You’re seeing the icosahedron from above. The important thing is that the layout looks regular enough, without any weird stuff in the corners, where 5 triangles meet.

Next step: build a paper version of bouLED. Behold !

That thing is HUGE. It was a pain to build using only paper and scotch tape, but it’s really useful to get a better idea of how to design the inner structure. On the flip side, I messed the dimensions up when printing the triangles, they’ve got 21cm sides instead of 18.5cm. The triangles I showed in my last post had the right scale, though (but the LED-to-side margins are slightly different). Notwithstanding my clumsiness while building this, it gives a good idea of what the end result will look like.

Power supply

Choosing a battery

With Lucas, we thought that by limiting the LED brightness, we’d be able to downscale the power supply a bit. The 3D printed prototype triangle (103 LEDs) was already unbearably bright when drawing 1A in white, so we’ll avoid drawing over 20A for all the triangles, at 5V. The main board will run on 3.3V, and 3A is way more than enough for it. That’s 110 watts.

A 4S LiPo battery has a 14.8V output voltage, and for a 110W output it’d spit 7.4A out. That’s a very conservative discharge current for LiPo batteries, a 4S 3000mAh 35C battery like this one can deliver more than 90 amps continuously and its peak current is probably even higher.

With 3Ah, this battery could supply bouLED power (at full brightness !) for 24 minutes. We could have picked one with a beefier capacity, at the expense of its weight. This one weighs 308g.

Voltage regulator choice

Alexis suggested using a small regulator per facet (and another one for the main board), saying that’s it’s way easier than finding a big regulator.

What we need is a buck converter: it reduces voltage but increases current. The part Alexis suggested is a LT1765 from Analog Devices: it’s rated for voltage inputs up to 25V and the output current limit is guaranteed by the datasheet to be above 3A. It has fixed-voltage versions that can output 5V or 3.3V without having to add an external voltage divider.

My previous calculations for LiPo sizing didn’t take into account the fact that a buck regulator transmits constant (without taking efficiency into account, of course) power but at a different voltage. Basically, I did them as if I had a linear regulator. Now, the battery is one third of the price of the one I mistakenly chose, same for the weight.

[bouLED] Choosing a LED layout

I changed the LED layout algorithm to allow us to set a number of LEDs for each row. To improve regularity, the algorithm only takes the bottom row’s number of LEDs, and the row above this has one less LED, and so on. There’s also a “margin” setting for the space between the outermost LEDs and the triangle’s edges.

Here are all the layouts I generated, printed on paper with a 1:1 scale, and a 5 cents coin for scale.

We’d appreciate your feedback on this: which variant is your favourite ? You can click on the images to display them in their full size.

[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] 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 !

[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] 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).