I’ve followed the video and got 45 of the 60 neopixels working.
Is it likely to be a lack of power from the pico?
If I set the brightness to 0.6, there’s is a lot of white flashing, which makes me think it’s power related.
I’ve followed the video and got 45 of the 60 neopixels working.
Is it likely to be a lack of power from the pico?
If I set the brightness to 0.6, there’s is a lot of white flashing, which makes me think it’s power related.
Hi Paul,
Do you have a photo of your setup? Which video are you following?
This is the tutorial:

Yes, you’ll definitely need external power to run that many WS2812s. For an extreme example, checkout adafruits neopixel curtain writeup.
Well that was an interesting fix.
I connected to an ATX psu to guarantee enough power, but it still wouldn’t show the last 15 leds.
Thinking that I had a faulty strip, I changed the number of leds in the code to 45.
This time, 30 leds sequenced, 15 lit but didn’t sequence and 15 stayed dead. Trial and error led me to set the number in the code to 80 and it now works fine.
I spent a lot of time trying to light individual pixels, but the results were always confusing. Never the same led, rarely the requested color.
And then it hit me, I’m using RGBWW neopixels, with RGB software, so the strip is expecting 4 commands but only getting three, hence the inconsistencies.
Is there an easy way to add the white channel?
It depends on your definition of easy
But yes, with some minor modifications to the example code you should be able to get it working. I don’t think you need to touch the state machine code but you’ll need to add in support for the WW channel.
I’m going to have a go at this tomorrow if I get some time! Good chance to have a play with a Pico
My son had a play last night and has go the correct colours showing, but still hasn’t activated the white.
Hi Paul,
Not coming at you with any solutions just yet.
I reviewed the code for someone at Core to do a bit of testing with.
I found this page here from the Raspberry Pi Foundation outlining some similar code in C++.
I’ll add some comments with explanations as to what the code is/might be doing (I have marked them with ’ #L - ')
# Example using PIO to drive a set of WS2812 LEDs.
#L - Importing the libraries commonly used in microcontrollers
import array, time
from machine import Pin
import rp2
# Configure the number of WS2812 LEDs.
NUM_LEDS = 13
PIN_NUM = 22
brightness = 0.2
@rp2.asm_pio(sideset_init=rp2.PIO.OUT_LOW, out_shiftdir=rp2.PIO.SHIFT_LEFT, autopull=True, pull_thresh=24) #L - Initialising the state machine for output, using the following settings
def ws2812():
T1 = 2 #L - Defining the timings for an output of either 1 or 0, not important for our case, though if you were using a different LED controller this would be essential
T2 = 5
T3 = 3
wrap_target()
label("bitloop")
out(x, 1) .side(0) [T3 - 1]
jmp(not_x, "do_zero") .side(1) [T1 - 1]
jmp("bitloop") .side(1) [T2 - 1]
label("do_zero")
nop() .side(0) [T2 - 1]
wrap()
# Create the StateMachine with the ws2812 program, outputting on pin
sm = rp2.StateMachine(0, ws2812, freq=8_000_000, sideset_base=Pin(PIN_NUM))
# Start the StateMachine, it will wait for data on its FIFO.
sm.active(1)
# Display a pattern on the LEDs via an array of LED RGB values.
ar = array.array("I", [0 for _ in range(NUM_LEDS)])
##########################################################################
def pixels_show():
dimmer_ar = array.array("I", [0 for _ in range(NUM_LEDS)]) #L - The capital i means that it is an integer array and the underscore is used as a variable basically loops through creating an element for each LED
for i,c in enumerate(ar): #L - Create the 'packets' to be sent to the WS2812 strip, the 0xFF in short means 100% on, after multiplying the brightness it changes how dim the colour is
r = int(((c >> 8) & 0xFF) * brightness)
g = int(((c >> 16) & 0xFF) * brightness)
b = int((c & 0xFF) * brightness)
dimmer_ar[i] = (g<<16) + (r<<8) + b
sm.put(dimmer_ar, 8) #L - Couldnt find anything on this line, from the sounds of it it puts the dimmer array into the state machine to send, I definitely could be way off the mark here, I would love to learn what exactly this line does!
time.sleep_ms(10)
#L - Below are some higher level functions that are run automatically
def pixels_set(i, color):
ar[i] = (color[1]<<16) + (color[0]<<8) + color[2]
def pixels_fill(color):
for i in range(len(ar)):
pixels_set(i, color)
def color_chase(color, wait):
for i in range(NUM_LEDS):
pixels_set(i, color)
time.sleep(wait)
pixels_show()
time.sleep(0.2)
def wheel(pos):
# Input a value 0 to 255 to get a color value.
# The colours are a transition r - g - b - back to r.
if pos < 0 or pos > 255:
return (0, 0, 0)
if pos < 85:
return (255 - pos * 3, pos * 3, 0)
if pos < 170:
pos -= 85
return (0, 255 - pos * 3, pos * 3)
pos -= 170
return (pos * 3, 0, 255 - pos * 3)
def rainbow_cycle(wait):
for j in range(255):
for i in range(NUM_LEDS):
rc_index = (i * 256 // NUM_LEDS) + j
pixels_set(i, wheel(rc_index & 255))
pixels_show()
time.sleep(wait)
BLACK = (0, 0, 0)
RED = (255, 0, 0)
YELLOW = (255, 150, 0)
GREEN = (0, 255, 0)
CYAN = (0, 255, 255)
BLUE = (0, 0, 255)
PURPLE = (180, 0, 255)
WHITE = (255, 255, 255)
COLORS = (BLACK, RED, YELLOW, GREEN, CYAN, BLUE, PURPLE, WHITE)
print("fills")
for color in COLORS:
pixels_fill(color)
pixels_show()
time.sleep(0.2)
print("chases")
for color in COLORS:
color_chase(color, 0.01)
print("rainbow")
rainbow_cycle(0)
Regards,
Liam.
My son got it working last night. I’ll post the code later.
Here is the quick hash my son made to get it working, with comments.
The brightness is set so low because I’m running 60 pixels off the pico and it crashes if I put the brightness too high. I’ve got a 7.5A ubec to power the finished item.
# Example using PIO to drive a set of WS2812 LEDs.
import array, time
from machine import Pin
import rp2
# Configure the number of WS2812 LEDs.
NUM_LEDS = 60
PIN_NUM = 22
brightness = 0.01
@rp2.asm_pio(sideset_init=rp2.PIO.OUT_LOW, out_shiftdir=rp2.PIO.SHIFT_LEFT, autopull=True, pull_thresh=32) # changed
def ws2812():
T1 = 2
T2 = 5
T3 = 3
wrap_target()
label("bitloop")
out(x, 1) .side(0) [T3 - 1]
jmp(not_x, "do_zero") .side(1) [T1 - 1]
jmp("bitloop") .side(1) [T2 - 1]
label("do_zero")
nop() .side(0) [T2 - 1]
wrap()
# Create the StateMachine with the ws2812 program, outputting on pin
sm = rp2.StateMachine(0, ws2812, freq=8_000_000, sideset_base=Pin(PIN_NUM))
# Start the StateMachine, it will wait for data on its FIFO.
sm.active(1)
# Display a pattern on the LEDs via an array of LED RGB values.
ar = array.array("I", [0 for _ in range(NUM_LEDS)])
##########################################################################
def pixels_show():
dimmer_ar = array.array("I", [0 for _ in range(NUM_LEDS)])
for i,c in enumerate(ar):
r = int(((c >> 8) & 0xFF) * brightness)
g = int(((c >> 16) & 0xFF) * brightness)
b = int((c & 0xFF) * brightness)
gg = int(((c >> 24) & 0xFF) * brightness) #susposidly white added
dimmer_ar[i] = (gg<<24) + (g<<16) + (r<<8) + b # ^
sm.put(dimmer_ar, 0) # do not discard any bits
time.sleep_ms(10)
def pixels_set(i, color):
ar[i] = (color[3]<<24)+ (color[1]<<16) + (color[0]<<8) + color[2] #needs reordering, color[3] supposed to be white
def pixels_fill(color):
for i in range(len(ar)):
pixels_set(i, color)
def color_chase(color, wait):
for i in range(NUM_LEDS):
pixels_set(i, color)
time.sleep(wait)
pixels_show()
time.sleep(0.2)
def wheel(pos):
# Input a value 0 to 255 to get a color value.
# The colours are a transition r - g - b - back to r.
if pos < 0 or pos > 255:
return (0, 0, 0)
if pos < 85:
return (255 - pos * 3, pos * 3, 0)
if pos < 170:
pos -= 85
return (0, 255 - pos * 3, pos * 3)
pos -= 170
return (pos * 3, 0, 255 - pos * 3)
def rainbow_cycle(wait): #needs remaking to support the white argument
for j in range(255):
for i in range(NUM_LEDS):
rc_index = (i * 256 // NUM_LEDS) + j
pixels_set(i, wheel(rc_index & 255))
pixels_show()
time.sleep(wait)
#colors set in RGBW format
BLACK = (0, 0, 0,0)
RED = (255, 0, 0,0)
YELLOW = (255, 150, 0,0)
GREEN = (0, 255, 0,0)
CYAN = (0, 255, 255,0)
BLUE = (0, 0, 255,0)
PURPLE = (180, 0, 255,0)
WHITE = (0,0,0,255)
ORANGE = (255,165,0,0) # added
COLORS = (BLACK, RED, YELLOW, GREEN, CYAN, BLUE, PURPLE, WHITE, ORANGE)
pixels_fill(BLACK)
pixels_show()
time.sleep(1)
#pixels_fill(ORANGE)
#pixels_show()
pixels_set(3,RED)
#pixels_set(1,RED)
#pixels_set(3,BLUE)
pixels_show()
#test to find the order of color values, currently displays as BRWG
#BRWG
while 0:
color = 255,0,0,0
pixels_fill(color)
pixels_show()
time.sleep(1)
color = 0,255,0,0
pixels_fill(color)
pixels_show()
time.sleep(1)
color = 0,0,255,0
pixels_fill(color)
pixels_show()
time.sleep(1)
color = 0,0,0,255
pixels_fill(color)
pixels_show()
time.sleep(1)
#demo with rainbow disabled
while 1:
print("color test")
color = 0,255,0,255
pixels_fill(color)
pixels_show()
time.sleep(1)
print("fills")
for color in COLORS:
pixels_fill(color)
pixels_show()
time.sleep(0.1)
print("chases")
for color in COLORS:
color_chase(color, 0.01)
print("rainbow")
# rainbow_cycle(0)
Thanks Paul,
That’s excellent! Let him know that we said well done on the fix! If there’s anything else that we can do for you please let us know. Have a great day!
Updated to include rainbow
# Example using PIO to drive a set of WS2812 LEDs.
import array, time
from machine import Pin
import rp2
# Configure the number of WS2812 LEDs.
NUM_LEDS = 60
PIN_NUM = 22
brightness = 0.09
@rp2.asm_pio(sideset_init=rp2.PIO.OUT_LOW, out_shiftdir=rp2.PIO.SHIFT_LEFT, autopull=True, pull_thresh=32) # changed
def ws2812():
T1 = 2
T2 = 5
T3 = 3
wrap_target()
label("bitloop")
out(x, 1) .side(0) [T3 - 1]
jmp(not_x, "do_zero") .side(1) [T1 - 1]
jmp("bitloop") .side(1) [T2 - 1]
label("do_zero")
nop() .side(0) [T2 - 1]
wrap()
# Create the StateMachine with the ws2812 program, outputting on pin
sm = rp2.StateMachine(0, ws2812, freq=8_000_000, sideset_base=Pin(PIN_NUM))
# Start the StateMachine, it will wait for data on its FIFO.
sm.active(1)
# Display a pattern on the LEDs via an array of LED RGB values.
ar = array.array("I", [0 for _ in range(NUM_LEDS)])
##########################################################################
def pixels_show():
dimmer_ar = array.array("I", [0 for _ in range(NUM_LEDS)])
for i,c in enumerate(ar):
r = int(((c >> 8) & 0xFF) * brightness)
g = int(((c >> 16) & 0xFF) * brightness)
b = int((c & 0xFF) * brightness)
gg = int(((c >> 24) & 0xFF) * brightness) #susposidly white added
dimmer_ar[i] = (gg<<24) + (g<<16) + (r<<8) + b # ^
sm.put(dimmer_ar, 0) # do not discard any bits
time.sleep_ms(10)
def pixels_set(i, color):
ar[i] = (color[3]<<24)+ (color[1]<<16) + (color[0]<<8) + color[2] #needs reordering, color[3] supposed to be white
def pixels_fill(color):
for i in range(len(ar)):
pixels_set(i, color)
def color_chase(color, wait):
for i in range(NUM_LEDS):
pixels_set(i, color)
time.sleep(wait)
pixels_show()
time.sleep(0.2)
def wheel(pos):
# Input a value 0 to 255 to get a color value.
# The colours are a transition r - g - b - back to r.
if pos < 0 or pos > 255:
return (0, 0, 0,0)
if pos < 85:
return (255 - pos * 3, pos * 3, 0,0)
if pos < 170:
pos -= 85
return (0, 255 - pos * 3, pos * 3,0)
pos -= 170
return (pos * 3, 0, 255 - pos * 3,0)
def rainbow_cycle(wait): #needs remaking to support the white argument
for j in range(255):
for i in range(NUM_LEDS):
rc_index = (i * 256 // NUM_LEDS) + j
pixels_set(i, wheel(rc_index & 255))
pixels_show()
time.sleep(wait)
#colors set in RGBW format
BLACK = (0, 0, 0,0)
RED = (255, 0, 0,0)
YELLOW = (255, 150, 0,0)
GREEN = (0, 255, 0,0)
CYAN = (0, 255, 255,0)
BLUE = (0, 0, 255,0)
PURPLE = (180, 0, 255,0)
WHITE = (0,0,0,255)
ORANGE = (255,165,0,0) # added
COLORS = (BLACK, RED, YELLOW, GREEN, CYAN, BLUE, PURPLE, WHITE, ORANGE)
pixels_fill(BLACK)
pixels_show()
time.sleep(1)
#pixels_fill(ORANGE)
#pixels_show()
pixels_set(3,RED)
#pixels_set(1,RED)
#pixels_set(3,BLUE)
pixels_show()
#test to find the order of color values, currently displays as BRWG
#BRWG
while 0:
color = 255,0,0,0
pixels_fill(color)
pixels_show()
time.sleep(1)
color = 0,255,0,0
pixels_fill(color)
pixels_show()
time.sleep(1)
color = 0,0,255,0
pixels_fill(color)
pixels_show()
time.sleep(1)
color = 0,0,0,255
pixels_fill(color)
pixels_show()
time.sleep(1)
while 1:
print("color test")
color = 0,255,0,255
pixels_fill(color)
pixels_show()
time.sleep(1)
print("fills")
for color in COLORS:
pixels_fill(color)
pixels_show()
time.sleep(0.1)
print("chases")
for color in COLORS:
color_chase(color, 0.01)
print("rainbow")
rainbow_cycle(0)
Hi Paul,
Awesome!! Amazing work from your son!
Thanks for adding some comments in your code, I couldn’t find all of the documentation
Liam.
He’s under strict instructions to sort out the green in rainbow tonight. Then he can start building the new 3d printer!
The rainbow now has green
# Example using PIO to drive a set of WS2812 LEDs.
import array, time
from machine import Pin
import rp2
# Configure the number of WS2812 LEDs.
NUM_LEDS = 16
# Configure the GPIO pin number
PIN_NUM = 22
# configure the brightness (0 - 1)
brightness = 0.1
@rp2.asm_pio(sideset_init=rp2.PIO.OUT_LOW, out_shiftdir=rp2.PIO.SHIFT_LEFT, autopull=True, pull_thresh=32)
def ws2812():
T1 = 2
T2 = 5
T3 = 3
wrap_target()
label("bitloop")
out(x, 1) .side(0) [T3 - 1]
jmp(not_x, "do_zero") .side(1) [T1 - 1]
jmp("bitloop") .side(1) [T2 - 1]
label("do_zero")
nop() .side(0) [T2 - 1]
wrap()
# Create the StateMachine with the ws2812 program, outputting on pin
sm = rp2.StateMachine(0, ws2812, freq=8_000_000, sideset_base=Pin(PIN_NUM))
# Start the StateMachine, it will wait for data on its FIFO.
sm.active(1)
# Display a pattern on the LEDs via an array of LED RGB values.
ar = array.array("I", [0 for _ in range(NUM_LEDS)])
##########################################################################
def pixels_show():
dimmer_ar = array.array("I", [0 for _ in range(NUM_LEDS)])
for i,c in enumerate(ar):
r = int(((c >> 8) & 0xFF) * brightness)
g = int(((c >> 16) & 0xFF) * brightness)
b = int((c & 0xFF) * brightness)
gg = int(((c >> 24) & 0xFF) * brightness)
dimmer_ar[i] = (gg<<24) + (g<<16) + (r<<8) + b
sm.put(dimmer_ar, 0) # do not discard any bits
time.sleep_ms(10)
#brwg
#rgbw
def pixels_set(i, color):
#ar[i] = (color[3]<<24)+ (color[1]<<16) + (color[0]<<8) + color[2] #needs reordering, color[3] supposed to be white
ar[i] = (color[0]<<16)+(color[1]<<24)+(color[2]<<8)+(color[3])
def pixels_fill(color):
for i in range(len(ar)):
pixels_set(i, color)
def color_chase(color, wait):
for i in range(NUM_LEDS):
pixels_set(i, color)
time.sleep(wait)
pixels_show()
time.sleep(0.2)
def wheel(pos):
# Input a value 0 to 255 to get a color value.
# The colours are a transition r - g - b - back to r.
if pos < 0 or pos > 255:
return (0, 0, 0,0)
if pos < 85:
return (255 - pos * 3, pos * 3, 0,0)
if pos < 170:
pos -= 85
return (0, 255 - pos * 3, pos * 3,0)
pos -= 170
return (pos * 3, 0, 255 - pos * 3,0)
def rainbow_cycle(wait): #needs remaking to support the white argument
for j in range(255):
for i in range(NUM_LEDS):
rc_index = (i * 256 // NUM_LEDS) + j
pixels_set(i, wheel(rc_index & 255))
pixels_show()
time.sleep(wait)
#colors set in RGBW format
BLACK = (0, 0, 0,0)
RED = (255, 0, 0,0)
YELLOW = (255, 150, 0,0)
GREEN = (0, 255, 0,0)
CYAN = (0, 255, 255,0)
BLUE = (0, 0, 255,0)
PURPLE = (180, 0, 255,0)
WHITE = (0,0,0,255)
ORANGE = (255,165,0,0)
COLORS = (BLACK, RED, YELLOW, GREEN, CYAN, BLUE, PURPLE, WHITE, ORANGE)
# Start off with no light
pixels_fill(BLACK)
pixels_show()
time.sleep(1)
#test to find the order of color values, currently displays as BRWG
#BRWG
while 0:
print("order test")
color = 255,0,0,0
pixels_fill(color)
pixels_show()
time.sleep(1)
color = 0,255,0,0
pixels_fill(color)
pixels_show()
time.sleep(1)
color = 0,0,255,0
pixels_fill(color)
pixels_show()
time.sleep(1)
color = 0,0,0,255
pixels_fill(color)
pixels_show()
time.sleep(1)
while 1:
print("color test")
color = 0,255,0,255
pixels_fill(color)
pixels_show()
time.sleep(1)
print("fills")
for color in COLORS:
pixels_fill(color)
pixels_show()
time.sleep(0.5)
print("chases")
for color in COLORS:
color_chase(color, 0.01)
print("rainbow")
rainbow_cycle(0)
Nice work
A day of frustration.
New neopixels arrive, this time 60 per metre. Knowing that the pico will struggle to drive them, I connect up the ATX supply and use a new pico. Everything goes wrong.
I then connect the old, 30 per metre strip. Everything goes wrong.
Go back to the old pico, everything goes wrong.
Drop the brightness in software and power from the pico, everything works.
This sounds like a floating earth problem. Fitted into my van, the pico & led strip will run from the same supply, but on the test bed, the pico runs from the desktop pi4.
Linking the pico & ATX grounds together solved the problem.
Learn from my experience
Floating grounds! Always catch me out too.
You’ll have to upload some photos when it’s all done!