Problem Sending Colors from an Audio Visualizer to Arduino

Sorry in advance for the length of my question; I want to provide proper context. I wrote an audio visualization program in Java that (in addition to making "pretty pictures" based off of the amplitudes of different frequencies being sent from the computer) sends a color to an Arduino Uno based off of the sound it is "hearing." I know the algorithm for generating this color is functional (in addition to sending that color to the Arduino, it also changes the color of an item on the DrawingCanvas). When the color is sent to the Arduino (as 3 bytes representing red, green, and blue), though, the physical LEDs don't respond correctly (they become a random color for a few seconds then switch to another random color for a bit (the behavior is hard to describe, but certainly not desired!)). I have been able to send colors to the Arduino using the same client program, but when the audio visualizer sends colors by the same method, this odd behavior occurs. My thought is that, because the audio visualizer sends color profiles dozens of times per second, the Arduino might be getting overloaded with data. Is that possible?

Here is the relevant pieces of code from the client, the audio visualizer, and the Arduino:

Client:

public class Client extends WindowController{
        //USB is a class I wrote that extends PApplet. Unless baud rates are the issue, I don't think we need to worry about this.
	static USB port = new USB("COM3", 9600);
	byte[] code = new byte[LENGTH];
	static byte killTerm = -100;
	private AudioVisualizer vis;
	
	public void begin()
	{
		resize(1500,900);
		for (int k=0;k<LENGTH;k++){
			code[k]=killTerm;
		}
		vis = new AudioVisualizer(10,30,1200,300,canvas);
	}
	
	public void onMouseClick(Location point)
	{
		runVis = !runVis;
		if(runVis){
			vis.start();
			code[0]=-22;
			sendCodeUSB(code);
		}
		else
			vis.stop();
		
	}
	
	
	public static void sendCodeUSB(byte[] code){
		for (int k=0; k<code.length; k++){
			port.writeProfile(code[k]);
		}
	}
	
}

AudioVisualizer

public class AudioVisualizer implements Runnable{
	Thread thread = null;
	DrawingCanvas canvas;

	
	
	byte[] code = new byte[3];
	
	
	private int xPos;
	private int yPos;
	private int width;
	private int height;
	private int scale;
	private Location topLeft;
	private Location bottomRight;
	private FilledRect background;
	
	private int brightness =0;
	
	private boolean needOff = false;
	
	
	
	public AudioVisualizer(int x, int y, int w, int h, DrawingCanvas myCanvas){
		canvas=myCanvas;
		xPos=x;
		yPos=y;
		topLeft = new Location (xPos,yPos);
		bottomRight = new Location (xPos+width, yPos+height);
		width=w;
		height=h;
		background = new FilledRect(topLeft,width,height,canvas);
		background.setColor(Color.BLACK);
		initiateMonitor();
		scale = height/30;
		
	}
	
	public void start() {
	    if (thread == null) {
	      thread = new Thread(this);
	      thread.start();
	    }
	}
	
	public void stop(){
		thread=null;
	}
	
	 public void run() {
		    while (thread != null) {
		      try {
		        Thread.sleep(40);
		      } catch (InterruptedException e) {
		      }
		      graphAmps();
		    }
		    thread = null;
		  }
	
	
	public void graphAmps(){
		//there is a whole bunch of stuff here that is unrelated that I removed. 
                //basically, just know that graphAmps() calls avgColors()
		avgColors();
		
	}
	
	public void avgColors(){
		//there is stuff here that generates avgRed,avgGreen,and avgBlue (known to be working)
		Color c = new Color (avgRed,avgGreen,avgBlue);
		background.setColor(c);
		
                //so we dont spam the arduino more than we need to
		if(avgRed>10 || avgGreen>10 || avgBlue>10){
			sendArduinoColor(c);
			needOff = true;
		}
		else if (!(avgRed>10 || avgGreen>10 || avgBlue>10) && needOff){
			sendArduinoColor(c);
		}
		
	}
	
	
	
	public void sendArduinoColor(Color c){
		//takes the color and sets code = an array of 3 bytes with values from 0-100 (100 is the highest brightness I ever want the LEDs to be)
               //I am sure this is done correctly so I've left it out.
		constrainArduinoColor(c);
	       //calls the static method from the client and passes in the byte array with the rgb values
		Client.sendCodeUSB(code);
	}
	
}

Arduino

#include <EEPROM.h>

int redPin = 11;
int bluePin = 10;
int greenPin = 9;

//declared here for debugging ease of access
int r;
int g;
int b;

//are we going through the Spectrum Cycle loop for the first time?
boolean sclFirstTime = true;

//temporary initialization

boolean waiting = true;
int index = 0;
const int LENGTH = 20;
byte profile[LENGTH];
byte avProfile[3];
byte killTerm = -100;
byte audioVisualizationCode = -22;



void setup() {
 //start the serial communication
  Serial.begin(9600);
 //initialize the profile to all -1 values
 clearProfile();
}

void loop() {
  //if there is nothing over serial and nothing is in the EPROM, we are waiting
  if (!eepromProfileAvailable() && Serial.available()==0){
    waiting = true;
  }

  //if there is something in EEPROM and nothing over Serial, we aren't waiting and load the EEPROM profile
  else if (eepromProfileAvailable() && Serial.available()==0){
    waiting = false;
    loadEEPROMProfile();
    //load the EPROM color profile into the array
  }

  //if something enters over Serial, we aren't waiting, clear the profile, and load the new profile with the serial info
  else if (Serial.available()>0){
      waiting = false;
      clearProfile();
      while (Serial.available()<LENGTH) {} // Wait 'till there are LENGTH number of Bytes waiting
      for(int n=0; n<LENGTH; n++){
      profile[n] = Serial.read(); // place them in the profile.
      }
      Serial.flush(); //clear out the serial to prep for next time
    
  }

  //if we have a profile (either from EEPROM or Serial), save it, check for special codes (if found, apply the effect), 
  //and if there are no special codes, the profile is a static color profile, and set LEDS to that.
  if(!waiting){
    saveEEPROMProfile(); //omitted but working
    
    if (profile[0]==101){
      while (Serial.available()==0)
      spectrumCycle(); //omitted but working
    }
    else if (profile[0]==-22){
      audioVis();
    }
    else{
    anodeSafteyOut(redPin,profile[0]);
    anodeSafteyOut(greenPin,profile[1]);
    anodeSafteyOut(bluePin,profile[2]);
    }
  }
  
}

//a bunch of preset color effects omitted

//we are using a common Anode LED, so low value is 255 instead of 0
void anodeSafteyOut(int pin, int c){
  if(c>=0){
   c = 255 - c;
    //as a saftey measure because there are no resistors (yes, I know im breaking an intergalactic law by not using any), make sure we aren't writing something too bright
   if (c>=155){
   analogWrite(pin,c);
   }
  }
}


//wait for 3 bytes to come in, assign them to the avProfile, set the colors to that, do it again
[b]//THIS IS PROBABLY WHERE THE PROBLEM IS[/b]
void audioVis(){
  while (Serial.available()<3);
    for (int k=0;k<3;k++)
      avProfile[k]=Serial.read();
  anodeSafteyOut(redPin,avProfile[0]);
  anodeSafteyOut(greenPin,avProfile[1]);
  anodeSafteyOut(bluePin,avProfile[2]);

  audioVis();
}

So that's a lot, and I've left a lot out that I didn't think was necessary, though I'm happy to provide the full programs if needed. Thanks for your help!

Your code:

      while (Serial.available()<LENGTH) {} // Wait 'till there are LENGTH number of Bytes waiting
      for(int n=0; n<LENGTH; n++){
      profile[n] = Serial.read(); // place them in the profile.
      }

might be making the task harder than it should be. Is there some kind of sentinel, or marker, that represents the end of the data stream? Often a newline, comma, or null is the sentinel. If a newline is the sentinel, make profile[] 21 elements and try:

   int charsRead;

   // more code...

      while (Serial.available()<LENGTH) {
           charsRead = Serial.readBytesUntil('\n', profile, 20);
           profile[charsRead] = '\0';                                        // profile is a string or null-terminated array
      }

If there is no sentinel, it seems you could add one to your port.writeProfile[] code to add one and then use that in place of the newline character assumed above.

very interesting. I like the thought of using something along those lines when the arduino is in the audiVis mode...

Update: So I set up a "simplest scenario" with excess code removed on both the java and arduino sides and raised the minimum threshold amplitude for color transmission a bit and got mostly desired behavior from the program (I need to fine tune the equalizers and the color generation algorithm). I'm now going to add back in the other code segments one at a time and see where the issue returns so I know where to apply fixes. I'll keep you posted. I'll definitely want to set up a sentinel.