I recently posted a few ideas about how to improve the framerate of an ambilight driven using the Adalight protocol. Before trying to implement some of those options, I thought it would be worthwhile to actually calculate the theoretical framerate limitations.

This post is part of a series on creating a DIY ambilight using Adalight and WS2812B LEDs. Check out the project page here.

## Assumptions and Goals

Before jumping into the math, I need to make one thing clear: these are the absolute, theoretical limits for the given data throughput settings only. I’m ignoring processing speed entirely from both ends and only focusing on the serial rate and the LED speed. The processing speed, combined with the inconsistency of the grab software and dropped frames due to the LED latching, means that you’ll likely never reach these limits in practice.

The monitor my ambilight is attached to runs at 60 hz, which makes my target framerate 60 frames per second (fps). Anything above 60 fps is considered excessive, because the ambilight will be repeating frames.

There is another advantage to higher baud rates, which is that even at the same framerate a higher data throughput (higher baud rate or fewer LEDs) will reduce the delay between frame generation and when the frame appears on the LEDs. In other words, the ambilight stays in “sync” with the monitor better at higher data rates.

My setup uses an Arduino Nano to drive 80 WS2812B LEDs using the Adalight protocol through Prismatik. At the moment it’s running at 115200 baud, the highest rate selectable in Prismatik.

## Function Graphs

A picture is worth a thousand words, so let’s start with the visual representations and then talk about the math behind them.

### Frame Limit vs. LED Number

This is a graph of the overall theoretical frame limit per second for WS2812B LEDs as a function of number of LEDs, shown at multiple baud rates.

Right away it should be clear how critical data throughput is to achieving an acceptable framerate.

At 9600 baud, an ambilight is nigh-unfeasible. A target framerate of 60, matching most common desktop monitors, is only possible if the number of LEDs is 3 or fewer. An “acceptable” framerate of 30 is only possible at 8 or fewer LEDs. By 30 LEDs the framerate is in the single digits.

Sextupling the baud rate to 57600 makes things much more reasonable. Hitting the target of 60 fps is theoretically possible for 27 or fewer LEDs, almost a 10-fold increase. As data throughput increases, that LED limit for 60 fps is continuously upped. At a baud rate of 921600, a framerate of 60 is theoretically possible at even 256 LEDs.

For my 80 LED setup, 230400 is the slowest standard baud rate that would allow me to achieve 60 frames per second (theoretical max: 76.47).

### Frame Limit vs. Baud Rate

For another perspective, here is a graph of the overall framerate limit at various baud rates for 20, 40, 60, 80, 100, and 120 LEDs.

This graph covers the range for all three baud rates available in Prismatik: 9600, 57600, and 115200. You can see that achieving 60 fps is only possible for small-numbered LED setups.

Expanding the graph for baud rates up to 1M paints a more optimistic picture:

You can see that LED lengths up to ~100 can theoretically reach 60 fps at a baud rate as low as 230400.

## Equations

Luckily for us, the equations to calculate these limits are all fairly simple (assuming I didn’t overlook anything in my calculations).

I apologize in advance if some of the notation is wonky. It’s been a long time since I’ve taken a proper math class. It’s also my first time writing anything in $\LaTeX$.

#### Combined Framerate Limit

Here is the total frame limit equation in its entirety:

$F_{Total} = {({10{(3N + 6)} \over {b}} + 0.00003N)}^{-1}$

Where:

• FTotal is the combined framerate limit from the serial connection and WS2812B latch time
• b is the baud rate
• N is the number of LEDs

I think it’s easier to think about when we break the equation into its components, so I’m going to talk about each one in turn.

#### SERIAL FRAME TIME

The first half of the equation is the serial frame time, or the amount of time it takes to send a single frame over serial.

$T_{Serial} = {10{(3N + 6)} \over {b}}$

The numerator ($10{(3N + 6)}$) is the amount of data required, in bits, per frame: 3 bytes per LED for the color data (1 each for Red, Green, and Blue) plus an additional 6 for the header (magic word “Ada” and a 3 byte checksum). This is multiplied by 10 to get the number of bits (baud) required for each byte (8 data bits + 1 start bit + 1 stop bit).

Dividing the baud required per frame by the baud rate (baud per second) gives us the frame time.

Solving the equation for my setup at 115200 baud and 80 LEDs gives us a frame time of 0.0214 seconds each, or 21.4 milliseconds each, for the serial data.

The reciprocal of this is the framerate limit for the serial connection:

$F_{Serial} = {{b} \over {10{(3N + 6)}}}$

With the same parameters, we would have a serial framerate limit of 46.8 frames per second.

While this is useful for thinking about the serial data, it doesn’t take into account the data time for the WS2812B LEDs.

#### LED Data Time

This is where the second half of the equation comes into play. After it successfully receives and parses the serial color data, the microcontroller disables interrupts in order to send the color data to the WS2812B LEDs.

$T_{LED} = {0.00003N}$

Each WS2812B LED takes approximately 30µs per LED for the color data transfer. Solving (0.00003 seconds * the number of LEDs) gives us the time, in seconds, that the microcontroller is sending the color data to the LEDs and cannot receive any new serial data.

Once again, for my setup of 80 WS2812B LEDs we can solve the equation:

$0.0024 s = {0.00003 s * 80}$

$2400{\mu}s = {30 {\mu}s * 80}$

Which gives us 2400 microseconds, which is 2.4 milliseconds or 0.0024 seconds of LED time per frame.

The reciprocal of this is the framerate limit for the LED data. That is to say – if we assume the serial data is always available instantaneously, what is the frame cap imposed by the time required to send the data to the LEDs?

$F_{LED} = {1 \over {0.00003N}}$

For my 80 LED setup, that is ${1 \over 0.0024}$416.7 frames per second,which is high enough not to cause any issues with the target framerate of 60.

#### Combined Frame Time

Adding the serial frame time of 0.0214 seconds and the led frame time of 0.0024 seconds gives us our combined frame time of 0.0238 seconds, or 23.8 milliseconds per frame. The reciprocal of this ($all^{-1}$ or ${1 \over all}$) is our combined framerate limit – the equation at the top.

For my 80 WS2812B LED setup at 115200 baud, our theoretical framerate limit is therefore 42 frames per second. Punching this equation into a spreadsheet allowed me to generate the graph above.

#### Equation in Plain Text

In case it’s useful to anyone, here is the equation in both LaTeX and plain text:

F_{Total} = {({10{(3N + 6)} \over {b}} + 0.00003N)}^{-1}
Ftotal = ((10 (3N + 6)) / b + 0.00003N)^-1

## Conclusion

Figuring-out the formula for these limits was quite fun, and it gives me some insight into how everything relates mathematically, not only conceptually. Hopefully it will also help others who are trying to plan their own Adalight system to see the framerate limits of their design.

In the next post, I’m going to expand on this by measuring the actual frame times and framerate produced by my own ambilight setup using a logic analyzer.