Hello all
I am working on a 3D pov music visualizer.
But I have found the delay between processing and the running display is too large, for my purposes. I'm not sure what part of my code is the bottleneck, Can you please help?
right now there is about an 500ms delay between changing the display data at the processing end and actually seeing it. That will make a crappy music visualizer.
What could be causing the problem
The display driving;
Yes I am bitbanging the shift registers; my impression is the pin toggling is more optimised for the hardware then using the arduino emulated stuff. But as I don't even have much experience with arduino code, I don't have time to go into using native code and adapting the sd card library optimised for teensy.
I am using a hardware interrupt to stabilize the image. I decided not to use a timer interrupt to power the display, as the timer libraries I looked at were in the millisecond range(not accurate enough?) Plus I don't think the way I have done is too less efficient.
I use if statements and track the microseconds, and within each of those times I only update the display once; so thats not causing the bottle neck.
Communication;
I have gone through all of the post about the work Paul has done on improving the serial receiving. So I made sure that I followed the suggestions of having a protocol where the teensy never asks for data, and trying to group together data within the 64 byte packets used. I am using serial readbytes and the latest update of teensyduion so I should be taking advantage of the optimizations recently done to it. Meaning I should be able to get, what is it about a megabyte per second and 50% cpu usage? That is an impressive data rate, so I must be doing something wrong?
What communication is taking place;
I am only sending 5 bytes at this stage, that should be no problem. This five is controlling 10 time sections with a bar value of 0-15. So is it
Why it can't be the display code;
The speed of the display has no effect and I have a very large head room for time resolution, with the current set up I could be getting 100*+ easy+
Is there a better way? or is this the reality?
Would doing the fft on the teensy give better performance? Or I am I going to have to take the analogue approach?
Sorry for the long post but, I have to post all the code as the problem could be anywhere.
////////// TEENSY CODE////////////////
//////////// Processing code//////////////////
I used to copy for forum tool.......
I am working on a 3D pov music visualizer.
But I have found the delay between processing and the running display is too large, for my purposes. I'm not sure what part of my code is the bottleneck, Can you please help?
right now there is about an 500ms delay between changing the display data at the processing end and actually seeing it. That will make a crappy music visualizer.
What could be causing the problem
The display driving;
Yes I am bitbanging the shift registers; my impression is the pin toggling is more optimised for the hardware then using the arduino emulated stuff. But as I don't even have much experience with arduino code, I don't have time to go into using native code and adapting the sd card library optimised for teensy.
I am using a hardware interrupt to stabilize the image. I decided not to use a timer interrupt to power the display, as the timer libraries I looked at were in the millisecond range(not accurate enough?) Plus I don't think the way I have done is too less efficient.
I use if statements and track the microseconds, and within each of those times I only update the display once; so thats not causing the bottle neck.
Communication;
I have gone through all of the post about the work Paul has done on improving the serial receiving. So I made sure that I followed the suggestions of having a protocol where the teensy never asks for data, and trying to group together data within the 64 byte packets used. I am using serial readbytes and the latest update of teensyduion so I should be taking advantage of the optimizations recently done to it. Meaning I should be able to get, what is it about a megabyte per second and 50% cpu usage? That is an impressive data rate, so I must be doing something wrong?
What communication is taking place;
I am only sending 5 bytes at this stage, that should be no problem. This five is controlling 10 time sections with a bar value of 0-15. So is it
Why it can't be the display code;
The speed of the display has no effect and I have a very large head room for time resolution, with the current set up I could be getting 100*+ easy+
Is there a better way? or is this the reality?
Would doing the fft on the teensy give better performance? Or I am I going to have to take the analogue approach?
Sorry for the long post but, I have to post all the code as the problem could be anywhere.
////////// TEENSY CODE////////////////
const int data = 3;
const int latch = 2;
const int clock = 4;
const int red = 23;
const int green = 22;
const int blue = 21;
//*settings
const int real_timeResolusion = 10;
const int timeResolusion = (10+(2*(( real_timeResolusion ))));
const int layerNum = 1;// starts at one to leave room for the buffer
byte displayData[(real_timeResolusion)/2][layerNum]; // time res /2 because there are two time sections stored per byte
int primaryKey[layerNum];// used to shift the visulization time layers, not the pov time sections
byte incomingByte;
unsigned long period = 100000;
volatile unsigned long periodStart;
volatile boolean interupt = false;
int led=13;
volatile unsigned long oldTime;
void setup() {
**for(int c=0; c<layerNum ;c++)
**{
****primaryKey[c]*=*c;
**}
**pinMode(5,INPUT);
**pinMode(data,OUTPUT);
**pinMode(latch,OUTPUT);
**pinMode(clock,OUTPUT);
**pinMode(red,OUTPUT);
**pinMode(green,OUTPUT);
**pinMode(blue,OUTPUT);
**pinMode(led,OUTPUT);
**attachInterrupt(5, checkPoint, RISING);
**oldTime=*micros();
//*common*colour*control*I*will*take*advantage*of*this*later,*for*now*this*is*just*so*I*can*see*whats*going*on
**digitalWrite(green,HIGH);
**Serial.begin(12000000);
}
int byteCnt =0;
void checkPoint()
{
**if(interupt==false)
**{
****interupt=true;
**}
**if((micros()-oldTime)>1000) // only had a reed switch to work with, it double taps where it is; this is easier than moving it
**{
****//period = micros()-oldTime; // updates the period every rotation,
****// disabled because the period didn't stay stable; will come back to this later with averaging, or working backwards
****oldTime=*micros();
****periodStart*=*micros();// a refrence to find what time section is active
**}
}
int sectionCnt=0;
void loop() {
**noInterrupts();
**if(interupt==true || micros()>periodStart && micros()<(periodStart+(period)))
**{
****int currentSection = (ceil((micros()-periodStart)/(period/timeResolusion)))-2;
****if(currentSection > sectionCnt+1)// only allows a single update per time segment
****{*
******digitalWrite(latch,LOW);
******int loopLength =(layerNum-1);// to allow setting to a single layer
******if(loopLength == 0)
******{
********loopLength=1;*
******}
******for(int c=0; c<loopLength ;c++)
******{
********for(int b =0; b<2; b++)
********{
**********for(int a=0; a<8; a++)// this loops through all 8 bits for each shift register
**********{***
************digitalWrite(clock,LOW);
************int ledNum = a; // give the 0-15 led number to for the current branch, checked working
************if(b==1)
************{
**************ledNum*=*8+a;
************}***
************int temp = ceil(currentSection/2);// works out what byte the 4 bit value is within
************int val = displayData[temp-1][c];// collects the data
************if((currentSection % 2) == 0)// spliting the bye into its two sections,
************{
**************//removes the top 4 bits, as only the bottem 4 are needed
**************val*=*val*<<*4;
**************val*=*val*>>*4;*******
************}****
************else
************{
**************//only want the top four bits, push them into the first 4 bits to read as the 0-15 values wanted
**************val*=*val*>>*4;
************}
************// writes the state to the shift register,
************if(ledNum >= val)
************{
**************digitalWrite(data,LOW);
************}
************else
************{
**************digitalWrite(data,HIGH);
************}*
************digitalWrite(clock,HIGH);
**********}
********}
******}
******digitalWrite(latch,HIGH);
******sectionCnt*=*currentSection;
******if(sectionCnt <= timeResolusion)
******{
********sectionCnt=0;
******}
****}
****if(interupt==true)// starts the rotation by updating the time refrence
****{
******periodStart*=*micros();
******interupt=false;
****}
**}
**interrupts();
**int numOf_bytes = (real_timeResolusion/2);
**if (Serial.available() >= numOf_bytes)
**{*
****
****while(byteCnt < numOf_bytes)
****{
******int n = Serial.readBytes((char *)displayData[0], numOf_bytes-byteCnt);
******byteCnt*+=*n;*
****}
****byteCnt=0;
****int loopLength =(layerNum-1);// to allow setting to a single layer, checked
****if(loopLength == 0)
****{
******loopLength=1;*
****}
****for(int i=0; i< layerNum ;i++) // this changes the primary keys to move to the next frame check boundry, checked
****{*************
******primaryKey++;
******if(primaryKey >= layerNum)// check
******{
********primaryKey*=*0;*
******}
****}
**}
}
//////////// Processing code//////////////////
import*processing.serial.*;
Serial myPort;
void setup()
{
**size(200, 200);
**myPort*=*new Serial(this, "COM6", 12000000);
}
int time =50;
void draw() {
**
**for(int i = 0; i< 15; i++)
{*
**for(int a =0; a<4;a++)
**{
****myPort.write(i);
**}
*delay(time);
}
*
delay(time*2);
*for(int i = 15; i> 0; i--)
{*
**for(int a =0; a<4;a++)
**{
****myPort.write(i);
**}
*
*delay(time);
}
}
void keyPressed()
{
*
***if (keyCode == UP)
****{
******time*+=*10;
****}
**
******if (keyCode == DOWN)
****{
******time*-=*10;
****}
}
I used to copy for forum tool.......