Reputation: 1846
I have SPI RGB led strip with three wires connection:
– TX1818 driver (manufacturer says “it’s compatible with TM1812, UCS1903, SM16703, WS2811–2815”)
– 12V, 9.3 W/m, 5060, 60/metre
– 3600 pixels, 60 lines, each 1 metre long with 60 pixels
– each 4 lines connected to power supply, 20 line per power supplier
– each line in section connected to power supply in parallel
– all lines have common ground and connected with common data cable
– length of data cable is about 2 metres between controller and matrix
Data cable and common ground connected to RPi 4b (21 GPIO). RPi has Raspberry Pi OS on the board, any software is up to date.
The problem: show() method takes like more than 0.2s to execute (using adafruit-circuitpython-neopixel & rpi_ws281x python libraries, calling after matrix values are updated)
import numpy as np
from PIL import Image, ImageSequence
import time
import board
import neopixel
PIN = board.D21
NUM_PIXELS = 3600
MATRIX_SIZE = 60
ORDER = neopixel.RGB
pixels = neopixel.NeoPixel(
PIN, NUM_PIXELS, auto_write=False, pixel_order=ORDER
)
# USING rpi_ws281x
# from rpi_ws281x import *
# LED_FREQ_HZ = 800000
# LED_DMA = 10
# LED_BRIGHTNESS = 100
# LED_INVERT = False
# LED_CHANNEL = 0
# LED_STRIP = ws.WS2811_STRIP_GRB
# pixels = Adafruit_NeoPixel(NUM_PIXELS, PIN, LED_FREQ_HZ, LED_DMA, LED_INVERT, LED_BRIGHTNESS, LED_CHANNEL, LED_STRIP)
# pixels.begin()
def readImage(path = ‘./some.gif’):
return np.array([np.array(frame.copy().convert('RGB').getdata(),dtype=np.uint8).reshape(frame.size[0] * frame.size[1],3) for frame in ImageSequence.Iterator(Image.open(path))])
image = readImage()
def printFrame(pixels, frame):
for rowIdx in range(NUM_PIXELS):
pixels[rowIdx] = frame[rowIdx]
def animate(pixels, frames):
for frame in frames:
start = time.time()
printFrame(pixels, frame)
pixels.show()
print(time.time() - start) # 0.3+ for adafruit-circuitpython-neopixel
# 0.2+ for rpi_ws281x
time.sleep(1/60)
while True:
animate(pixels, image)
I also have Arduino Mega Rev3, but it’s not enough memory for 3600 pixel.
I thought about splitting matrix by three sections 60x20 (1200 pixels), each connected to separate SPI GPIO but couldn’t find libraries that can handle multiple channels as one.
May be there is something I’m missing? Some hidden settings? Or for RPi some extension should be used for this case, like hat?
Upvotes: 0
Views: 176
Reputation: 78975
The WS2812B (and likely the compatible TX1818) LED strips use a protocol with base frequency of 800kHz.
So if we do the math:
800kHz ÷ 8 bits per color ÷ 3 colors per pixel ÷ 3600 pixels = 9.3 frame/s.
So it the most optimal case, you can display 9.3 frames per second. Thus if pixels.show()
was perfectly optimized, it would take 0.1s (1 frame / 9.3 frame/s).
If you want to achieve 30 or even 60 updates per second, you will need to split it indeed.
Update
The blog post Raspberry Pi 16-channel WS2812 NeoPixel LED driver shows how to drive 16 LED strings in parallel. The Raspberry Pi can easily do this. The code is in C and is probably missing many features of the Adafruit library let alone the Python image library.
Upvotes: 1