Last active
March 29, 2025 20:04
-
-
Save dnnsmnstrr/355f622b69e1b82f8d7b69453e624355 to your computer and use it in GitHub Desktop.
Raspberry Pi Pico 2 with LED matrix
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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() | |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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) | |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
https://www.waveshare.com/wiki/RP2040-Matrix