SeppeBudenaers / IoT_Technologie_PXL_2024

1 stars 0 forks source link

WS2812 #21

Open SeppeBudenaers opened 9 months ago

SeppeBudenaers commented 9 months ago

Epic : #8

SamyWarnants commented 9 months ago

How do you program the LED strip?

Great source to learn more about ws28x ledstrips.

For programming the WS2813 ledstrip on the pico we used the standard neopixel.py library. A ZIP-folder containing the files to be installed here. (If you don't now how to transfer this library to the pico here is a link on how to transfer files using thonny).

1) Upload the code below to the pico:

import time
from neopixel import Neopixel

numpix = 14
pixels = Neopixel(numpix, 0, 28, "RGB")

green = (0, 255, 0)
blue = (0, 0, 255)
red = (255, 0, 0)
color0 = green
color1 = blue

pixels.brightness(50)
pixels.fill(blue)

while True:
    if color0 == green:
       color0 = blue
       color1 = green
    else:
        color0 = green
        color1 = blue
    pixels.set_pixel(3, color0)
    pixels.set_pixel(4, color1)
    pixels.show()
    time.sleep(1)

2) When this code is uploaded to the pico and the ledstrip is connected. All the leds should turn blue and the third and fourth led should switch colors between blue and green. We can see that the pixel.fill() function is used to turn all the leds to the same color. This can come in handy for the game code. This code is verified and works.

SamyWarnants commented 8 months ago

Seppe and Kobe will take over this ticket.

SeppeBudenaers commented 8 months ago

because we could not get machine to work inside of a docker we used a SPI kernelmodule and made a custom ws2812 library to convert R G B Brightness values into a ws2812 data stream

custom ws2812 library

from dataclasses import dataclass

@dataclass
class RGBdata:
    RED: int
    GREEN: int
    BLUE: int
    BRIGHTNESS: int

    def __init__(self, red: int = 0, green: int = 0, blue: int = 0, brightness: int =0):
        def limit_to_8bits(value):
            return value & 0xFF

        self.RED = limit_to_8bits(red)
        self.BLUE = limit_to_8bits(blue)
        self.GREEN = limit_to_8bits(green)
        self.BRIGHTNESS = limit_to_8bits(brightness)

    def output_bytes(self) -> bytes:

        # Calculate RGB values with brightness adjustment
        red_value = int(self.RED * self.BRIGHTNESS/255 )
        green_value = int(self.GREEN * self.BRIGHTNESS/255)
        blue_value = int(self.BLUE * self.BRIGHTNESS/255)

        # Pack RGB values into a 3-byte representation (bytes)
        output = bytes([blue_value, red_value, green_value])
        return output

    def colors(self):
        output: str = " "+str(self.RED) +" "+ str(self.GREEN) +" "+ str(self.BLUE) +" "+ str(self.BRIGHTNESS)
        return output

@dataclass
class Neopixel:

    def __init__(self, count: int =0):
        self.pixels = [RGBdata()] * count

    pixels = []

    def colors(self):
        output_list = []
        index = 0
        for pixel in self.pixels:
            output_list.append("LED" + str(index) + self.pixels[index].colors())
            index += 1
        return ' '.join(output_list)

    def set_pixel(self,pixel: int , input: RGBdata):
        self.pixels[pixel] = input
        return 0

    def fill(self, input: RGBdata):
        self.pixels = [input] * len(self.pixels)
        return 0

    def ws2812_Data(self):
        outputArray = [0] * (len(self.pixels) * 24)
        index = 0

        for pixel in self.pixels:
            color = pixel.output_bytes()

            for i in range(23, -1, -1):
                byte_index = i // 8
                bit_index = 7 - (i % 8)

                if ((color[byte_index] >> bit_index) & 0x01) == 1:
                    outputArray[index] = 0b11111000  # store 1
                else:
                    outputArray[index] = 0b11100000 # store 0
                index += 1

        return bytes(outputArray)

The important part is the last function called ws2812_Data(self)

SPI

this WS2812 data pact than gets send over SPI with the help of the SPIDEV kernel module at around 6.25 Mhz to 6.75 Mhz


#SPI
spi = spidev.SpiDev()
spi.open(0,0) # open /dev/spidev0.0
spi.mode = 0b00
spi.max_speed_hz = 6000000*2

NeoPixel

leds = Neopixel(1) leds.fill(RGBdata(255, 200, 0, 100)) print(leds.colors()) oldData = RGBdata(0,0,0,0) newData = RGBdata(0,0,0,0)

leds.fill(RGBdata(0,0,0,0)) spi.writebytes2(leds.ws2812_Data())


> please make sure when you use give the docker container access to `spidev0.0`