AS7343 tinkering

I just got one of the new AS7343 14-Channel Multi-Spectral Sensor Breakouts.
AS7343 14-Channel Multi-Spectral Sensor Breakout (pimoroni.com)

I have it connected to my Pico W Explorer running a modified version of the Tufty demo py file.

AS7343

I looked up the RGB values for the nm values for each channel and edited the file to match them up.

From the data sheet:                     R,G,B
F1:  396...415  405 nm violet        (130, 0, 200)
F2:  415...435  425 nm blue          (84, 0, 255) 
FZ:  440...460  450 nm light blue    (0, 70, 255)
F3:  465...485  475 nm turqois        (0, 192, 255)
F4:  505...525  515 nm light green    (31, 255, 0)
FY:  545...565  555 nm pail green     (179, 255, 0)
F5:  540...560  550 nm pail green     (163, 255, 0)
FXL: 590...610  600 nm orange         (255, 190, 0
F6:  630...650  640 nm red            (255, 33, 0)
F7:  680...700  690 nm red            (255, 0, 0)
F8:  735...756  745 nm dark red       (171, 0, 0)
NIR: 645...865  855 nm near ir         (97, 0, 0)

Blue	400...450 nm
Indigo	450...490 nm
Cyan	490...530 nm
Green	530...570 nm
Yellow	570...600 nm
Orange	600...630 nm
Red	    630...700 nm

One issue is the order that they are placed in the demo file isnā€™t ideal. Not as far as wavelength goes.

ā€œFZ: {0}, FY: {1}, FXL: {2}, NIR: {3}, F2: {4}, F3: {5}, F4: {6}, F6: {7}, F1: {8}, F5: {9}, F7: {10}, F8: {11}ā€.format(*reading)

Ideally Iā€™d prefer
F1, F2, FZ, F3, F4, FY, F5, FXL, F6, F7, F8, NIR

Going to be a bit of work to achieve that though.

from breakout_as7343 import BreakoutAS7343
from pimoroni_i2c import PimoroniI2C

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

i2c = PimoroniI2C(sda=20, scl=21)
as7343 = BreakoutAS7343(i2c)

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, rotate=270)
display.set_font("bitmap8")
display.set_backlight(0.5)


WIDTH, HEIGHT = display.get_bounds()

BLACK = display.create_pen(0, 0, 0)

FZ = display.create_pen(0, 70, 255)
FY = display.create_pen(179, 255, 0)
FXL = display.create_pen(255, 190, 0)
NIR = display.create_pen(97, 0, 0)
F2 = display.create_pen(84, 0, 255)
F3 = display.create_pen(0, 192, 255)
F4 = display.create_pen(31, 255, 0)
F6 = display.create_pen(255, 33, 0)
F1 = display.create_pen(130, 0, 200)
F5 = display.create_pen(163, 255, 0)
F7 = display.create_pen(255, 0, 0)
F8 = display.create_pen(171, 0, 0)

WHITE = display.create_pen(255, 255, 255)



as7343.set_channels(18)
as7343.set_gain(1024)
as7343.set_measurement_time(33)  # Roughly 30fps at 16ms/measurement
as7343.set_integration_time(27800)

as7343.set_illumination_current(4)
as7343.set_illumination_led(False)


BAR_WIDTH = 18
BAR_SPACING = 4
MARGIN = display.measure_text("NIR") + 2
BAR_HEIGHT = WIDTH - MARGIN

OFFSET_LEFT = int((HEIGHT - ((BAR_WIDTH + BAR_SPACING) * 12)) / 2)

# Satrting max values for auto-ranging
# From figure 8 of the datasheet
MAX_VALUES = [
    2711,
    4684,
    5970,
    13226,
    2371,
    962,
    3926,
    4170,
    7760,
    1967,
    6774,
    1166
]

LABELS = [
    "FZ",
    "FY",
    "FXL",
    "NIR",
    "F2",
    "F3",
    "F4",
    "F6",
    "F1",
    "F5",
    "F7",
    "F8"
]


while True:
    display.set_pen(0)
    display.clear()
    readings = as7343.read()
    for i, reading in enumerate(readings):
        MAX_VALUES[i] = max(reading, MAX_VALUES[i])
        scaled = int(reading / MAX_VALUES[i] * BAR_HEIGHT)

        y = i * (BAR_WIDTH + BAR_SPACING)
        y += OFFSET_LEFT

        display.set_pen(i + 1)
        display.rectangle(MARGIN, y, scaled, BAR_WIDTH)

        display.set_pen(WHITE)
        display.text(LABELS[i], 0, y + 1)

    display.update()

Oh, I so want to reorder whatā€™s displayed on the LCD. Get the colors in groups etc.

F1, F2, FZ | F3 | F4, FY, F5, FXL | F6, F7, F8 | NIR
     Blue  Indigo      Yellow          Red   Very Dark Red 

Too many family related distractions to get near it tonight. IMHO, this is one awesome light sensor. All thatā€™s holding me back is my less than stellar Micro Python skills. The other side of the coin is I learn more each time I tinker with a new toy. And more often than not the price is right. IMHO anyway. =) I like giving credit where credit is due.

Oh, and if your wondering why you canā€™t find the Pico W Explorer on the shop page? Mine was a prototype for a new product. I was given it for testing.
Pimoroni sent me this prototype to tinker with. =) - Discussion - Pimoroni Buccaneers

1 Like

Iā€™ve got my AS7343 working on a pico explorer base - had to tweak the OFFSET to match the slightly different display, and also the button numbers 12-15, so I could turn the LED on and off with the buttons.
OFFSET_LEFT = int((HEIGHT - 80 - ((BAR_WIDTH + BAR_SPACING) * 12)) / 2)
I had to change a couple of the max values to stop F3 and F5 maxing out.

Strange thing is, if I try and run the code with the existing PicoExplorer display rather than the W one:
from picographics import PicoGraphics, DISPLAY_PICO_EXPLORER, PEN_P8
display = PicoGraphics(display=DISPLAY_PICO_EXPLORER, pen_type=PEN_P8)
The board hangs and wont display anything, even though it works with the standard demo code.
It seems that WIDTH, HEIGHT = display.get_bounds() doesnā€™t get the HEIGHT value, which should be 240 for the standard display.

Hi Alphanumeric
Iā€™ve implemented your desire to have the colours in the right order, by adding a ā€˜PLACEā€™ array to put the readings in the right place on the display.
Hereā€™s my code for the pico explorer base. Also uses the pico explorer base buttons and display size, and uses the A, X, and B buttons to set the LEDs ON, brighter, OFF.

from breakout_as7343 import BreakoutAS7343
from pimoroni_i2c import PimoroniI2C
from picographics import PicoGraphics, DISPLAY_PICO_W_EXPLORER, PEN_P4
from pimoroni import Button
import time

i2c = PimoroniI2C(sda=20, scl=21)
as7343 = BreakoutAS7343(i2c)

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

button_a = Button(12)
button_b = Button(13)
button_x = Button(14)
button_y = Button(15)

display = PicoGraphics(display=DISPLAY_PICO_W_EXPLORER, pen_type=PEN_P4, rotate=270)
display.set_font("bitmap8")
display.set_backlight(0.5)


WIDTH, HEIGHT = display.get_bounds()
#WIDTH = 240
#HEIGHT = 240
#the above call doesn't get this for the display_pico_explorer

print (WIDTH, HEIGHT)

BLACK = display.create_pen(0, 0, 0)

FZ = display.create_pen(0, 70, 255)
FY = display.create_pen(179, 255, 0)
FXL = display.create_pen(255, 190, 0)
NIR = display.create_pen(97, 0, 0)
F2 = display.create_pen(84, 0, 255)
F3 = display.create_pen(0, 192, 255)
F4 = display.create_pen(31, 255, 0)
F6 = display.create_pen(255, 33, 0)
F1 = display.create_pen(130, 0, 200)
F5 = display.create_pen(163, 255, 0)
F7 = display.create_pen(255, 0, 0)
F8 = display.create_pen(171, 0, 0)

WHITE = display.create_pen(255, 255, 255)



as7343.set_channels(18)
as7343.set_gain(1024)
as7343.set_measurement_time(33)  # Roughly 30fps at 16ms/measurement
as7343.set_integration_time(27800)


BAR_WIDTH = 16
BAR_SPACING = 4
MARGIN = display.measure_text("NIR") + 2
BAR_HEIGHT = WIDTH - MARGIN

OFFSET_LEFT = int((HEIGHT - 80 - ((BAR_WIDTH + BAR_SPACING) * 12)) / 2)

# Starting max values for auto-ranging
# From figure 8 of the datasheet
# F3 in pos 6 was 962 but gave overrange
# F5 in pos 10 was 1967 but also overrange
MAX_VALUES = [
    2711,
    4684,
    5970,
    13226,
    2371,
    5000,
    3926,
    4170,
    7760,
    5000,
    6774,
    1166
]

LABELS = [
    "FZ",
    "FY",
    "FXL",
    "NIR",
    "F2",
    "F3",
    "F4",
    "F6",
    "F1",
    "F5",
    "F7",
    "F8"
]

PLACE = [
    3,
    6,
    8,
    12,
    2,
    4,
    5,
    9,
    1,
    7,
    10,
    11
]


while True:
    display.set_pen(0)
    display.clear()
    readings = as7343.read()
    for i, reading in enumerate(readings):
        MAX_VALUES[i] = max(reading, MAX_VALUES[i])
        scaled = int(reading / MAX_VALUES[i] * BAR_HEIGHT)
#       y = i * (BAR_WIDTH + BAR_SPACING)
        y = PLACE[i] * (BAR_WIDTH + BAR_SPACING)
        y += OFFSET_LEFT

        display.set_pen(i + 1)
        display.rectangle(MARGIN, y, scaled, BAR_WIDTH)

        display.set_pen(WHITE)
        display.text(LABELS[i], 0, y + 1)

    display.update()
    if button_b.is_pressed:
        as7343.set_illumination_led(False)
    elif button_a.is_pressed:       
        as7343.set_illumination_current(4)
        as7343.set_illumination_led(True)
    elif button_x.is_pressed:
        as7343.set_illumination_current(10)
        as7343.set_illumination_led(True)
    time.sleep(0.01)

1 Like

I am so going to try that, maybe tonight even. getting supper ready at the moment. I will let you know how it turns out. Thankyou so much. =)

As ā€œmyā€ Pico W Explorer is a prototype, I have to also copy this custom pimoroni.py file to it. None of the Pico W Explorer examples will work without it. This might factor into issues your having? Iā€™ll be honest and say I have had a few Rum & Cokes, as pirates will. =) So I may have missed something in your post about the width height issue, that I normally wouldnā€™t.

import time
from machine import Pin, PWM, ADC


BREAKOUT_GARDEN_I2C_PINS = {"sda": 4, "scl": 5}
PICO_EXPLORER_I2C_PINS = {"sda": 20, "scl": 21}
HEADER_I2C_PINS = {"sda": 20, "scl": 21}

# Motor and encoder directions
NORMAL_DIR = 0x00
REVERSED_DIR = 0x01

BREAKOUT_GARDEN_SPI_SLOT_FRONT = 0
BREAKOUT_GARDEN_SPI_SLOT_BACK = 1
PICO_EXPLORER_SPI_ONBOARD = 2


class Analog:
    def __init__(self, pin, amplifier_gain=1, resistor=0, offset=0):
        self.gain = amplifier_gain
        self.resistor = resistor
        self.offset = offset
        self.pin = ADC(pin)

    def read_voltage(self):
        return max((((self.pin.read_u16() * 3.3) / 65535) + self.offset) / self.gain, 0.0)

    def read_current(self):
        if self.resistor > 0:
            return self.read_voltage() / self.resistor
        else:
            return self.read_voltage()


class AnalogMux:
    def __init__(self, addr0, addr1=None, addr2=None, en=None, muxed_pin=None):
        self.addr0_pin = Pin(addr0, Pin.OUT)
        self.addr1_pin = Pin(addr1, Pin.OUT) if addr1 is not None else None
        self.addr2_pin = Pin(addr2, Pin.OUT) if addr2 is not None else None
        self.en_pin = Pin(en, Pin.OUT) if en is not None else None
        self.max_address = 0b001
        if addr1 is not None:
            self.max_address = 0b011
            if addr2 is not None:
                self.max_address = 0b111
        self.pulls = [None] * (self.max_address + 1)
        self.muxed_pin = muxed_pin

    def select(self, address):
        if address < 0:
            raise ValueError("address is less than zero")
        elif address > self.max_address:
            raise ValueError("address is greater than number of available addresses")
        else:
            if self.muxed_pin and self.pulls[address] is None:
                self.muxed_pin.init(Pin.IN, None)

            self.addr0_pin.value(address & 0b001)

            if self.addr1_pin is not None:
                self.addr1_pin.value(address & 0b010)

            if self.addr2_pin is not None:
                self.addr2_pin.value(address & 0b100)

            if self.en_pin is not None:
                self.en_pin.value(1)

            if self.muxed_pin and self.pulls[address] is not None:
                self.muxed_pin.init(Pin.IN, self.pulls[address])

    def disable(self):
        if self.en_pin is not None:
            self.en_pin.value(0)
        else:
            raise RuntimeError("there is no enable pin assigned to this mux")

    def configure_pull(self, address, pull=None):
        if address < 0:
            raise ValueError("address is less than zero")
        elif address > self.max_address:
            raise ValueError("address is greater than number of available addresses")
        else:
            self.pulls[address] = pull

    def read(self):
        if self.muxed_pin is not None:
            return self.muxed_pin.value()
        else:
            raise RuntimeError("there is no muxed pin assigned to this mux")


class Button:
    def __init__(self, button, invert=True, repeat_time=200, hold_time=1000):
        self.invert = invert
        self.repeat_time = repeat_time
        self.hold_time = hold_time
        self.pin = Pin(button, pull=Pin.PULL_UP if invert else Pin.PULL_DOWN)
        self.last_state = False
        self.pressed = False
        self.pressed_time = 0

    def read(self):
        current_time = time.ticks_ms()
        state = self.raw()
        changed = state != self.last_state
        self.last_state = state

        if changed:
            if state:
                self.pressed_time = current_time
                self.pressed = True
                self.last_time = current_time
                return True
            else:
                self.pressed_time = 0
                self.pressed = False
                self.last_time = 0

        if self.repeat_time == 0:
            return False

        if self.pressed:
            repeat_rate = self.repeat_time
            if self.hold_time > 0 and current_time - self.pressed_time > self.hold_time:
                repeat_rate /= 3
            if current_time - self.last_time > repeat_rate:
                self.last_time = current_time
                return True

        return False

    def raw(self):
        if self.invert:
            return not self.pin.value()
        else:
            return self.pin.value()

    @property
    def is_pressed(self):
        return self.raw()


class RGBLED:
    def __init__(self, r, g, b, invert=True):
        self.invert = invert
        self.led_r = PWM(Pin(r))
        self.led_r.freq(1000)
        self.led_g = PWM(Pin(g))
        self.led_g.freq(1000)
        self.led_b = PWM(Pin(b))
        self.led_b.freq(1000)

    def set_rgb(self, r, g, b):
        if self.invert:
            r = 255 - r
            g = 255 - g
            b = 255 - b
        self.led_r.duty_u16(int((r * 65535) / 255))
        self.led_g.duty_u16(int((g * 65535) / 255))
        self.led_b.duty_u16(int((b * 65535) / 255))


# A simple class for handling Proportional, Integral & Derivative (PID) control calculations
class PID:
    def __init__(self, kp, ki, kd, sample_rate):
        self.kp = kp
        self.ki = ki
        self.kd = kd
        self.setpoint = 0
        self._error_sum = 0
        self._last_value = 0
        self._sample_rate = sample_rate

    def calculate(self, value, value_change=None):
        error = self.setpoint - value
        self._error_sum += error * self._sample_rate
        if value_change is None:
            rate_error = (value - self._last_value) / self._sample_rate
        else:
            rate_error = value_change
        self._last_value = value

        return (error * self.kp) + (self._error_sum * self.ki) - (rate_error * self.kd)


class Buzzer:
    def __init__(self, pin):
        self.pwm = PWM(Pin(pin))

    def set_tone(self, freq, duty=0.5):
        if freq < 50.0:  # uh... https://github.com/micropython/micropython/blob/af64c2ddbd758ab6bac0fcca94c66d89046663be/ports/rp2/machine_pwm.c#L105-L119
            self.pwm.duty_u16(0)
            return False

        self.pwm.freq(freq)
        self.pwm.duty_u16(int(65535 * duty))
        return True


class Speaker:
    def __init__(self, pin):
        self.pwm = PWM(Pin(pin))

    def set_tone(self, freq, volume=0.3):
        if freq < 50.0:  # uh... https://github.com/micropython/micropython/blob/af64c2ddbd758ab6bac0fcca94c66d89046663be/ports/rp2/machine_pwm.c#L105-L119
            self.pwm.duty_u16(0)
            return False

        self.pwm.freq(freq)
        corrected_volume = (volume ** 4)  # Correct for RC Filter curve
        self.pwm.duty_u16(int(32768 * corrected_volume))
        return True


class ShiftRegister:
    def __init__(self, clk, lat, dat):
        self.clk = Pin(clk, Pin.OUT)
        self.lat = Pin(lat, Pin.OUT)
        self.dat = Pin(dat, Pin.IN)

    def __iter__(self):
        self.lat.off()
        self.lat.on()
        for _ in range(8):
            yield self.dat.value()
            self.clk.on()
            self.clk.off()

    def __getitem__(self, k):
        return list(self)[k]

    def read(self):
        out = 0
        for bit in self:
            out <<= 1
            out += bit
        return out

    def is_set(self, mask):
        return self.read() & mask == mask


# A basic wrapper for PWM with regular on/off and toggle functions from Pin
# Intended to be used for driving LEDs with brightness control & compatibility with Pin
class PWMLED:
    def __init__(self, pin, invert=False):
        self._invert = invert
        self._led = PWM(Pin(pin, Pin.OUT))
        self._led.freq(1000)
        self._brightness = 0
        self.brightness(0)

    def brightness(self, brightness):
        brightness = min(1.0, max(0.0, brightness))
        self._brightness = brightness
        if self._invert:
            brightness = 1.0 - brightness
        self._led.duty_u16(int(65535 * brightness))

    def on(self):
        self.brightness(1)

    def off(self):
        self.brightness(0)

    def toggle(self):
        self.brightness(1 - self._brightness)


1 Like

Understood - Iā€™m on my second bottle of wine ;-)

Iā€™m struggling with the channels. Some are higher but saturate easily. Others like FXL and F7 and F4 seems to be low, but are either on or off.

Just noticed - I had to change OFFSET_LEFT to ā€¦HEIGHT - 110ā€¦ to get the NIR channel on the screen with my display.

I meant to post this last night but got sidetracked some how and forgot.

The file I started with is here, itā€™s written for the Tufty.
pimoroni-pico/micropython/examples/breakout_as7343/tufty_spectrometer.py at main Ā· pimoroni/pimoroni-pico (github.com)

I have a tufty, but its in use, so I went with my Pico W Explorer instead. They both have a 320x 240 display.

Thanks alphanumeric

That tufty code works fine on my Pico explorer, and I was able to change the display to DISPLAY_PICO_EXPLORER without it hanging up (after changing the SCL and SDA pins).
Iā€™ll study all the variations and try and understand the anomalies. Have a nice day.
Tony

1 Like

Yeah, the i2c pins moving around depending on what Pimoroni product it is has caught me out a few times. Had me scratching my head the first couple of times. Getting used to it now.
Screen rotation is another one. Where the LCD ribbon cable is situated, what side of the screen its on etc. Moving code from one device to another sometimes requires a rotate=.

Going to have a go at your new code tonight. Sometime after supper probably. What seems like endless distractions are getting in the way. Family stuff etc. Thatā€™s how it goes some times. :(

@tony1tf that worked a treat. Thankyou very much. =)
My camera doesnā€™t work so well when shooting Backlit Color LCDā€™s. As a result some of the colors are washed out a bit. Yellow looks really pail as an example.
Capture.PNG

1 Like

Well done. I used the ā€˜professionalā€™ photo setting on my Samsung phone, and reduced the exposure till the colours were good. Iā€™ve also been tweaking the RGB a bit to get better contrast between adjacent bars.
BTW - can you check if all your channels move in an analogue way - I have three that just jump between a low and a high value. I donā€™t know if I have a faulty sensor.
Tony

My father was a professional photographer. He always went fully manual. For me itā€™s got to be full auto. As far as taking pictures goes, we were polar opposites.

I havenā€™t noticed any channels on mine acting as you describe. I will keep an eye out for it though. I have plans to do some tinkering / testing with a battery powered setup. I can then take it outside untethered, at dusk, dawn, night, etc. Street lights might be an issue, weā€™ll see.
My Pico W Explorer does have a battery connector, so that simplifies that somewhat. Iā€™m really wanting to get my hands on one of the new Pico Display 2.8ā€™s. I almost need to hold what I have now two handed. It does look nice on my desk though.

Iā€™ve turned things on their side. =)
Iā€™ve replaced the F1 etc with the NM wavelength for that channel. And rotated the display so I can read the text. Also noticed I had two channels (FY and F5) in the wrong order, wavelength wise.
Itā€™s now F1, F2, FZ, F3, F4, F5, FY, FXL, F6, F7, F8, NIR

I turned the backlight down to 0.5 to get a good picture. ;)

1 Like

Hi alpha

Can you post your code please, so I donā€™t have to!
It looks very nice - unfortunately my Pico Explorer doesnā€™t have a backlight control, but I can alter the brightness of each band.

Tony

Ops, sorry about that, I had intended to do that? Must have slipped up some how and left it out of my post.
I have now setup my backlight so I can set it with a button press. My Pico W Explorer was a prototype that they sent me to play with. Likely now replaced by the new bigger better faster Pico 2 version.

import time 

from breakout_as7343 import BreakoutAS7343
from pimoroni_i2c import PimoroniI2C
from picographics import PicoGraphics, DISPLAY_PICO_W_EXPLORER, PEN_P4
from pimoroni import Button

i2c = PimoroniI2C(sda=20, scl=21)
as7343 = BreakoutAS7343(i2c)

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, rotate=0)
display.set_font("bitmap8")
display.set_backlight(1.0)


WIDTH, HEIGHT = display.get_bounds()

BLACK = display.create_pen(0, 0, 0)

FZ = display.create_pen(0, 70, 255)
FY = display.create_pen(179, 255, 0)
FXL = display.create_pen(255, 190, 0)
NIR = display.create_pen(97, 0, 0)
F2 = display.create_pen(84, 0, 255)
F3 = display.create_pen(0, 192, 255)
F4 = display.create_pen(31, 255, 0)
F6 = display.create_pen(255, 33, 0)
F1 = display.create_pen(130, 0, 200)
F5 = display.create_pen(163, 255, 0)
F7 = display.create_pen(255, 0, 0)
F8 = display.create_pen(171, 0, 0)

WHITE = display.create_pen(255, 255, 255)



as7343.set_channels(18)
as7343.set_gain(1024)
as7343.set_measurement_time(33)  # Roughly 30fps at 16ms/measurement
as7343.set_integration_time(27800)

as7343.set_illumination_current(4)
as7343.set_illumination_led(False)

BAR_WIDTH = 16
BAR_SPACING = 2
MARGIN = display.measure_text("NIR") + 2
BAR_HEIGHT = WIDTH - MARGIN

OFFSET_LEFT = int((HEIGHT - 40 - ((BAR_WIDTH + BAR_SPACING) * 12)) / 2)

# Satrting max values for auto-ranging
# From figure 8 of the datasheet
MAX_VALUES = [
    2711,
    4684,
    5970,
    13226,
    2371,
    962,
    3926,
    4170,
    7760,
    1967,
    6774,
    1166
]

LABELS = [
    "450",
    "555",
    "600",
    "855",
    "425",
    "475",
    "515",
    "640",
    "405",
    "550",
    "690",
    "745"
]

PLACE = [
    3,
    7,
    8,
    12,
    2,
    4,
    5,
    9,
    1,
    6,
    10,
    11
]


while True:
    
    if button_a.read():
        display.set_backlight(1.0)                                           # clear to black
    elif button_b.read():
        display.set_backlight(0.0)
    elif button_x.read():
        display.set_backlight(1.0)
    elif button_y.read():
        display.set_backlight(0.5)
    
    display.set_pen(0)
    display.clear()
    readings = as7343.read()
    for i, reading in enumerate(readings):
        MAX_VALUES[i] = max(reading, MAX_VALUES[i])
        scaled = int(reading / MAX_VALUES[i] * BAR_HEIGHT)

        y = PLACE[i] * (BAR_WIDTH + BAR_SPACING)
        y += OFFSET_LEFT

        display.set_pen(i + 1)
        display.rectangle(MARGIN, y, scaled, BAR_WIDTH)

        display.set_pen(WHITE)
        display.text(LABELS[i], 0, y + 1)
   
    display.update()
    
    

Iā€™ve resorted to using HSV instead of RGB to get a Global Brightness function on devices like the Interstate 75. V becomes the brightness variable. Itā€™s a bit of a PITA, but it works OK. You just have to go look up your colors.
Reinvented Color Wheel Picker Demo Page (cssscript.com)

Interstate 74 W, how do you control the display brightness? - Support - Pimoroni Buccaneers

I have set the max limit of 515, 600 and 690 to 1000 to get a higher reading. However, as I suggested earlier, they donā€™t move with more illumination. I need to check with Pimoroni to see if this means that the sensor is faulty. Two photos attached - low and high illumination.



Tony