WS2812B LED support?



  • Hi

    im thinking of using the WS2812B individually addressable LEDs in my printer for both lighting the printbed as well as signalizing individual printer states by chaning color (running, error…)

    Is there a way to address the data pin on these leds from Duet?

    thanks!

    Chipsa


  • administrators

    Those LEDs don't use a standard protocol, and are currently not supported in firmware.



  • It is possible to drive them from a SPI bus. Here is an example in micropython:

    [[python]]
    # -*- coding: utf-8 -*-
    
    import gc
    import pyb
    
    class WS2812:
        """ Driver for WS2812 RGB LEDs. May be used for controlling single LED or chain  of LEDs.
        """
        buf_bytes = (0x11, 0x13, 0x31, 0x33)
    
        def __init__(self, spi_bus=1, led_count=1, intensity=1):
            """
            """
            self.led_count = led_count
            self.intensity = intensity
            self.disable_irq = True
    
            # prepare SPI data buffer (4 bytes for each color)
            self.buf_length = self.led_count * 3 * 4
            self.buf = bytearray(self.buf_length)
    
            # SPI init
            self.spi = pyb.SPI(spi_bus, pyb.SPI.MASTER, baudrate=3200000, polarity=0, phase=1)
    
            # turn LEDs off
            self.show([])
    
        def show(self, data):
            """ Show RGB data on LEDs.
    
            Expected data = [(R, G, B), ...] where R, G and B are intensities of colors in range from 0 to 255.
            One RGB tuple for each LED.
            Count of tuples may be less than count of connected LEDs.
            """
            self.fill_buf(data)
            self.send_buf()
    
        def send_buf(self):
            """ Send buffer over SPI.
            """
            if self.disable_irq:
                pyb.disable_irq()
                self.spi.send(self.buf)
                pyb.enable_irq()
            else:
                self.spi.send(self.buf)
            gc.collect()
    
        def fill_buf(self, data):
            """ Fill buffer with bytes.
            """
            i = 0
            for byte in self.data_to_bytes(data):
                self.buf[i] = byte
                i += 1
    
            # turn off the rest of the LEDs
            while i < self.buf_length:
                self.buf[i] = self.buf_bytes[0]
                i += 1
    
        def data_to_bytes(self, data):
            """ Convert data to bytes.
    
            Note: Order of colors is changed from RGB to GRB because WS2812 LED has GRB order of colors.
            """
            for red, green, blue in data:
                for byte in self.color_to_bytes(green):
                    yield byte
                for byte in self.color_to_bytes(red):
                    yield byte
                for byte in self.color_to_bytes(blue):
                    yield byte
    
        def color_to_bytes(self, color):
            """ Yields 4 buffer bytes representing color value (1 byte for each 2 bits).
            """
            color = int(color * self.intensity)
            for i in range(4):
                yield self.buf_bytes[(color & 0xC0) >> 6]
                color <<= 2
    
    def main():
        ring = WS2812(spi_bus=1, led_count=16)
    
        data = [
            (24, 0, 0),
            (0, 24, 0),
            (0, 0, 24),
            (12, 12, 0),
            (0, 12, 12),
            (12, 0, 12),
            (24, 0, 0),
            (21, 3, 0),
            (18, 6, 0),
            (15, 9, 0),
            (12, 12, 0),
            (9, 15, 0),
            (6, 18, 0),
            (3, 21, 0),
            (0, 24, 0),
            (8, 8, 8),
        ]
    
        ring.show(data)
    
    if __name__ == "__main__":
        main()
    [/i][/i]
    

  • administrators

    As in the oled thread, the easiest approach would be to use a little Arduino or equivalent to switch between the display chip and the Duet.


Locked
 

Looks like your connection to Duet3D was lost, please wait while we try to reconnect.