Brightness, Analog > Digital

One of the annoyances with my led clock has been that it is too bright during the evening. But, that can be easily solved by adding some kind of brightness control… This is the tale of that feature.

So, brightness control. There’s an awesome digital light sensor that can give you resolutions up to 16 bits and provides on chip lux conversion for getting numbers out of it that actually make sense (On high resolution you’ll get a number between 1 an 65535 lux) . It’s called a BH1750 and it is cheaply available everywhere. Connecting it over I2C is a breeze and there are lots of good libraries available for this chip, even for my Spark Core.

BH1750 Spark Core

Hooking it up to your Spark is a breeze and I wrote a small brightness controller with a running average trick in it to smoothen the transitions between different light readings. More on how that works later, first let me tell you this thing is simply not fast enough. As the main loop that makes sure there’s continuously fading between pixels (limited at 30 refreshes per second) even on low resolution the BH1750 needs 16ms for a measurement which gives a notable hick-up. Since you can’t do it async I decided to ditch the digital way and go for analog instead.

Photoresistor Spark Core

The Spark Core has 8 analog ports (A0 till A7), which give a 12bit accuracy when reading an analog value on it. This allows us to connect the photo-resistor with only a few components to the Spark Core and then reading it’s voltage gives a pretty good resolution and most important without any delays. Of course the numbers returned are not saying that much, so what I did in code was add a minimum and maximum threshold and minimum and maximum brightness of the LEDs so you can actually tweak how the brightness controller reacts to changes.

Mapping the numbers from the one range to the other is as simple as Y = (X – A) / (B – A) * (D – C) + C, where X is the number we get out of the reading, A is the minimum threshold, B the maximum threshold, C the minimum brightness and D the maximum brightness. Y of course is the outcome and before doing this you’ll need to check if X is below or above the thresholds since then you could directly write the minimum or maximum brightness, depending on X being above or below.


Moving Average

Getting back to the running average I’ve added, what it does is dampen the peaks or lows the circuit might give due to instability but also provide smooth fading between brightnesses (see graph above to illustrate this principle). This excellent tutorial on the Arduino website describes perfectly how to do it and gives you a nice library if you’d wish to integrate it into your own program. My own version of it is tailored to my specific needs (who needs floats anyway!).

Leave a Reply