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
-
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]
-
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.