Voting resources, early voting, and poll worker information - VOTE. ... Adafruit is open and shipping.
0

DotStar Ultra Bar Brightness and Color Control Issues
Moderators: adafruit_support_bill, adafruit

Please be positive and constructive with your questions and comments.

DotStar Ultra Bar Brightness and Color Control Issues

by carpdiem on Fri Sep 11, 2020 7:39 pm

I'm working with the DotStar Ultra Bar (https://www.adafruit.com/product/3776), and running into some weird issues around brightness and color control using the adafruit python dotstar library.

In particular, examining the datasheet for the AP102-2020 LEDs (linked from here: https://www.adafruit.com/product/3341) suggests that the "brightness" value has 5 bits of resolution (controlling current), and each color channel has 8 bits of resolution (controlling PWM). This indicates that, if, for example, we were only controlling a single color (say, the green channel), then we could achieve essentially 13-bits of visual brightness resolution, with some significant overlap (e.g., high PWM value with low brightness may appear identical to low PWM value with high brightness).

However, when trying to manually control the strip from python, I'm running into very strange behavior: for any given "brightness" setting, there are many values for the color intensity that do not change the LED's light state.

Here's example stub code I'm using:

Code: Select all | TOGGLE FULL SIZE
import board
import adafruit_dotstar as ds

def test_green(brightness, gr):
    # ok, technically, I'm using the number of LEDs = 256, since my test setup here has a pair of ultra bars connected in series
    # I've nevertheless left the number of LEDs below = 128 for ease of test with a single ultra bar
    dots = ds.DotStar(board.SCK, board.MOSI, 128, brightness = brightness)
    dots.fill((0, gr, 0))


Now, we can easily test a given brightness / green-value combination by simply calling test_green() with the appropriate values, so on to the observed behavior.

Brightness value does not function with 5 bits of resolution
If brightness value had 5 bits of resolution, and was confined in the range [0, 1), we would expect to see step functions in brightness around multiples of 1/32.

Fittingly, then, "test_green(1./32. + 0.001, 255)" is the first brightness value that turns on the LEDs.

We would then expect the next increment to happen at "test_green(2./32. + 0.001, 255)". It does not. In fact, we see brightness on the LEDs increase by as soon as "test_green(1./32. + 0.021, 255)", where, notably, 1./32 + 0.021 = 0.05225, which is less than 2./32. = 0.0625.

5-bit resolution would also imply that "test_green(1./32. + 0.001, 255)" should produce the same visual brightness as "test_green(2./32. - 0.001, 255)". It does not. The later function call produces noticeably brighter light from the LEDs than the former.


Color Intensity Values do not have a linear mapping, nor do they show 8-bits of resolution

Let's take a fixed brightness, say, 0.25, and ask a simple question: what's the smallest color intensity value that actually turns on the LEDs for this brightness setting?

In other words, if we call "test_green(0.25, x)", what's the smallest x we can set such that the LEDs light up.

Surprise! It's x = 32!

That is, if we call "test_green(0.25, 7)" we get no light. If we call "test_green(0.25, 13)", we get no light. No dice at all until we get to "test_green(0.25, 32)".

What if we take a different brightness value, say, 0.5? What's the smallest x that gives us light then?

It's x = 16!

Hrm... seems might suspicious, but let's follow it to its logical conclusion and find the smallest x value for brightness = 1.0...

Sure enough, "test_green(1.0, 8)" is the first time the LEDs turn on.

Ok, that's weird, right? But maybe something screwy is just happening where the LEDs are trading off resolution between their brightness and color intensities. Surely, at least for a given brightness, the LED output has a uniformly-spaced series of step functions?

Well, let's test this with brightness = 1.0. We already established that the minimum color intensity value to turn on the LEDs here is 8, so if output was at least linearly spaced, we would expect the next increment of light intensity to show up with a command color intensity value of 16, right?

Again, nope! In practice, we observe the second increment of light from the LEDs to occur at "test_green(1.0, 12)"! Following that, the third increment occurs at "test_green(1.0, 15)"!

If we repeat this test for a different brightness value, say, 0.5, we get the following results:
1st turn on => test_green(0.5, 16)
2nd light increment => test_green(0.5, 24)
3rd light increment => test_green(0.5, 30)

What in the world is going on?

Are the LEDs (or the adafruit_dotstar library) trying to apply some sort of internal gamma correction? If it's the adafruit_dotstar library, is there a way to use that library to control the LED strip without said gamma correction? Or is there something else entirely going on that I haven't yet guessed at? And in either case, how does that relate to the strange behavior observed with the non-5-bit resolution behavior of the brightness value itself? Is that also gamma corrected internally somewhere?

P.S. -
I've double checked all my wiring with a multimeter set to continuity test, and my grounds are correctly connected, and shared properly between the raspberry pi zero I'm using to control the strips, and the strips themselves.

carpdiem
 
Posts: 11
Joined: Wed Jan 30, 2019 5:30 am

Re: DotStar Ultra Bar Brightness and Color Control Issues

by adafruit_support_mike on Sat Sep 12, 2020 1:14 am

carpdiem wrote:Brightness value does not function with 5 bits of resolution

Strictly speaking they do, but the human eye can't see it.

The human eye responds to light logarithmically.. we see ratios of light intensity more than absolute quantities. That's how we can see both in starlight and noonday sun (the latter being about 100 million times more light than the former).

A 2:1 increase in absolute light quantity looks the same to us whether it's 1 photon to 2 (yes, we can see down that low) or 1 million to 2 million.. and in either case the visible change is toward the lower limit of what we can detect. You probably wouldn't be able to see any difference if you looked at one, looked away while the level changed, then looked back. You could probably see the change if it toggled back and forth at about 5Hz, but might not see it immediately.

That's why headlights that seem blinding at night are barely visible during the day. The absolute quantity of light they emit is the same in both cases, but the ratio of that light to the ambient light is very different.

To get what looks like a linear increase in brightness to the human eye, you need to make each increase a constant multiple of the current value.. 1, 2, 4, 8, 16, 32, and so on.

At that 2x multiple, the range from 1 to 32 would only give you 5 steps of apparent change in brightness. They'd look like a uniform gradient across 6 LEDs sitting side by side, but might look a bit jumpy if you used them to fade the brightness of a single LED.

Using a multipler of 1.26 would give you 15 steps from 1 to 32, and would look like a smooth fade in brightness. You won't be able to get most of those values with the integers between 1 and 32 though:

Code: Select all | TOGGLE FULL SIZE
 1 :  1.00
 2 :  1.26
 3 :  1.59
 4 :  2.00
 5 :  2.52
 6 :  3.18
 7 :  4.00
 8 :  5.04
 9 :  6.35
10 :  8.00
11 : 10.09
12 : 12.71
13 : 16.01
14 : 20.18
15 : 25.42
16 : 32.03
The 32-step exponential progression from 1 to 32 uses a multiplier of 1.12, and looks like this:

Code: Select all | TOGGLE FULL SIZE
 1 :  1.00
 2 :  1.12
 3 :  1.25
 4 :  1.40
 5 :  1.57
 6 :  1.76
 7 :  1.97
 8 :  2.21
 9 :  2.48
10 :  2.77
11 :  3.11
12 :  3.48
13 :  3.90
14 :  4.36
15 :  4.89
16 :  5.47
17 :  6.13
18 :  6.87
19 :  7.69
20 :  8.61
21 :  9.65
22 : 10.80
23 : 12.10
24 : 13.55
25 : 15.18
26 : 17.00
27 : 19.04
28 : 21.32
29 : 23.88
30 : 26.75
31 : 29.96
32 : 33.56

adafruit_support_mike
 
Posts: 61439
Joined: Thu Feb 11, 2010 2:51 pm

Re: DotStar Ultra Bar Brightness and Color Control Issues

by carpdiem on Sat Sep 12, 2020 3:01 am

Hrm... I'm not sure that this is addressing my points, so I'll try to clarify a different way.

On item 1 - "Brightness value does not function with 5 bits of resolution"

The adafruit dotstar python library includes a "brightness" argument as part of the __init__() for the DotStar class. You pass this value in, and it is applied globally to all of the color channels on the LEDs. The datasheets for the LEDs explain that this value corresponds to the amount of current commanded through the LEDs, on a scale with 32 increments (e.g., 5-bit resolution).

So the question here is, since the "brightness" argument in the DotStar __init__() is a float in the range of [0,1), what float values correspond to different commanded currents through the LEDs?

With 5 bits resolution, I would have expected the step-points to be at floating point values 1/32, 2/32, 3/32, etc, but they are not.

Are you saying that the step points are actually following an exponential spacing in the range of that argument between [0,1)? If so, how is that spacing determined?


On item #2 - Color intensity levels do not have a linear mapping, nor do they have 8-bits of resolution:

I'm not sure if you also meant to address my second issue with the same response in your post.

In case you did, this logarithmic description still seems like it's besides the point. I'm not claiming that I look away, change the light values, and then look back and it looks the same.

To be very specific, I can turn the light off, then type in the command, "test_green(1.0, 5)" for example, look back at the light, and only while looking at the light hit enter to actually send the command. In this case, the LEDs remain off for all values 0-7 for the commanded color intensity with global brightness=1.0. Then, following the same "looking at the LEDs during the change" procedure, I notice a very visible change when commanding "test_green(1.0, 8)". Namely, the LEDs actually turn on. It's not a small or subtle thing.

Since this color intensity is supposed to be (as per the LED datasheets) an 8-bit value controlling the PWM on the LEDs, I am very confused by this behavior. For true 8-bit resolution, I would expect some light at all from color intensity values in the range 1-7 (again, with global brightness=1.0). Instead, there is nothing for any of them, and then a sudden jump at 8.

Does this make sense? With this second issue, I'm not debating or running into questions of logarithmic sensitivity of the human eye with respect to different light levels (and I have a graduate study background in optical physics!), I'm running into the issue that, when commanded with, e.g., "test_green(1.0, 5)" as per the stub code I provided, the LEDs simply do not turn on. It is not small, it is not subtle, and I've double checked it in a completely dark room to make sure there wasn't even the faintest bit of light coming from them.


Maybe there's something wrong with my understanding, and in the adafruit dotstar library, the brightness argument is not actually meant to be a float in the range of [0,1]? Or maybe the color intensities are not actually meant to be in the range [0,255]? Or is there something else going on?

carpdiem
 
Posts: 11
Joined: Wed Jan 30, 2019 5:30 am

Re: DotStar Ultra Bar Brightness and Color Control Issues

by carpdiem on Sat Sep 12, 2020 7:08 pm

I've now gone a level deeper than this, and reproduced the observed behavior by just commanding raw bytes out the raspberry pi's SPI device from the command line in accordance with the LED datasheet linked from the adafruit product page for the APA102-2020 dotstar LEDs (http://www.led-color.com/upload/201604/ ... %20LED.pdf).

For example, sending

Code: Select all | TOGGLE FULL SIZE
echo -ne "\x00\x00\x00\x00\xff\x00\x08\x00" > /dev/spidev0.0

(corresponding to a full 31/31 max global brightness, and a color intensity of 8/255 on the green channel for the first LED)

Causes the first dotstar LED on the bar to turn on to a dim green color.

However, sending

Code: Select all | TOGGLE FULL SIZE
echo -ne "\x00\x00\x00\x00\xff\x00\x07\x00" > /dev/spidev0.0

(corresponding to a full 31/31 max global brightness, and a color intensity of 7/255 on the green channel for the first LED)

Fails to produce any light at all.

I'm trying to do fairly detailed color mixing of the various RGB channels here, so this is a real issue for me. How do you actually get even 8-bit (255 discrete levels) resolution on any given color channel?

carpdiem
 
Posts: 11
Joined: Wed Jan 30, 2019 5:30 am

Re: DotStar Ultra Bar Brightness and Color Control Issues

by adafruit_support_carter on Mon Sep 21, 2020 5:41 pm

Code: Select all | TOGGLE FULL SIZE
def test_green(brightness, gr):
    # ok, technically, I'm using the number of LEDs = 256, since my test setup here has a pair of ultra bars connected in series
    # I've nevertheless left the number of LEDs below = 128 for ease of test with a single ultra bar
    dots = ds.DotStar(board.SCK, board.MOSI, 128, brightness = brightness)
    dots.fill((0, gr, 0))

You're recreating a DotStar instance each time you call this function.

Try recreating the behavior via REPL.

adafruit_support_carter
 
Posts: 17112
Joined: Tue Nov 29, 2016 2:45 pm

Re: DotStar Ultra Bar Brightness and Color Control Issues

by carpdiem on Mon Sep 21, 2020 9:55 pm

adafruit_support_carter wrote:
Code: Select all | TOGGLE FULL SIZE
def test_green(brightness, gr):
    # ok, technically, I'm using the number of LEDs = 256, since my test setup here has a pair of ultra bars connected in series
    # I've nevertheless left the number of LEDs below = 128 for ease of test with a single ultra bar
    dots = ds.DotStar(board.SCK, board.MOSI, 128, brightness = brightness)
    dots.fill((0, gr, 0))

You're recreating a DotStar instance each time you call this function.

Try recreating the behavior via REPL.


Thanks for the reply here.

I've actually already recreated the behavior both within a REPL environment, using the adafruit_dotstar library, and using the spidev library sending raw bytes.

I've also recreated the behavior directly from the command line, writing raw bytes to the SPI device, as described in post #4 of this thread, directly prior to your response.

With that in mind, any other ideas and/or ability to confirm correct / incorrect behavior on your end?

I believe the simplest test would be to simply try to command a dotstar ultra bar to full brightness and, e.g., (0, 7, 0) color. Contrary to the datasheets on adafruit.com, this does not emit any light in my setup. Does it work if you try it?

carpdiem
 
Posts: 11
Joined: Wed Jan 30, 2019 5:30 am

Re: DotStar Ultra Bar Brightness and Color Control Issues

by adafruit_support_carter on Tue Sep 22, 2020 12:43 pm

I just did a quick test with a Trinket M0, which has a DotStar builtin. Here's what I did via REPL:
Code: Select all | TOGGLE FULL SIZE
Adafruit CircuitPython 5.3.1 on 2020-07-13; Adafruit Trinket M0 with samd21e18
>>> import board
>>> import adafruit_dotstar
>>> ds = adafruit_dotstar.DotStar(board.APA102_SCK, board.APA102_MOSI, 1)
>>> ds.brightness = 1.0
>>> ds.fill((0,7,0))
>>>

I get a green DotStar. This also works:
Code: Select all | TOGGLE FULL SIZE
>>> ds.fill((0,1,0))

adafruit_support_carter
 
Posts: 17112
Joined: Tue Nov 29, 2016 2:45 pm

Re: DotStar Ultra Bar Brightness and Color Control Issues

by carpdiem on Tue Sep 22, 2020 4:14 pm

adafruit_support_carter wrote:I just did a quick test with a Trinket M0, which has a DotStar builtin. Here's what I did via REPL:
Code: Select all | TOGGLE FULL SIZE
Adafruit CircuitPython 5.3.1 on 2020-07-13; Adafruit Trinket M0 with samd21e18
>>> import board
>>> import adafruit_dotstar
>>> ds = adafruit_dotstar.DotStar(board.APA102_SCK, board.APA102_MOSI, 1)
>>> ds.brightness = 1.0
>>> ds.fill((0,7,0))
>>>

I get a green DotStar. This also works:
Code: Select all | TOGGLE FULL SIZE
>>> ds.fill((0,1,0))


Great to know! And that's a 2020-sized dotstar, right? Were you able to try it with one of the dotstar ultra boards? I've got a 5V arduino shipping to me that I'll try on my setup, just to vary the hardware, and will let you know how it behaves.

carpdiem
 
Posts: 11
Joined: Wed Jan 30, 2019 5:30 am

Re: DotStar Ultra Bar Brightness and Color Control Issues

by adafruit_support_carter on Tue Sep 22, 2020 4:23 pm

Yes, it's the 2020 size DotStar.

What board are you running CircuitPython on?

adafruit_support_carter
 
Posts: 17112
Joined: Tue Nov 29, 2016 2:45 pm

Re: DotStar Ultra Bar Brightness and Color Control Issues

by carpdiem on Tue Sep 22, 2020 5:50 pm

I'm using a raspberry pi zero, controlling the ultra bar via the MOSI && CLK pins, and using the 74AHCT125 - Quad Level-Shifter (3V to 5V) (https://www.adafruit.com/product/1787) to get up to 5V logic for the SPI.

The really weird thing is that I'm not just seeing this behavior with circuitpython!

In fact, I see identical behavior (e.g., no light at brightness = 1.0 and color = (0, 7, 0)) even if i write raw bytes out the spi as per the APA102-2020 datasheet using the python spidev library (even trying different clock rates!).

Weirder than that, is that even if I remove python from the loop entirely by writing raw bytes to the SPI device from the command line (see post #4 in this thread), I still see the same behavior!

The whole setup is powered in common by the adafruit 5V 10A power supply, and I've double-checked that my grounds are good and shared with a multimeter set for continuity testing.

carpdiem
 
Posts: 11
Joined: Wed Jan 30, 2019 5:30 am

Re: DotStar Ultra Bar Brightness and Color Control Issues

by carpdiem on Sat Sep 26, 2020 6:55 pm

I've now reproduced this issue with entirely different hardware: an arduino nano every, and sending raw bytes out the SPI as per the APA102-2020 datasheet:

Code: Select all | TOGGLE FULL SIZE
#include <SPI.h>

void setup() {
  SPI.beginTransaction(SPISettings(1000000, MSBFIRST, SPI_MODE0));
  SPI.begin();
  SPI.transfer(0x00);
  SPI.transfer(0x00);
  SPI.transfer(0x00);
  SPI.transfer(0x00);
  for (int i = 0; i < 128; i++) {
    SPI.transfer(0xE0);
    SPI.transfer(0x00);
    SPI.transfer(0x00);
    SPI.transfer(0x00);
  }
  SPI.transfer(0x00);
  SPI.transfer(0x00);
  SPI.transfer(0x00);
  SPI.transfer(0x00);
}

void loop() {
  SPI.transfer(0x00);
  SPI.transfer(0x00);
  SPI.transfer(0x00);
  SPI.transfer(0x00);

  SPI.transfer(0xFF);
  SPI.transfer(0x00);
  SPI.transfer(0x07);
  SPI.transfer(0x00);
  delay(1000);
 
  SPI.transfer(0x00);
  SPI.transfer(0x00);
  SPI.transfer(0x00);
  SPI.transfer(0x00);

  SPI.transfer(0xFF);
  SPI.transfer(0x00);
  SPI.transfer(0x08);
  SPI.transfer(0x00);
  delay(1000);
}


Here, the setup() is initializing the strip to all-OFF, and the loop() cycles between full brightness and color = (0, 7, 0) and full brightness and color = (0, 8, 0) on the first LED.

This causes the LED to clearly blink on and off, one second each, with a dim, green color.

This seems to be contrary to the datasheet that suggests that color = (0, 7, 0) at full brightness should still result in light being produced.

Have you had the chance to try to test this on your end using one of the actual dotstar ultra bars? Perhaps the LEDs on the ultra bars are not actually APA102-2020 devices as advertised!

carpdiem
 
Posts: 11
Joined: Wed Jan 30, 2019 5:30 am

Re: DotStar Ultra Bar Brightness and Color Control Issues

by carpdiem on Thu Oct 08, 2020 4:41 pm

Hi!

Just an update, but I've now verified the integrity of my SPI data being sent to the dotstar ultra bar with an oscilloscope.

LED data frame commanding full brightness and color = (0, 7, 0), which results in no light - https://www.dropbox.com/s/n18nkgajho12a ... 5.jpg?dl=0

LED data frame commanding full brightness and color = (0, 8, 0), which results in light - https://www.dropbox.com/s/ycx9d4r3ukz0k ... 7.jpg?dl=0

Have you had the chance to attempt to replicate this on one of your dotstar ultra bars in house yet?

carpdiem
 
Posts: 11
Joined: Wed Jan 30, 2019 5:30 am

Re: DotStar Ultra Bar Brightness and Color Control Issues

by adafruit_support_carter on Thu Oct 08, 2020 5:21 pm

Have you had the chance to attempt to replicate this on one of your dotstar ultra bars in house yet?

Not yet. We will respond here when we do.

adafruit_support_carter
 
Posts: 17112
Joined: Tue Nov 29, 2016 2:45 pm

Re: DotStar Ultra Bar Brightness and Color Control Issues

by carpdiem on Thu Oct 08, 2020 5:35 pm

adafruit_support_carter wrote:
Have you had the chance to attempt to replicate this on one of your dotstar ultra bars in house yet?

Not yet. We will respond here when we do.


Thanks for the reply!

Just so I have some kind of idea what to expect, do you have any estimate how long it might take to attempt to replicate this? It's been a total blocker on my project for nearly a month now. :(

carpdiem
 
Posts: 11
Joined: Wed Jan 30, 2019 5:30 am

Re: DotStar Ultra Bar Brightness and Color Control Issues

by carpdiem on Mon Oct 19, 2020 5:02 pm

Hi guys, I wanted to provide an update on this.

Since my last post, I've purchased a different APA102-2020 dotstar device via adafruit, namely the high density 8x8 grid (https://www.adafruit.com/product/3444).

On this product, connected to and running the exact same python code with the adafruit dotstar libraries, and using my exact same raspberry pi zero w/ level shifter and capacitor setup, I get correct behavior.

That is, brightness = 1.0, and color = (0, 7, 0) results in a dim, green light. (for that matter, color = (0, 1, 0) also makes it light up!)

However, on the exact same HW/SW setup, when I instead plug in the dotstar ultra bar, I again get no light until color = (0, 8, 0).

I've now done literally everything I can possibly think to do here, namely, I have:

- Reproduced the problem with the dotstar ultra bars using multiple different HW && SW control setups.
- Reproduced the problem with the dotstar ultra bars using two different dotstar ultra bars on my side.
- Verified the integrity of my SPI commands via oscilloscope.
- Produced the correct behavior using a different APA102-2020 dotstar device from adafruit (namely, the 8x8 high density grid), and using the exact same HW && SW as produced the error using the dotstar ultra bars.

At this point, the evidence seems very strong that this is an issue inherent in the dotstar ultra bars. Perhaps the manufacturer is not actually using APA102-2020 LEDs?

Any idea what the ETA might be for attempting to reproduce this on your end? I'd love to know if I'm going crazy here or not. This is currently a total blocker on my project.

carpdiem
 
Posts: 11
Joined: Wed Jan 30, 2019 5:30 am

Please be positive and constructive with your questions and comments.