I have a question regarding a new project I’m currently working on. It involves a Raspberry Pico W, an external 5V 12A power supply and a WS2812B LED strip. Now, I already got it working flawlessly using an Arduino Uno R3 and now want to port it to MicroPython on the Pico using the built-in NeoPixel library.

The connections are made as follows: The LED strip 5V and GND are connected to the positive and negative terminals of the power supply, and Din is attached to one of the Uno's digital pins (in my case 7). There is also a common ground connection between the LED strip, power supply and the Uno as stated in multiple guides. The Uno itself is powered over USB.

As far as I can tell the connections should still stay the same, however I would have to connect the 5V power supply‘s ground to the Pico's ground. Is this safe to do, considering the fact that both devices run at different voltages or will I have to use some type of voltage regulation?

I'm still a beginner in electronics and have made all my experiences so far using the Arduino and just got a Pico recently, so I want to make sure I don't break anything by accident. Thank you in advance for any help.

2 Answers 2


This is perfectly safe and it is the expected way to do it, in fact, I have such a setup on my desk right now.

A lot of products use different voltages on the same PCB, but share the same ground.

What you technically need to worry about is that the WS2812B expects a digital control signal that is higher than the 3.3 volt you get from the Raspberry Pi Pico, but in practice it works well with a direct connection and I have not seen any reports of people having issues interfacing a 3.3 volt system to the WS2812B. If I was to do a commercial product I would add a simple level converter in between but it's not something you should worry about at this stage.

  • WS2812B is 3.3V compatible.
    – Milliways
    Feb 4 at 12:33
  • @Milliways Do you have a source for that? The datasheet disagrees.
    – pipe
    Feb 4 at 16:24

Not only is it safe it is essential.

Without a common reference connection it is unlikely to work and risks damage.

In general ANY circuit should have a common "ground" (actually they need common reference which is not necessarily ground but this is esoteric).

Incidentally there is a far better and simpler way to control LED strips using the Pico PIO which I have used.

# Example using PIO to drive a set of WS2812 LEDs.
# https://core-electronics.com.au/guides/how-to-use-ws2812b-rgb-leds-with-raspberry-pi-pico/
import array, time
from machine import Pin
import rp2

# Configure the number of WS2812 LEDs.
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)

def ws2812():
    T1 = 2
    T2 = 5
    T3 = 3
    out(x, 1)               .side(0)    [T3 - 1]
    jmp(not_x, "do_zero")   .side(1)    [T1 - 1]
    jmp("bitloop")          .side(1)    [T2 - 1]
    nop()                   .side(0)    [T2 - 1]

# 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.

# 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)
        dimmer_ar[i] = (g<<16) + (r<<8) + b
    sm.put(dimmer_ar, 8)

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)
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))

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)

for color in COLORS:       

for color in COLORS:       
#     color_chase(color, 0.01)
    color_chase(color, 0.05)


Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.