Tryna catch me drivin’ dirty

We decided to use the TLC5957 LED driver of Texas Instruments with Broadcom RGB LEDs: ASMB-KTF0-0A306.


Brightness control

First, we have to determine the maximum current which will be used. The 3 colours of the RGB LEDs can get a 20 mA input current max and the driver can handle 20mA sink current max. So we choose a maximum current of 20mA.

We decided to configure the driver with the maximum value for the Brightness Control (BC) (and by consequence, the maximum gain) to provide the intensity to go over 20mA. So we have to choose a value of BC equals to 7. And to limit the current to 20mA max we have to put a 9.27kΩ IREF resistor between IREF and IREFGND pins.

After that, we have to choose the Colour control for each colour. This parameter is used to choose for each colour, the ratio between the maximum output current for this colour and the maximum output of the driver. This is used to tune the white balance. According to the LEDs datasheet, the mean intensities are 490mcd for Red, 1100mcd for Green, 215mcd for Blue. So, to have the same mean intensity for each colour, we have to choose those values for CC: 224 for Red, 100 for Green, 511 for Blue.

Display control

The main mode of this driver is done to be used with 16-bits colours. However, we want to use it with 9-bits colours. So, we have to use the other mode: the Poker Mode. When we choose the Poker Mode, we have to activate the ES-PWM and the XREFRESH.

Data configuration

The driver contains several registers. We will use the 4 main ones. The first one is the Common shift register (48bits). Every data one wants to input has to be written in this register. The second one is the FC data latch (48bits). This register is used to configure the driver. Both last ones are GS data latches 1 and 2 (768bits each). They are used to save the data and prepare it to be sent to the LEDs.

The communication between registers is led by the SCK clock and the LAT signal.

How to use the driver


First, we have to configure the driver so, we have to configure the FC data latch. To do so, we send bit after bit the 48bits configuration from the MSB to the LSB. In this configuration, we specify different values like the BC, the CC for each colour. We also activate the Poker mode, the ES-PWM and disable the XREFRESH. After sending the 48bits, we send the FCWTREN (LAT high for 15 rising edges) command then the WRTFC (LAT high for 5 rising edges) as below.

Poker Mode

In the traditional mode, we input in the common register the 16bits of each colour from Blue to Red and from MSB to LSB. But, in Poker mode, it is different. We input the bit n of the Blue of the 15th LED then, the bit n of the Green of the 15th LED … until the bit n of the Red of the 0th LED.

So because we use 9-bits colours, we have to first send le Bit 8 of the colours of 16 LEDs then the Bit 8 etc until the Bit 0. Then we output everything. So how does this work? When one has input in the common register the 48 bits data which represent the Bit 8 of the colours of 16 LEDs, one sends WRTGS command (LAT high during one rising edge). This command will copy the 48 bits of the common register in the 1st GS Latch at the address of Bit 8 (address given by the GS data bit address counter). Then the GS data bit address counter is decreased 1. The process is the same for Bits 7 to 1. For Bit 0, one uses the LATGS command (LAT high during three rising edges). This command will do the same thing as WRTGS but, it will also copy the entire 1st GS latch into the second one, it resets the GS data bit address counter to 8 and increased 1 the LINE counter (it will be useful later). But it also forces out the new values which will be sent to the LEDs.

Just below, an example with 10-bits colours. For 9-bits colours, it is quite the same but there are only 8 calls of WRTGS and the GS data Bit address counter starts at 8.


This is a different approach to realize a PWM. The high state period will be cut and spread to minimize the time between high and low states and get a better result.


For this project, we decided to multiplex LEDs by 4. Indeed, this driver has enough pins to control 16 LEDs but on each column, we have 64 LEDs. The process to write data is quite the same as without multiplexing. However, they are some things new. First, we will now also use a line counter. This counter is here to know in which step of the multiplexing we are; do we display the first 16 LEDs, the second, the third or the fourth ones. This counter is used by the LED Open Detection which is used to prevent the caterpillar effect but we will explain this after.

So now how do we write our data? For the three first groups of 16 LEDs, it is still the same: 8 WRTGS + 1 LATGS. However, for the fourth group, the LATGS method will be replaced by the LINERESET command (LAT high during seven rising edges). This command will do the same things as LATGS but instead of increasing the LINE counter, it will reset it to 1. That means we sent the data on every LED.

There is an error in this graph, you should replace XREFRESH=0 by XREFRESH=1

Caterpillar cancelling

The caterpillar effect is a problem caused by broken LEDs in multiplexed architectures. As a result, the LEDs multiplexed with the broken one can blink whereas they should be off when the driver tries to switch on the broken one. The Line Counter and the LINERESET command help the Caterpillar cancelling function to detect the broken LEDs and to automatically turn off the output channel for the specific line (so only turn off the output for the broken LED and not to every LEDs multiplexed with it).

Pro (Component) Choice

Update on the choices in components for Litspin. All of the main components have been chosen. Here are the ones we landed on :

System on Module

After looking at the schematics for CyL3D, we saw that they used around 40 pins on the FPGA IO. This meant that we could use the same Aries Embedded SoM based on a Cyclone V combined with two ARM cores.

LED Driver

For our LED drivers, we’ve chosen the Texas Instruments TLC5957. They give us a high enough input data rate and PWM reference frequency as well as enough channels to drive our LEDs.


The LEDs we will use are the Broadcom ASMB-KTF0-0A306. They are 4-pin (common anode) RGB LEDs.

The wifi module and sensors are given in a previous post.

The hardest choices require the strongest will

The past week I’ve been looking through datasheet after datasheet in order to find several components that would fit our project.

  • Hall effect sensor:

Looking through the different types of hall sensors, I found that a switch sensor was the best fit, since we will use it to get the motor’s speed rotation, we only need to know when the magnet will be aligned with the sensor. The constraints we had on the choice of sensor were not numerous: we need a sensor with digital output, with 3.3V in input. However, one interrogation I have is whether or not the inductive power transmission will infer with the sensor. Alexis said that it was not a problem, but I am still wondering if having a highly sensitive sensor like the one Cyled chose, the TLE4964-4M, won’t increase the risk of interfering with the power transmission. I honestly don’t think it will be a serious issue, but I prefer to be sure before I validate this sensor.

Another issue I had with the position sensor was if it would be precise enough. A solution to that could have been adding an optical sensor in order to have a second measure, but the problem was that most optical sensors use infrared, which we already use for communication. In fact, simply having several magnets on the fixed part allow us to have several measurement points per rotation.

  • Infrared sensor:

Regarding the communication from the mobile part to the static part, Alexis advised us to do some research on the IrDA protocol, which is a communication protocol using infrared transceivers. There are several communication speeds available (SIR, MIR and FIR), but since we only need to transmit speed commands to the motor, the lowest speed (SIR, which corresponds to a standard serial communication speed: 115.2 Kbps) will be sufficient. I chose to use this kit with a emitter and a receiver: TFBS4650-TR1.

  • Wifi module:

For the Wifi module, I had two main choices to make:

  • the hardware interface: I started by searching what Cyled did. However, they did not have much choice regarding the hardware interface, and had to choose a USB module. On the other hand, we have a larger SOM that gives us much more choice: USB, SPI, PCIe are the main ones. I found module for each of them, but I’m still not sure which interface would be the easiest to implement.
  • the protocol version: for the 802.11 protocol there are several versions, such as 802.11b, 802.11n or 802.11ac., 802.11ac is the most recent one and the fastest, but it also consumes more power, and most importantly, we don’t need that kind of speed, since we won’t do any streaming. Consequently I choose to stick with 802.11b/g/n compatible modules.
  • Leds:

In terms of lighting, we have the same constraints as Cyled, so we will just take the same: ASMB-KTF0-0A306.

EDIT: I didn’t publish this post right after I wrote it because at the time we were waiting for answers from Alexis, and I wanted to publish it with the answers.

After the discussion, several things changed:

We will in the use a sensorless motor, as Cyled did, so this eliminates the need for a IrDA communication with the motor. No IrDA communication means we can use an optical sensor along with the Hall sensor in order to increase to precision of the speed measurement, just like Cyled did. We will use the TCUT1600X01.

As for the Wifi module, in the end we will go with an ESP32-WROOM wifi module which will communicate in UART with the PCB.

That’s it for the choice of these components. We can now start making the PCB!

Weird flex but okay

The issue of centrifugal force

When you try to rotate at a relatively high speed, centrifugal force comes with the territory. The issue is that PCBs are not the most robust pieces in a mechanical system. We need to find a way to make them stronger to hold them in place so they don’t fly away and/or break and find their way into a bystander’s face.

We tried to figure out how much the PCBs would flex. Thankfully, Wikipedia exists and our problem is a classic strength of material case. We have an issue similar to beam theory’s cantilever beam case with a spread out force. Wikipedia has an article with the relevant formula giving us the information we need.

the last formula is the one giving the vertical flex in relation to x. In this formula, w is the force per length, E is Young’s Modulus for the material the beam is made of, I is the second moment of area for the beam and L is the beam’s length.

With this formula, we can deduce that a PCB will flex about 2.5cm if left on its own. Needless to say, in this formula, an assumption is made that it would not break. We need to find a way to reduce flex as much as possible.

A path to solutions

We explored ways to make the PCBs stronger. For now, the best solution we have is small steel beams on each side of the PCB. We estimate that flex would then go down to about mm. There might be a better solution but we have not found it yet and mm of flex over a cm PCB does not seem to be that much and might work.

A first look at the FPGA architecture

In order to synchronize the LEDs and create a persistence of vision image, we use a CycloneV SOC.

Here is a first idea of the architecture we might use :

The ARM processor fills a buffer with the next image to be displayed, that is then swapped with the second buffer. It can pull this image from the SD card, or from another source such as the text printing function we plan on adding.

The full buffer is then accessed by a Direct Memory Access (DMA) IP that then sends the relevant cylinder (32 * 128 pixels) to each LED band controller that is then stored in their memory.

The sync module uses the signal from the hall effect sensor to compute the current rotation speed and deduce the approximate angular position of the rotating part(current_angle).

This current_angle combined with the pcb_angle parameter (that gives the angular position of the PCB in the configuration) allows each LED band controller to read a in the relevant addresses of their memory and flash the LEDs with the color corresponding to their position.

This first draft gives us an idea of the architecture we are going to use, however a lot of choices have still to be made, such as the type of buses to use.

Wireless power transmission and Motor choice

Power Transmission choices and explanation

As referenced in a previous post we need a way to wirelessly transfer power from the static part to the rotating part of our system. We found a 200W dev kit from Würth Elektronik but it seemed over-powered for our needs. Another integrated solution exists but is only good for 60W. Therefore we needed to estimate how much power our rotating system would need.

The bulk of our needs is in the LEDs. Considering 1280 LEDs and a multiplexing factor of 1:4, we would consume at most the power of 320 LEDs at a time. According to the specifications, an LED could use 60mA@3.3V at most. This gives us a max power consumption of 63W just for the LEDs. Even though this is a worst case scenario, it seemed to us that using a 60W power supply would be too risky, even more with all of the other components (SoM, wifi module etc..) and taking into account a DC-DC converter efficiency of 95%.

Since we couldn’t find another solution for wireless power transmission between 60W and 200W, we stuck with the 200W option, a using only coils and making our on driving circuitry would require us to be experts in induction power transmission and power supply design.

Motor and ESC choice

Our search for a BLDC motor took us all over the e-bike, drone and RC car and boat world. At first, we found a motor at Alien Power Systems but couldn’t find an ESC to match so they directed us towards Maytech. They make both ESCs and BLDC motors. We need a motor with enough torque to start the rotation considering our system will be quite heavy compared to an RC car or a drone propeller.

Getting both the motor and ESC from the same brand made it so we didn’t have to solder connectors or bother with pinout issues. It would allow us to have better support down the line should we have a technical issue. We then chose a Maytech MTVESC50A for our ESC which gives plenty of power for the Maytech 5055 1100W 70KV motor.


LitSimulate is a simulator which simulates what LitSpin will display. We developed the first versions with PyOpenGL and PyGame.

Image Format

Each 3D image is represented by a classical image. If we note r the radial resolution (total number of columns), h the number of LEDs by column and n the number of steps by rotation, our image dimensions are rh x n. In our case r=20, h=32 and n=128. So we have 640×128. One line represents the n points one led will display. And each block of h lines represents the 360° image of a column from the outermost to the innermost (from 1 to r). Just below an example with r = 8.

Example of image for r=8

Examples of simulation

We made some simulations with r=10, h=10 and n=100


For now, we simulate an 8-bits-by-colour display and not a 9-bits-by-colour one. This is just because it is easier to create an 8-bits image on the internet rather than 8 bits. However, it will be very simple to change LitSimulate into a 9-bit simulator.

The main issue is a problem of memory. Indeed, the RAM is constantly filling up until the PC is completely blocked. So we can only use this first version of the simulator for a few seconds. Moreover, we can’t simulate with our real values of r, h and n because it takes too much memory to display the results. To deal with this issue there will be several steps:

  1. We will try to fix it by keeping Pygame et PyOpenGL
  2. If we can’t, we will try without PyGame and only use PyOpenGL (because PyGame is used to initialize OpenGL display). Maybe we would directly go to step 3
  3. If it is still too slow, we will make the simulator in C++
  4. If it is still too slow or too complicated, we will try the Point Cloud Library for C++

Gobal architecture for LitSpin

In order to better understand how to make LitSpin a coherent and functionnal device, we created a diagram of its architecture .

The following represents how the different modules will communicate and work together. Technical details will come later as choices in components and communication buses are made. This is not supposed to be a drawing so it is not representative of how LitSpin will look but it should give an idea of how it will work.

Basically, there will be two main systems. A static system that will have an electric motor and what is needed to control it : a control board that will communicate with an Electronic Speed Controller, the accompanying BLDC motor, an IR receiver that will get information from the rotating system and the induction power transmitter.

The rotating system will contain the bulk of the project. The DC-DC power supply converting 24V to 5V, our SoM, LED drivers and multiplexing circuits and other modules. The SoM will contain both an ARM processor and an FPGA element to control the drivers and multiplexing circuits.

In order to have one driver per 64 LEDs, we will be multiplexing our LED outputs 1:4. Each PCB will then consist of 32 LEDs on each side, one TLC5957 driver and the multiplexing circuitry.

As for communication, the rotating system will have a Wifi module that a user will be able to connect to and an IR LED to send motor control information to the static PCB.

Ah, yes. Stereoscopic vision.

This is a follow-up to my previous article, in which we explored the choice of PCB placement in order to get an optimal visibility.

My previous analysis only covered the case of a punctual point of view. However, most people have two eyes, which provide a double point of view and could increase our coverage of space. It is to be pointed out that a point of space seen by one eye does not provide depth information to the brain, however let us assume that our image perception is smart enough to overcome this limit.

In the following simulation, we used a typical eye distance of 6 cm. To understand the different configurations, please refer to this article.

As you can see, the dispositions that seem to benefit the most of stereoscopic vision are modulo forests, particularly the ones where the repartition of PCBs seems the most uniform. The parallax effect is all the stongest when PCBs hiding each other are far away in the axis of vision. Modulo forests with k = 3 and 11 seem to be good candidates as the front portion of the cylinder is (almost) complete in both cases.

Choosing a shape

As stated in this previous post, we have to compare different PCB dispositions to avoid blind spots. We soon came to realization that we would not be able to get rid of blind spots with our design, but it is possible to study the different ideas we came up with in order to mitigate this issue.

That’s why we created a python program that can simulate :

  • blind spots created by PCBs hiding each other
  • the variations of brightness due to the fact that LEDs can be seen at an angle (which is what created the dark center zone in CyL3D, which we are trying to get rid of)

Stairs : an iteration over CyL3D’s design

To avoid the issue of a dark zone due to all LEDs facing the observer at an angle in the center zone, an idea was to make sure that all LEDs were not facing the same direction. There came the stairs idea:

Stairs design. The PCBs have LEDs on one face.

After modelling this idea in python we get:

As you can see, there are a lot of deadzones, particularly in the central viewing axis.

The radial revolution?

Imagine a configuration with one vertical PCB with LEDs on both sides, facing the radial direction. Wait, don’t. I modeled it so you don’t have to :

This creates a 2D cylindrical POV display, with dark zones on the sides, which is in our opinion much better than a center dark zone. To create a 3D POV display, we “only” need to add concentric cylinders. The question is now: how serious is the problem of PCBs hiding each other and how to avoid it.

Spiraling down the rabbit hole

The idea of spirals seems natural. PCBs can laid out with an angular offset when compared to the adjacent PCB. For balancing reason, we alternate the PCBs with a central symmetry in order to create a double spiral.

The major issue is that the adjacent PCBs tend to hide each other in large portions of space, due to the fact that they are aligned and closed to each other. We can also notice that the resulting shape is far from being symmetric (which is expected with a spiral).

Some arithmetics

In order to shake things up a little more, we can keep the idea of a constant angular offset, but with a twist.

Let us take a circle split in n angular positions. If you choose a starting point and then jump from position to positions by skipping k positions, you will reach all positions if, and only if, n and k are coprime. This gives us a more evenly spread disposition.

For the sake of convenience, and because it is a nice name, we shall name this configuration “modulo forest”.

Deadzones tend to be much more spread out, which seems more acceptable. Further investigation has to be done in order to choose a definitive shape.