I am doing a large scale LED project using processing and STM32.
processing converts the video data into led pixel data and sends them to STM32 controllers.
each controller controls about 1200 LEDs.
each controller is connected to computer using a USB CDC serial port.
i was successfully able to send LED_DATA to one STM32 controller and display it on LED screen.
But when i will be using multiple serial ports(lets say 12) there would be delay between the time at which data is written to first serial and the 12th one.
I wanted to know
1)how to measure this delay.
2)how to send data simultaneously to all serial ports.
If anyone needs to the see the code i can post it.
i still don’t understand what you are saying.
is C the serial port and p the led data.
this is my current code:
Serial myPort; // The serial port
byte[] leddata = new byte[3600]; // 3 byte for each LED's RGB data
void draw()
{
myPort.write(leddata);
}
the code has all the setup and draw loop not shown here.
this is one leddata array.
i have multiple arrays and multiple ports and i want to write data to each port simultaneously,
because if i do this
Serial myPort1; // The serial port
Serial myPort2;
byte[] leddata1 = new byte[3600]; // 3 byte for each LED's RGB data
byte[] leddata2 = new byte[3600];
void draw()
{
myPort1.write(leddata1);
myPort2.write(leddata2);
}
there would be a delay between controller one and controller two receiving data.
i don’t want that delay to be there.
Serial[] myPorts;
byte[][] leddata;
int DEVICES = 12;
int LEDS = 3600;
void setup(){
myPorts = new Serial[DEVICES];
// assign ports
leddata = byte[DEVICES][LEDS];
// import
}
…then one thing to do might be to walk across your led data in an outer loop, and send only part of it – a subrange of LEDs, like 100, or 300, or 600 - to each device in the inner loop. Then, in the outer loop, advance to the next chunk, and send that chunk to each of the 12 devices in the inner loop. And so on, until your outer loop has moved through all 3600 LEDs, and the inner loop has finished all 12 devices for the last chunk.
int chunk = 100;
for(int i=0; i<3600; i=i+chunk){
for(int j=0; j<DEVICES; j++){
// send a chunk of leddata[j][i]-to-[j][i+chunk-1] to that device
}
}
Maybe people with more serial experience will have additional feedback on whether that approach is worth trying.
A core issue is, you can either send that much information with your hardware in real time or your can’t. If you can’t, there will be delay – you just have to decide where the delay will happen. You can synchronize on scan lines, or on chunks, or on whole frames – so synchronizing on scan lines or chunks will drop your frame drawing time, but the frames will be in sync. You can’t send a million cars between two cities, and then a million trucks, and have them all arrive at the same time because: roads. However, you can send 100 of each in repeated turns and the arrivals of both will remain more or less constant.
Some other alternatives:
send less data
use faster hardware
pre-render and cache the data locally so that it doesn’t have to be sent over the wire, then synchronize playback from local data based on shared clock or sending simple frame data over the wire
have multiple playing computers that are synchronized, each one feeding data to only one (or fewer) serial ports
experiment with multi-threaded solutions using thread() or java Thread – although if this is a bandwidth issue then results will probably be little different from the chunk solution I already suggested.
I would love to see people with more serial experience weigh in on this – particularly re:multiple devices and bandwidth. But if it is bandwidth, I think there is no magic bullet.
What baud rate are you using for communication? How fast are you expecting?
At 115000 bit/s
10 bits per byte (1 start, 1 stop, 8 data)
x3600 bytes = ~1/3 sec per device
To measure the time, you could grab millis() before then after sending each frame.
Perhaps have the STM32 reply when complete.
so when i connect the device using usb micro to the computer it shows up as COM port (because of the drivers)but is actually a USB 2.0 device capable of 12Mbits/s( i guess) communication speed.
I tested the time gap it was around 30ms, from STM32 initiating the request to receving the entire array on the controller.
import processing.serial.*;
Serial myPort; // The serial port
byte[] buff = new byte[3600];
int i;
int k=0,init=0;
String report = "!";
String ack = "0";
String request = "0";
String incoming ;
void setup()
{
printArray(Serial.list()); // List all the available serial ports
myPort = new Serial(this, Serial.list()[0], 9600);// the speed stated here does not matter
// the serial port works at full 12Mbit/s speed
//fill the transmit buffer
for(i=0;i<3600;i++)
{
buff[i] = (byte)k;
k++;
if(k==256)
k=0;
}
//check the connecion with stm32 controller
while(init==0)
{
myPort.write(report);
delay(1000);
while (myPort.available() > 0)
{
ack = myPort.readString();
}
println("checking");
println(ack);
if(ack.equals("OK") == true)
{
println("connection to STM32 is successful");
init = 1;
}
}
}
void draw()
{
while (myPort.available() > 0)
{
request = myPort.readString();//request generated by STM32 for ledData
}
if(request.equals("<") == true)
{
//for(i=0;i<3600;i++)
// {
myPort.write(buff);
// }
request = "0";
println("snet one frame data");
delay(1000);
while (myPort.available() > 0)
{
incoming = myPort.readString();//the time delay in Millisecond calculated by the STM32
println(incoming);
}
}
}
I imagine you would want some kind of producer/consumer setup.
Producer: prepares a frame, adds it to a queue
Consumer: waits for request on USB, pulls from the queue, writes frame to USB
Need to have a pair to handle each of the STM32’s.
Shared resources may be troublesome… though reading from memory should be less of problem.
Maybe you could get away with a single producer for the lot.
Are you generating the data from individual frames of video or would one STM32 control a portion of the same video?
Maybe a solution is to send all your data like you are doing but tell your STM32 to wait for a signal to actually use that data.
So then you can send a “go” to all your devices one after another, but since it will be very little information, it would be fast enough to appear in sync.
Each STM32 has an internal counter which knows when all the data has arrived(since the data send to each controller is fixed 3600 bytes)
Each controller knows when they have received the entire data.
but is there a way to know which one will receive the entire data last.
if there is then i can make the that one create a signal for all other controllers to start displaying the data.
I am more concerned about the frame rate.
at 30ms per controller I am getting a frame rate of 30fps theoretical .
i will having almost 20 controllers which reduces the frame rate.
so I wanted a way so that each one can receive the data at the same time.
If you have a counter for the data then send all the data except one to each controller.
When it is done, send the last data to each controller. It should be fast enough so they all receive that last data almost at the same time and thus make it look like they are in sync