Skip to content

Instantly share code, notes, and snippets.

@dnnsmnstrr
Last active March 29, 2025 20:04
Show Gist options
  • Save dnnsmnstrr/355f622b69e1b82f8d7b69453e624355 to your computer and use it in GitHub Desktop.
Save dnnsmnstrr/355f622b69e1b82f8d7b69453e624355 to your computer and use it in GitHub Desktop.
Raspberry Pi Pico 2 with LED matrix
import time
import math
from machine import Pin
import rp2
NUM_LEDS = 25 # 5x5 matrix
max_lum = 100 # Maximum brightness level
brightness = 0.1 # Scale brightness (0.0 to 1.0)
@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
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(16).
sm = rp2.StateMachine(0, ws2812, freq=8_000_000, sideset_base=Pin(16))
sm.active(1)
def hsv_to_rgb(h, s, v):
h = h % 360
c = v * s
x = c * (1 - abs((h / 60) % 2 - 1))
m = v - c
if h < 60:
r, g, b = c, x, 0
elif h < 120:
r, g, b = x, c, 0
elif h < 180:
r, g, b = 0, c, x
elif h < 240:
r, g, b = 0, x, c
elif h < 300:
r, g, b = x, 0, c
else:
r, g, b = c, 0, x
return int((r + m) * 255 * brightness), int((g + m) * 255 * brightness), int((b + m) * 255 * brightness)
def set_leds(colors):
for r, g, b in colors:
rgb = (g << 24) | (r << 16) | (b << 8)
sm.put(rgb)
def wave_animation():
t = 0
while True:
colors = []
for y in range(5):
for x in range(5):
hue = (math.sin(t + (x + y) * 0.5) * 180 + 180) % 360
colors.append(hsv_to_rgb(hue, 1, 1))
set_leds(colors)
t += 0.2
time.sleep(0.1)
wave_animation()
import time
import math
from machine import Pin
import rp2
NUM_LEDS = 25 # 5x5 matrix
max_lum = 100 # Maximum brightness level
brightness = 0.1 # Scale brightness (0.0 to 1.0)
@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
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(16).
sm = rp2.StateMachine(0, ws2812, freq=8_000_000, sideset_base=Pin(16))
sm.active(1)
def hsv_to_rgb(h, s, v):
h = h % 360
c = v * s
x = c * (1 - abs((h / 60) % 2 - 1))
m = v - c
if h < 60:
r, g, b = c, x, 0
elif h < 120:
r, g, b = x, c, 0
elif h < 180:
r, g, b = 0, c, x
elif h < 240:
r, g, b = 0, x, c
elif h < 300:
r, g, b = x, 0, c
else:
r, g, b = c, 0, x
return int((r + m) * 255 * brightness), int((g + m) * 255 * brightness), int((b + m) * 255 * brightness)
def set_leds(colors):
for r, g, b in colors:
rgb = (g << 24) | (r << 16) | (b << 8)
sm.put(rgb)
# Define a simple 5x5 font for uppercase letters and space
font = {
' ': [0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0],
'A': [0,1,1,1,0, 1,0,0,0,1, 1,0,0,0,1, 1,1,1,1,1, 1,0,0,0,1],
'B': [1,1,1,1,0, 1,0,0,0,1, 1,1,1,1,0, 1,0,0,0,1, 1,1,1,1,0],
'C': [0,1,1,1,0, 1,0,0,0,1, 1,0,0,0,0, 1,0,0,0,1, 0,1,1,1,0],
'D': [1,1,1,1,0, 1,0,0,0,1, 1,0,0,0,1, 1,0,0,0,1, 1,1,1,1,0],
'E': [1,1,1,1,1, 1,0,0,0,0, 1,1,1,1,0, 1,0,0,0,0, 1,1,1,1,1],
'F': [1,1,1,1,1, 1,0,0,0,0, 1,1,1,1,0, 1,0,0,0,0, 1,0,0,0,0],
'G': [0,1,1,1,0, 1,0,0,0,1, 1,0,0,0,0, 1,0,1,0,1, 0,1,1,1,0],
'H': [1,0,0,0,1, 1,0,0,0,1, 1,1,1,1,1, 1,0,0,0,1, 1,0,0,0,1],
'I': [0,1,1,1,0, 0,0,1,0,0, 0,0,1,0,0, 0,0,1,0,0, 0,1,1,1,0],
'J': [0,1,1,1,0, 0,0,0,0,1, 0,0,0,0,1, 1,0,0,0,1, 0,1,1,1,0],
'K': [1,0,0,0,1, 1,0,0,1,0, 1,1,1,0,0, 1,0,0,1,0, 1,0,0,0,1],
'L': [1,0,0,0,0, 1,0,0,0,0, 1,0,0,0,0, 1,0,0,0,0, 1,1,1,1,1],
'M': [1,0,0,0,1, 1,1,0,1,1, 1,0,1,0,1, 1,0,0,0,1, 1,0,0,0,1],
'N': [1,0,0,0,1, 1,1,0,0,1, 1,0,1,0,1, 1,0,0,1,1, 1,0,0,0,1],
'O': [0,1,1,1,0, 1,0,0,0,1, 1,0,0,0,1, 1,0,0,0,1, 0,1,1,1,0],
'P': [1,1,1,1,0, 1,0,0,0,1, 1,1,1,1,0, 1,0,0,0,0, 1,0,0,0,0],
'Q': [0,1,1,1,0, 1,0,0,0,1, 1,0,0,0,1, 1,0,1,0,1, 0,1,1,1,1],
'R': [1,1,1,1,0, 1,0,0,0,1, 1,1,1,1,0, 1,0,0,1,0, 1,0,0,0,1],
'S': [0,1,1,1,1, 1,0,0,0,0, 0,1,1,1,0, 0,0,0,0,1, 1,1,1,0,0],
'T': [1,1,1,1,1, 0,0,1,0,0, 0,0,1,0,0, 0,0,1,0,0, 0,0,1,0,0],
'U': [1,0,0,0,1, 1,0,0,0,1, 1,0,0,0,1, 1,0,0,0,1, 0,1,1,1,0],
'V': [1,0,0,0,1, 1,0,0,0,1, 0,1,0,1,0, 0,1,0,1,0, 0,0,1,0,0],
'W': [1,0,0,0,1, 1,0,0,0,1, 1,0,1,0,1, 1,1,0,1,1, 1,0,0,0,1],
'X': [1,0,0,0,1, 0,1,0,1,0, 0,0,1,0,0, 0,1,0,1,0, 1,0,0,0,1],
'Y': [1,0,0,0,1, 1,0,0,0,1, 0,1,0,1,0, 0,0,1,0,0, 0,0,1,0,0],
'Z': [1,1,1,1,1, 0,0,0,1,0, 0,0,1,0,0, 0,1,0,0,0, 1,1,1,1,1],
'.': [0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,1,0,0],
',': [0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,1,0,0, 0,0,1,1,0],
'!': [0,0,1,0,0, 0,0,1,0,0, 0,0,1,0,0, 0,0,0,0,0, 0,0,1,0,0]
}
def get_char_pixels(char):
if char.upper() in font:
return font[char.upper()]
else:
return font[' '] # Return space for unknown characters
def scroll_text(text, scroll_speed=0.1, rainbow_effect=True):
text += " " # Add some spaces at the end for smoother scrolling
num_chars = len(text)
char_width = 5 # Width of each character (5 columns)
spacing = 1 # Blank column between characters
# Calculate total scroll steps needed
total_steps = num_chars * (char_width + spacing) + 4 # +4 to scroll completely off screen
for i in range(total_steps):
frame = [(0, 0, 0)] * NUM_LEDS
for char_index, char in enumerate(text):
pixels = get_char_pixels(char)
# Calculate the character's starting column position
char_start = char_index * (char_width + spacing) - i
# Only process if any part of the character is visible
if char_start < 5 and char_start > -char_width:
for row in range(5):
for col in range(5):
# Calculate the LED matrix position
led_col = char_start + col
if 0 <= led_col < 5: # Only draw if within visible columns
led_index = row * 5 + led_col
if pixels[row * 5 + col]: # If pixel should be lit
hue = (i * 5) % 360 # Rainbow effect that changes as it scrolls
frame[led_index] = hsv_to_rgb(hue if rainbow_effect else 1, 1, 1)
set_leds(frame)
time.sleep(scroll_speed)
if __name__ == "__main__":
try:
scroll_text("HELLO PICO!")
time.sleep(0.5)
# scroll_text("SCROLLING TEXT", 0.05)
while True:
scroll_text("WITHOUT RAINBOW", 0.1, False)
time.sleep(0.5)
scroll_text("HELLO WORLD")
time.sleep(0.5)
except KeyboardInterrupt:
# Turn off LEDs on Ctrl+C
set_leds([(0, 0, 0)] * NUM_LEDS)
import time
from machine import Pin
import rp2
NUM_LEDS = 25 # 5x5 matrix
PIN_NUM = 16 # GPIO pin connected to the LED matrix
brightness = 0.5 # Scale brightness (0.0 to 1.0)
@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
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
sm = rp2.StateMachine(0, ws2812, freq=8_000_000, sideset_base=Pin(PIN_NUM))
sm.active(1)
# Clear all LEDs
def clear_leds():
for i in range(NUM_LEDS):
sm.put(0)
time.sleep(0.01)
# Function to display colors - uses the SAME format as your working rainbow code
def set_leds(colors):
for r, g, b in colors:
# IMPORTANT: This matches your working rainbow code's format
rgb = (g << 24) | (r << 16) | (b << 8)
sm.put(rgb)
# Define colors
def rgb(r, g, b):
return (int(r * brightness), int(g * brightness), int(b * brightness))
# Basic colors
RED = rgb(255, 0, 0)
GREEN = rgb(0, 255, 0)
BLUE = rgb(0, 0, 255)
YELLOW = rgb(255, 255, 0)
PURPLE = rgb(128, 0, 128)
CYAN = rgb(0, 255, 255)
WHITE = rgb(255, 255, 255)
BLACK = rgb(0, 0, 0)
# Create heart pattern (5x5)
def heart_pattern():
return [
BLACK, RED, BLACK, RED, BLACK,
RED, RED, RED, RED, RED,
RED, RED, RED, RED, RED,
BLACK, RED, RED, RED, BLACK,
BLACK, BLACK, RED, BLACK, BLACK
]
# Create smiley pattern (5x5)
def smiley_pattern():
return [
BLACK, YELLOW, BLACK, YELLOW, BLACK,
BLACK, YELLOW, BLACK, YELLOW, BLACK,
BLACK, BLACK, BLACK, BLACK, BLACK,
YELLOW, YELLOW, BLACK, YELLOW, YELLOW,
BLACK, YELLOW, YELLOW, YELLOW, BLACK
]
# Create cross pattern (5x5)
def cross_pattern():
return [
BLACK, BLACK, BLUE, BLACK, BLACK,
BLACK, BLUE, BLUE, BLUE, BLACK,
BLUE, BLUE, BLUE, BLUE, BLUE,
BLACK, BLUE, BLUE, BLUE, BLACK,
BLACK, BLACK, BLUE, BLACK, BLACK
]
# Create arrow pattern (5x5)
def arrow_pattern():
return [
BLACK, BLACK, GREEN, BLACK, BLACK,
BLACK, BLACK, GREEN, GREEN, BLACK,
GREEN, GREEN, GREEN, GREEN, GREEN,
BLACK, BLACK, GREEN, GREEN, BLACK,
BLACK, BLACK, GREEN, BLACK, BLACK
]
# Rainbow animation (taken from your working code)
def hsv_to_rgb(h, s, v):
h = h % 360
c = v * s
x = c * (1 - abs((h / 60) % 2 - 1))
m = v - c
if h < 60:
r, g, b = c, x, 0
elif h < 120:
r, g, b = x, c, 0
elif h < 180:
r, g, b = 0, c, x
elif h < 240:
r, g, b = 0, x, c
elif h < 300:
r, g, b = x, 0, c
else:
r, g, b = c, 0, x
return int((r + m) * 255 * brightness), int((g + m) * 255 * brightness), int((b + m) * 255 * brightness)
def main():
# Get all patterns
patterns = [
heart_pattern(),
smiley_pattern(),
cross_pattern(),
arrow_pattern()
]
# Main loop - cycle through all patterns
try:
while True:
for pattern in patterns:
clear_leds()
set_leds(pattern)
time.sleep(1)
except KeyboardInterrupt:
clear_leds()
print("Animation stopped")
# Choose which animation to run
clear_leds()
# Uncomment the animation you want to run
main() # Cycle through all patterns
@dnnsmnstrr
Copy link
Author

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment