Sunday, 29 December 2024

Pimoroni Plasma 2350

Raspberry Pi recently released the RP2350 microcontroller. There was a shortage of the corresponding Pico 2 development board, but other board manufacturers certainly filled the gap.

One of them was Pimoroni with a number of interesting offerings.

One of them is the Plasma 2350 Neopixel strip controller.

I already had a set of the RGB LED Star Wire 66 Neopixel strips, so I just bought the board.

The board is fully assembled and just requires the use of a jeweller's type screwdriver to attach the wires from the NeoPixel strip to the board using the terminal block. One thing to note is that unlike the Plasma Stick 2040W, the Plasma 2350 has a four connector terminal block. As you can see, the connections to use are 5V, Dat[a] and negative.

The board has one QWIC/STEMMA I2C connector, an on-board NeoPixel, three buttons (reset, boot and user button) and a connector labelled SP/CE. The latter is an SPI connector standard allowing higher speed connections to the board (such as WIFI).

What it does not have is WIFI or Bluetooth onboard (a later variant does but does not have the SP/CE connector, a Raspberry Pi RM2 Wireless module is directly wired to the board.)

Code

So to use the board and the LED string, some code is required.
This is the code for the main.py file.
The plasma2040 module in plasma works with the Pasma 2350.
The user interface is very simple. Pressing the User Button A cycles through the available light options.
The specific display uses Pythons' polymorphism to handle the basic operations. The method update() updates the display and is triggered (in this case) every half a second.
The light_show_base class (and its subtypes) determine what happens during the update. That code is in a separate file.

main.py

import plasma
from light_show_base import RGBElement, light_show_base, light_show_static_seven, light_show_static_seven_reverse, light_show_alternate
from plasma import plasma2040
from time import sleep
from pimoroni import RGBLED
# Set how many LEDs you have
NUM_LEDS = 66

led = RGBLED(16, 17, 18) 

# WS2812 / NeoPixel™ LEDs
led_strip = plasma.WS2812(NUM_LEDS, 0, 0, plasma2040.DAT)

# Start updating the LED strip
led_strip.start()

display = light_show_base(led_strip, NUM_LEDS, led)
a_button = machine.Pin(12, machine.Pin.IN, machine.Pin.PULL_UP)

selected_pattern = 0

while True:
    display.update()
    if a_button.value() == 0:
        selected_pattern = selected_pattern + 1
        if selected_pattern > 5:
            selected_pattern = 0

        if selected_pattern == 0:
            display = light_show_base(led_strip, NUM_LEDS, led)
        elif selected_pattern == 1:
            display = light_show_static_seven(led_strip, NUM_LEDS, led)
        elif selected_pattern == 2:
            display = light_show_static_seven_reverse(led_strip, NUM_LEDS, led)
        elif selected_pattern == 3:
            display = light_show_alternate(led_strip, NUM_LEDS, led, RGBElement(255,0,0), RGBElement(0,255,0))
        elif selected_pattern == 4:
            display = light_show_alternate(led_strip, NUM_LEDS, led, RGBElement(0,0,255), RGBElement(255,255,0))
        elif selected_pattern == 5:
            display = light_show_alternate(led_strip, NUM_LEDS, led, RGBElement(0,255,0), RGBElement(255,255,255))
        print(selected_pattern)

    sleep(0.5)
    

light_show_base.py

The file contains two main classes: RGBElement and light_show_base.
There are also subclasses of class light_show_base, inheriting from light_show_base.
class RGBElement:
    def __init__(self,red, green,blue):
        self.red = red
        self.green = green
        self.blue = blue
    def __str__(self): 
        return f"{self.red} {self.green} {self.blue}"
        
class light_show_base:
    def __init__(self, led_strip, num_leds, rgb_led):
        # Device specific settings
        self.led_strip = led_strip
        self.rgb_led = rgb_led
        self.num_leds = num_leds
        
        # Chosen colour
        self.current_colour = 0
        
        # Base set of colours
        self.white = RGBElement(255,255,255)
        self.yellow = RGBElement(255,255,0)
        self.magenta = RGBElement(255,0,255)
        self.red = RGBElement(255,0,0)
        self.cyan = RGBElement(0,255,255)
        self.green = RGBElement(0,255,0)
        self.blue = RGBElement(0,0,255)
        self.black = RGBElement(0,0,0)
  
        # List of colours
        self.colours = [
            self.white,
            self.yellow,
            self.magenta,
            self.red,
            self.cyan,
            self.green,
            self.blue,
            self.black
            ] 

            
    def update(self):
        if self.current_colour == len(self.colours) - 1:
            self.current_colour = 0
        else:
            self.current_colour = self.current_colour + 1

        rgb_colour = self.colours[self.current_colour]
        self.rgb_led.set_rgb(rgb_colour.red, rgb_colour.green, rgb_colour.blue)
        for i in range(self.num_leds):
            self.led_strip.set_rgb(i, rgb_colour.green,rgb_colour.red, rgb_colour.blue)
        
class light_show_static_seven(light_show_base):
    def __init__(self, led_strip, num_leds, rgb_led):
        super().__init__(led_strip, num_leds, rgb_led)
        self.colour_strip = []
        ix = 0
        for i in range(self.num_leds):
            self.colour_strip.append(self.colours[ix])
            if ix == len(self.colours) - 1:
                ix = 0
            else:
                ix = ix +1
                
    def change_colours(self):
        last_colour = self.colour_strip[1]
        for i in range(self.num_leds):
            if i > 1:
                self.colour_strip[i - 1] = self.colour_strip[i]
        self.colour_strip[self.num_leds - 1] = last_colour
            
    def update(self):
        for i in range(self.num_leds):
            rgb_colour = self.colour_strip[i]           
            self.led_strip.set_rgb(i, rgb_colour.green,rgb_colour.red, rgb_colour.blue)
        rgb_colour = self.colour_strip[1] 
        self.rgb_led.set_rgb(rgb_colour.red, rgb_colour.green, rgb_colour.blue)

        self.change_colours()

class light_show_static_seven_reverse(light_show_static_seven):
    def __init__(self, led_strip, num_leds, rgb_led):
        super().__init__(led_strip, num_leds, rgb_led)

    def change_colours(self):
        last_colour = self.colour_strip[self.num_leds-1] 
        for i in range(self.num_leds-1):
            ix = self.num_leds - i
            print(ix)
            if ix < self.num_leds-1: 
                self.colour_strip[ix + 1] = self.colour_strip[ix]
        self.colour_strip[1] = last_colour            
        
class light_show_alternate(light_show_base):
     def __init__(self, led_strip, num_leds, rgb_led, led_one, led_two):
        super().__init__(led_strip, num_leds, rgb_led)
        self.led_one = led_one
        self.led_two = led_two

     def change_colours(self):
        temp = self.led_one
        self.led_one = self.led_two
        self.led_two = temp


     def update(self):
        led_one = self.led_one
        led_two = self.led_two
        self.rgb_led.set_rgb(led_one.red, led_one.green, led_one.blue)
        for i in range(self.num_leds/2):
            self.led_strip.set_rgb(i * 2, led_one.green,led_one.red, led_one.blue)
            self.led_strip.set_rgb(i * 2+1, led_two.green,led_two.red, led_two.blue)
        self.change_colours()

References