Hey everyone,
I’ve been working on a modular LED video panel system for several months and despite being close to the end I’ve hit a rather large roadblock and I’m at a loss here of what to do next…
The setup here does work great up until maybe 1000 led’s, then the slowdown gets to be quite noticeable.
In Short:
I’m trying to find a way to either optimize sending 11,520 bytes every frame (roughly 690 kbytes a second) over serial OR another protocol or way all together…
I’ve read through the forums in search of other similar issues and have only found this:
[Seeking advice on using TD with display of 7000+ LED Pixels)
A bit more detail on the setup:
Hardware:
- Windows 8
- Teensy 3.1 (arduino based MC with full usb speed serial communication)
- OctoWs2811 (high speed led library for the teensy)
- Adafruit’s Neopixel strips
My setup:
1) Touch designer instance that manages the UI and animations created. This sends the animation data pre mapped in a table (3 rows, r/g/b, the number of columns equal the number of addressable led’s), out through a Touch Out DAT.
2) Second Touch designer instance receives the table dat, and focuses solely on formatting that table data into several compact byte strings that are sent using python and the serial.sendBytes() command.
[i]A side note here, I have to split the led bytes into chunks or packets of 255 or less due to a built in limit that sendBytes has… Is there a way around this limit? I’ve successfully sent entire byte strings using processing and it’s considerably faster (35-45 fps)
3) Byte string is received over serial comport by the teensy, at this point it’s premapped and each 3 values are applied to the led’s 1:1 more or less.
Python Code:
[code]def receive(dat, rowIndex, message, bytes):
print(“asd”)
thisTeensysName = “%s”%(me.name.split(“_”)[0])
panelEnabled = op(“serialCom_enabler”)[“%s_enableLED”%(thisTeensysName)]
if(panelEnabled == 1):
n = op('%s_dataEnd'%(thisTeensysName))
serialConnectorName = "%s_serialConnector"%(thisTeensysName)
serialToggleVal = op("serialCom_enabler")["serialToggle"]
packetSize = int(255)
debugCharLength = 0 # when this is set to one, we build our debug array. If it is set to 2, we debug our time.
if(debugCharLength == 2):
import time
millis0 = int(round(time.time() * 1000))
colorTable_RGB = []
#debugLengthArray = []
executeArray = []
subExArray = []
numSamps = n.numSamples
ch_r = n['r']
ch_g = n['g']
ch_b = n['b']
if(debugCharLength == 2):
millis1 = int(round(time.time() * 1000))
print(" Initialization Stuff TIME: %i"%(millis1 - millis0))
for i in range(0, numSamps):
if((len(subExArray) + 5) < packetSize):
subExArray.append(int(ch_r[i]))
subExArray.append(int(ch_g[i]))
subExArray.append(int(ch_b[i]))
else:
executeArray.append(subExArray)
subExArray = []
subExArray.append(int(ch_r[i]))
subExArray.append(int(ch_g[i]))
subExArray.append(int(ch_b[i]))
executeArray.append(subExArray)
if(debugCharLength == 2):
millis2 = int(round(time.time() * 1000))
print(" Building Exec Arrays TIME: %i"%(millis2 - millis1))
if( int(serialToggleVal) == 1 ):
for subArray in executeArray:
#print(subArray)
#print('op("%s").sendBytes(%s)'%(serialConnectorName, str(subArray).strip('[]')))
exec('op("%s").sendBytes(%s)'%(serialConnectorName, str(subArray).strip('[]')))
if(debugCharLength == 2):
millis3 = int(round(time.time() * 1000))
print(" Serial Send TIME: %i"%(millis3 - millis2))
return[/code]
My next course of action is trying out a couple of FadeCandy’s and using 1 per panel instead of 8 panels per teensy.
I’m not even sure this will remove the bottleneck, as just as many bytes will need to be written, just to different devices… but these devices are highly optimized so worth a shot I guess.
Any ideas, thoughts, criticisms are all hugely appreciated! I really want to get this part ironed out.