Close

Porting from Arduino (C++) to RP2040 (MicroPython)

A project log for Awesome Mix Vol. 1

Cassette Tape SAO with backlit LED spools and I2C-triggered visualizations animating Fast Forward, Rewind, Play, and Pause.

dustin-johnsonDustin Johnson 10/25/2024 at 06:240 Comments

I needed to port my Arduino design onto the RP2040. I was going to use a boost converter, but I don't have one, so I just decided to use the 5V rail on the RP2040-One that gets "populated" on the RP2040 when powered over USB. If I take care of the 5V rail on the circuit later, the code should be the same either way.

We can see I have another rp2040 "SAO" connected via a directly soldered I2C bus ;) I'm working on the I2C communication -- the disconnected rp2040-Matrix you see connected will be pretending to be the conference badge (the I2C master), for now.

Pics of the updated prototype circuit:

A video of the same animations playing, but now through micropython:

The ported code is as follows:

# Arduino code ported to RP2040 micropython
# -----------------------------------------
import machine
import neopixel
import time
import random

LED_PIN = 8
LED_COUNT = 14
LED_BRIGHTNESS = 0.05  # Start with 0.1 to check visibility; adjust to preferred level
LED_CENTER_LEFT = 0
LED_CENTER_RIGHT = 7
LED_LEFT_MIN = 1  # Exclude center LED (left spool)
LED_LEFT_MAX = 6  # Exclude center LED (left spool)
LED_RIGHT_MIN = 8  # Exclude center LED (right spool)
LED_RIGHT_MAX = 13  # Exclude center LED (right spool)

# Initialize NeoPixel
np = neopixel.NeoPixel(machine.Pin(LED_PIN), LED_COUNT)

LED_LEFT_INDEX = random.randint(LED_LEFT_MIN, LED_LEFT_MAX)
LED_RIGHT_INDEX = random.randint(LED_RIGHT_MIN, LED_RIGHT_MAX)

# Original colors
FOREGROUND_COLOR = (0, 0, 0)  # Black
BACKGROUND_COLOR = (255, 165, 0)  # Orange
CENTER_COLOR = (255, 0, 0)  # Red

# Function to adjust brightness with minimum scaling effect
def set_neopixel_color(color, brightness_factor):
    return tuple(max(int(c * brightness_factor), 1) for c in color)


# Animation functions with brightness adjustment
# ----------------------------------------------
def animation_play(millis_delay=130):
    global LED_LEFT_INDEX, LED_RIGHT_INDEX
    
    # Play animation for left spool
    if LED_LEFT_INDEX < LED_LEFT_MAX:
        np[LED_LEFT_INDEX] = set_neopixel_color(BACKGROUND_COLOR, LED_BRIGHTNESS)
        np[LED_LEFT_INDEX + 1] = set_neopixel_color(FOREGROUND_COLOR, LED_BRIGHTNESS)
        LED_LEFT_INDEX += 1
    else:
        np[LED_LEFT_MAX] = set_neopixel_color(BACKGROUND_COLOR, LED_BRIGHTNESS)
        np[LED_LEFT_MIN] = set_neopixel_color(FOREGROUND_COLOR, LED_BRIGHTNESS)
        LED_LEFT_INDEX = LED_LEFT_MIN

    # Play animation for right spool
    if LED_RIGHT_INDEX < LED_RIGHT_MAX:
        np[LED_RIGHT_INDEX] = set_neopixel_color(BACKGROUND_COLOR, LED_BRIGHTNESS)
        np[LED_RIGHT_INDEX + 1] = set_neopixel_color(FOREGROUND_COLOR, LED_BRIGHTNESS)
        LED_RIGHT_INDEX += 1
    else:
        np[LED_RIGHT_MAX] = set_neopixel_color(BACKGROUND_COLOR, LED_BRIGHTNESS)
        np[LED_RIGHT_MIN] = set_neopixel_color(FOREGROUND_COLOR, LED_BRIGHTNESS)
        LED_RIGHT_INDEX = LED_RIGHT_MIN

    np.write()
    time.sleep_ms(millis_delay)


def animation_rewind(millis_delay=50):
    global LED_LEFT_INDEX, LED_RIGHT_INDEX
    
    # Rewind animation for left spool
    if LED_LEFT_INDEX > LED_LEFT_MIN:
        np[LED_LEFT_INDEX] = set_neopixel_color(BACKGROUND_COLOR, LED_BRIGHTNESS)
        np[LED_LEFT_INDEX - 1] = set_neopixel_color(FOREGROUND_COLOR, LED_BRIGHTNESS)
        LED_LEFT_INDEX -= 1
    else:
        np[LED_LEFT_MIN] = set_neopixel_color(BACKGROUND_COLOR, LED_BRIGHTNESS)
        np[LED_LEFT_MAX] = set_neopixel_color(FOREGROUND_COLOR, LED_BRIGHTNESS)
        LED_LEFT_INDEX = LED_LEFT_MAX

    # Rewind animation for right spool
    if LED_RIGHT_INDEX > LED_RIGHT_MIN:
        np[LED_RIGHT_INDEX] = set_neopixel_color(BACKGROUND_COLOR, LED_BRIGHTNESS)
        np[LED_RIGHT_INDEX - 1] = set_neopixel_color(FOREGROUND_COLOR, LED_BRIGHTNESS)
        LED_RIGHT_INDEX -= 1
    else:
        np[LED_RIGHT_MIN] = set_neopixel_color(BACKGROUND_COLOR, LED_BRIGHTNESS)
        np[LED_RIGHT_MAX] = set_neopixel_color(FOREGROUND_COLOR, LED_BRIGHTNESS)
        LED_RIGHT_INDEX = LED_RIGHT_MAX

    np.write()
    time.sleep_ms(millis_delay)


# Blink to indicate function triggered
def animation_function_triggered(color):
    np[LED_CENTER_LEFT] = set_neopixel_color(color, LED_BRIGHTNESS)
    np[LED_CENTER_RIGHT] = set_neopixel_color(color, LED_BRIGHTNESS)
    np.write()
    time.sleep_ms(100)
    np[LED_CENTER_LEFT] = set_neopixel_color((0, 0, 0), LED_BRIGHTNESS)
    np[LED_CENTER_RIGHT] = set_neopixel_color((0, 0, 0), LED_BRIGHTNESS)
    np.write()


def animation_pause():
    np[LED_LEFT_INDEX] = set_neopixel_color(BACKGROUND_COLOR, LED_BRIGHTNESS)
    np[LED_RIGHT_INDEX] = set_neopixel_color(BACKGROUND_COLOR, LED_BRIGHTNESS)
    np.write()
    time.sleep_ms(100)


def animation_bootup():
    # Illuminate left spool
    for i in range(LED_LEFT_MIN, LED_LEFT_MAX + 1):
        if i == LED_CENTER_LEFT:
            continue
        np[i] = set_neopixel_color(BACKGROUND_COLOR, LED_BRIGHTNESS)
        np.write()
        time.sleep_ms(50)

    # Illuminate right spool
    for i in range(LED_RIGHT_MIN, LED_RIGHT_MAX + 1):
        if i == LED_CENTER_RIGHT:
            continue
        np[i] = set_neopixel_color(BACKGROUND_COLOR, LED_BRIGHTNESS)
        np.write()
        time.sleep_ms(50)


def animation_fastforward():
    animation_play(40)


# Main setup
# ----------
animation_bootup()

# Main loop
# ---------
while True:
    animation_function_triggered((255, 255, 255))  # White
    for _ in range(20):
        animation_pause()

    animation_function_triggered((255, 255, 255))
    for _ in range(50):
        animation_play()

    animation_function_triggered((255, 255, 255))
    for _ in range(150):
        animation_fastforward()

    animation_function_triggered((255, 255, 255))
    for _ in range(50):
        animation_play()

    animation_function_triggered((255, 255, 255))
    for _ in range(50):
        animation_rewind()

Discussions