Plasma Stick 2040 W - LED brightness contol

Looking at the default main.py which runs cheerlights.

led_strip.set_rgb(i, r, g, b)

How do I adjust brightness in there?

Thank you.

Have you tried this command? (I don’t have this board, just followed the example links from the product page).

Good spot, tried that and got

AttributeError: 'plasma_ws2812' object has no attribute 'set_brightness'

Could you put your full code here? I wonder if you are calling that method on the wrong object.

Sure, full code is


import WIFI_CONFIG
from network_manager import NetworkManager
import uasyncio
import urequests
import time
import plasma
from plasma import plasma_stick
from machine import Pin

import network   # handles connecting to WiFi

'''
This Plasma Stick example sets your LED strip to the current #cheerlights colour.
Find out more about the Cheerlights API at https://cheerlights.com/
'''

URL = 'http://api.thingspeak.com/channels/1417/field/2/last.json'
UPDATE_INTERVAL = 120  # refresh interval in secs. Be nice to free APIs!

# Set how many LEDs you have
NUM_LEDS = 50


def status_handler(mode, status, ip):
    # reports wifi connection status
    print(mode, status, ip)
    print('Connecting to wifi...')
    # flash while connecting
    for i in range(NUM_LEDS):
        led_strip.set_rgb(i, 255, 255, 255)
        time.sleep(0.02)
    for i in range(NUM_LEDS):
        led_strip.set_rgb(i, 0, 0, 0)
    if status is not None:
        if status:
            print('Wifi connection successful!')
        else:
            print('Wifi connection failed!')
            # if no wifi connection, you get spooky rainbows. Bwahahaha!
            spooky_rainbows()


def spooky_rainbows():
    print('SPOOKY RAINBOWS!')
    HUE_START = 30  # orange
    HUE_END = 140  # green
    SPEED = 0.3  # bigger = faster (harder, stronger)

    distance = 0.0
    direction = SPEED
    while True:
        for i in range(NUM_LEDS):
            # generate a triangle wave that moves up and down the LEDs
            j = max(0, 1 - abs(distance - i) / (NUM_LEDS / 3))
            hue = HUE_START + j * (HUE_END - HUE_START)

            led_strip.set_hsv(i, hue / 360, 1.0, 0.3)

        # reverse direction at the end of colour segment to avoid an abrupt change
        distance += direction
        if distance > NUM_LEDS:
            direction = - SPEED
        if distance < 0:
            direction = SPEED

        time.sleep(0.01)


def hex_to_rgb(hex):
    # converts a hex colour code into RGB
    h = hex.lstrip('#')
    r, g, b = (int(h[i:i + 2], 16) for i in (0, 2, 4))
    return r, g, b




# set up the Pico W's onboard LED
pico_led = Pin('LED', Pin.OUT)

# set up the WS2812 / NeoPixel™ LEDs
led_strip = plasma.WS2812(NUM_LEDS, 0, 0, plasma_stick.DAT, color_order=plasma.COLOR_ORDER_RGB)


# led_strip.set_brightness(4)


# start updating the LED strip
led_strip.start()

# set up wifi
try:
    network_manager = NetworkManager(WIFI_CONFIG.COUNTRY, status_handler=status_handler)
    uasyncio.get_event_loop().run_until_complete(network_manager.client(WIFI_CONFIG.SSID, WIFI_CONFIG.PSK))
    
       
except Exception as e:
    print(f'Wifi connection failed! {e}')
    # if no wifi, then you get...
    spooky_rainbows()

while True:
    # open the json file
    print(f'Requesting URL: {URL}')
    r = urequests.get(URL)
    # open the json data
    j = r.json()
    print('Data obtained!')
    r.close()

    # flash the onboard LED after getting data
    pico_led.value(True)
    time.sleep(0.2)
    pico_led.value(False)

    # extract hex colour from the data
    hex = j['field2']

    # and convert it to RGB
    r, g, b = hex_to_rgb(hex)

    # light up the LEDs
    for i in range(NUM_LEDS):
        led_strip.set_rgb(i, r, g, b)
    print(f'LEDs set to {hex}')

    # sleep
    print(f'Sleeping for {UPDATE_INTERVAL} seconds.')
    time.sleep(UPDATE_INTERVAL)


1 Like

Aha, I spotted this in the docs:

APA102 pixels support global brightness

That would imply (to me) that the WS2812 does not support global brightness, and it’s the WS2812 you are using.

It’s not quite the same, but perhaps you could change your RGB values per pixel by a floating point multiplier between 0.0 and 1.0. A value of 1.0 would be full brightness, and 0.0 would be black (off).

So for example white (0xffffff) would come out as grey (0xcacaca).

Way above my skillset, but thank you for the suggestion.

As a very basic example, try this:

# light up the LEDs
multiplier = 0.75
for i in range(NUM_LEDS):
    led_strip.set_rgb(i, r * multiplier, g * multiplier, b * multiplier)

This basically changes what the colours would have been, and makes them 25% more black.

FWIW, I am applying two RGB principles here:

  • darker colours move all three values towards 0, and lighter colours move all three values towards 255
  • if you multiply one colour channel independently then you’ll modify the hue, but if you modify them together, then it is like making them lighter or darker

Give it a try? 🏅

I am assuming the RGB ranges in the set_rgb() method are 0-255, but the above should still work if the top value is something else, like 100.

I’m also expecting the setter method to be OK with fractional values, but if it complains, I expect we can find a rounding function 👍

I’ll certainly give this a try just as soon as time permits, but hopefully over this long weekend. Thank you.

1 Like

Finally found five mins to have a look at this.

led_strip.set_rgb(i, r * multiplier, g * multiplier, b * multiplier)

Invalid syntax on that line.

it may not accept floating point values… for safety you may either need to ensure you use multiple of 4 for the RGB inputs, or use the math.floor(), math.ceil(), trunc(), or int() functions to force them to integers

2 Likes

I was trying to figure this out as well, I thought brighness would work but I think you’d need to change from r, g, b values to HSV so we can use V to set the brigness and use led_strip.set_hsv instead of led_strip.set_rgb if you look at alternating-blinkies.py you can see where this is used.

How to do that? I have no idea yet, the hex value would need to change to a HUE value and then the rest of the code would need to change.

I personally would stick to the method I outlined earlier in the thread - possibly because I can visualise RGB easier than HSV. Have you tried this approach? Did you bump into the same problem as Richard? As Nox says, the issue may just be that the Python type-checker requires integers, and floats are being supplied.

I’m still watching this thread, not had time to do much with anything Pi related recently (It’s gardening season…)

Nox’s suggestion looks interesting. Not sure my coding skills match what’s required though, sadly.

Mixing in Nox’s suggestion to your code, I would try:

led_strip.set_rgb(
    i,
    math.floor(r * multiplier),
    math.floor(g * multiplier),
    math.floor(b * multiplier)
)

If that doesn’t work, add your code and error here, as formatted code blocks, and someone should be able to help you.

1 Like

Remember also to add at the beginning

import math

…because I didn’t, and of course, it failed!

I then set mine at 50%, 0.5, which seems to work.

    # light up the LEDs
    multiplier = 0.5
    for i in range(NUM_LEDS):
        led_strip.set_rgb(i, 
        math.floor(r * multiplier),
        math.floor(g * multiplier),
        math.floor(b * multiplier),
)

I’ll let it run for a few hrs to confirm, but it looks promising.

3 Likes

I’ve added it the same code as Richard and it’s working well!

Thank you @halfer and @Nox

1 Like

I ran into a similar problem with my Interstate 75, no global brightness control.
I ended up using hsv. Just a for your info post.
Interstate 74 W, how do you control the display brightness? - Support - Pimoroni Buccaneers

Glad that works! I confess I am used to C-like languages where everything has a semi-colon at the end, and line-breaks are common for readability. I had forgotten Python is reliant on neat formatting - but it looks like @Richard238 confirms it does work. (The formatting isn’t ideal, as I find it more readable to indent the parameters within the set_rgb call, but I accept that might break the Python interpreter).