Want to use a BH1745 for Ambient Lighting

I have a BH1745 connected to a Pico W Explorer, displaying it’s readings on the explorers LCD. I also using the Clamped RGB values to light up the LED Ring on an Encoder Wheel.


Sorry about the picture, probably should have turned the LCD Backlight down?

I couldn’t find any info on what the clamped values are? It looks like what ever the highest value is R G or B, that gets clamped to 255, and then the others are adjusted accordingly.
Raw: 451, 849, 896, 1560
Clamped: 128, 241, 255, 1560
Scaled: #4b8b93
Raw: 19, 15, 5, 140
Clamped: 255, 240, 45, 140
Scaled: #1b1d05
Raw: 15, 3, 0, 120
Clamped: 255, 51, 0, 120
Scaled: #280600

That gets me my color on the LER Ring, but at or near full brightness.

import time
import machine
import micropython
import pimoroni_i2c
import breakout_bh1745

PINS_BREAKOUT_GARDEN = {"sda": 4, "scl": 5}
PINS_PICO_EXPLORER = {"sda": 20, "scl": 21}

I2C = pimoroni_i2c.PimoroniI2C(**PINS_PICO_EXPLORER)
bh1745 = breakout_bh1745.BreakoutBH1745(I2C)

bh1745.leds(False)

from picographics import PicoGraphics, DISPLAY_PICO_W_EXPLORER, PEN_P4
from pimoroni import Button
from breakout_encoder_wheel import BreakoutEncoderWheel, UP, DOWN, LEFT, RIGHT, CENTRE, NUM_BUTTONS, NUM_LEDS


wheel = BreakoutEncoderWheel(I2C)
BUTTON_NAMES = ["Up", "Down", "Left", "Right", "Centre"]
last_pressed = [False] * NUM_BUTTONS
pressed = [False] * NUM_BUTTONS
wheel.clear()

button_a = Button(6)
button_b = Button(7)
button_x = Button(10)
button_y = Button(11)

display = PicoGraphics(display=DISPLAY_PICO_W_EXPLORER, pen_type=PEN_P4)
display.set_font("bitmap8")

WHITE = display.create_pen(255, 255, 255)
BLACK = display.create_pen(0, 0, 0)
CYAN = display.create_pen(0, 255, 255)
MAGENTA = display.create_pen(255, 0, 255)
YELLOW = display.create_pen(255, 255, 0)
GREEN = display.create_pen(0, 255, 0)

while True:
    rgbc_raw = bh1745.rgbc_raw()
    rgb_clamped = bh1745.rgbc_clamped()
    rgb_scaled = bh1745.rgbc_scaled()
    print("Raw: {}, {}, {}, {}".format(*rgbc_raw))
    print("Clamped: {}, {}, {}, {}".format(*rgb_clamped))
    print("Scaled: #{:02x}{:02x}{:02x}".format(*rgb_scaled))
    
    display.set_pen(BLACK)
    display.clear()
    display.set_pen(WHITE)
    display.text("Raw: (R, G, B)", 0, 20, scale = 3)
    #display.text("{}, {}, {}, {}".format(*rgbl_raw), 0, 50, scale = 3)
    display.text("({}, {}, {})".format(*rgbc_raw), 0, 50, scale = 3)
    display.text("Clamped: (R, G, B)", 0, 110, scale = 3)
    display.text("({}, {}, {})".format(*rgb_clamped), 0, 140, scale = 3)
    #display.text("Scaled: {:02x} {:02x} {:02x}".format(*rgb_scaled), 0, 210, scale = 3)
    
    
    (R, G, B, L) = bh1745.rgbc_clamped()
    display.text("Luminance {:0.0f}".format(L), 0, 210, scale = 3)    
    #print (L)
    wheel.clear()
    for i in range(NUM_LEDS):
        wheel.set_rgb(i, R, G, B)    
    
    display.update()
    wheel.show()
    
    time.sleep(5.0)

It looks like I’ll have to do some math on the Clamped RGB based on the Luminance / LUX reading. RGB to HSV and use the LUX for V, then do a HSV to RGB?
I have no idea what the Scaled values are?

Looking for suggestions?

Hi Alpha,

The BH1745 “clamped” values as you correctly surmise are on the scale of 0 to 255. So are approximated (or clamped) to fit on that scale. The win there is that the values are standardised and will not exceed the maximum. However may not be super accurate as a result.

In the world of RGB which I’ve no doubt you’re familiar with 255, 255, 255 with give a white colour. 255, 0, 0 will be red, 0, 255, 0 for green 0, 0, 255 for blue and so on.

The scaled (hex) readings are a bit more flexible giving a HTML standard colour value via fstring formatting But are ultimately the same thing expressed differently.

Looking at your example not sure you’d need HSV conversion. Though maybe easier to work with with some smart lighting.

It should be noted for nothing more than clarity that the clamped and scaled output doesn’t account for luminance.

The BH1745 raw readings are given in μW/cm² as opposed to Lux for luminance. Hence the higher values than the LTR559 may read in comparison.

In broad summer daylight for example, I’ve taken a luminance reading in the 230,490 μW/cm² range. Around midday when the sun is at it’s apex.

There are online convertors around. But you’d have to scale up μW to whole Watts before hand.

Hope this might help a bit with your project.

After thought edit. I’ve learnt a new thing! Thank you, aIpha. I wasn’t aware that the pico BH1745 clamped values for luminance were accessable. It’s a fair assumption to make, I think, that they will also be clamped to 0-255. A person with more smarts than myself may be able to clairfy further.

Right now the above is just a test setup. Something to tinker with. If get what I want code wise, I’ll then port it over to work on my Plasma Stick desktop lighting setup. That’s the plan anyway.
Right now for example, a Raw (1, 0, 0) gets a clamped (255, 0, 0).

The Clamped luminance (clear channel) isn’t clamped at 255, The Raw and Clamped for that value always matched when I ran the demo file.
Raw: 451, 849, 896, 1560
Clamped: 128, 241, 255, 1560
Scaled: #4b8b93
It’s what is shown for Luminance on the LCD. I probably should call it something else. According to the data sheet its RGBC, Red Green Blue Clear. Unfiltered I guess?
I may be able to adapt some auto brightness code I have that works with the LTR-559. That’s what got me thinking HSV. There is no global brightness function on the Plasma Stick, or the Encoder Wheel. I’m already using the Wheel to adjust the brightness (v).

I’m also playing around with the new AS7343. I’ll try and post that tomorrow in a new thread. I have something tricky I want to do on that setup too.

Okay, that’s interesting. Goes to show a new thing can be learned each day, and I should wear my glasses more often!

So the colour values are clamped, but the luminance is not. As demonstrated. I’ve always understood the “clear” to be transparent, without colour. But here, for my use case, I only use the raw readings for it.

My after thought was not correct. The “C” channel is indeed expressed in μW/cm² (as per the data sheet) so perhaps the conversion might be a good place to start. I’ve got no suggestions on how to bring the clear channel output into a regex format though, accurately.

If anyone can get that AS7343 doing interesting things it would be you! Might pick on up in the future. No real use for one at the moment.

Also just noticed a double “with” in my reply. I’ll now spend the rest of the day hiding from the grammar pendants. 😉

I had a look at the C-source code of Pimoroni’s driver. What they call “clamping” is actually scaling by max(r,g,b). What they call “scaling” is scaling by c followed by clamping to 255. In addition, they always scale (r,g,b,c) by (2,1,1.8,10) before they “clamp” or “scale”.

This is why I like Pimoroni as a hardware-shop, but not as a software shop. They add too much magic sauce (or as I would call it: voodoo) into their drivers which might or might not be correct. In this case I would just call it strange. Especially the initial scaling levels out the spectral response as a whole.

@alphanumeric: if you want your LEDs to show the RGB value, you should also use gamma-correction. This is because the response of the LEDs is not linear.

2 Likes