Communication Examples Broken in Processing

Both the Arduino example sketches VirtualPixel and Graph, appear to be broken in Processing. They throw "array index out of bounds" errors - I may not have that error message wording precisely correct.

This doesn't happen every time but more often than not. There seems to be some condition of serial input, that raises the error condition.

Anyone know if Processing has changed their Serial class, since the examples were written?

paulb

If the first character that the serialEvent sees is a NEWLINE - with nothing else in the buffer, then the function will fail at the buff trim. If the only two characters in the buffer are NEWLINE, CR, then the function fails at ParseInt. (BTW - you really have to dig on the processing site for any info on parseInt method - I still can't find code for it.)

The lack of characters in the buffer seems to happen almost every time on the first function call to Serial.available, so I think there is something in the Processing functions that favors it. A little defensive programming isn't a bad thing though.

Here's one fix

void serialEvent(int serial)
{
  if (serial != NEWLINE) {
    // Store all the characters on the line.
    buff += char(serial);
  } else {
    // The end of each line is marked by two characters, a carriage
    // return and a newline.  We're here because we've gotten a newline,
    // but we still need to strip off the carriage return.

// this is the fix - not in original code
 if (buff.length < 2){
buff = "";             // clear out the buffer
port.clear             // clear out serial buffer
return;                   // return to avoid parseInt
}
// end fix 

    buff = buff.substring(0, buff.length()-1);
    
    // Parse the String into an integer.  We divide by 4 because
    // analog inputs go from 0 to 1023 while colors in Processing
    // only go from 0 to 255.
    int val = Integer.parseInt(buff)/4;
    
    // Clear the value of "buff"
    buff = "";
    
    // Shift over the existing values to make room for the new one.
    for (int i = 0; i < 63; i++)
      values[i] = values[i + 1];
    
    // Add the received value to the array.
    values[63] = val;
  }
}

Is this the examples that come with Arduino 0015? Tom Igoe rewrote the communication examples and Processing counterparts. Do you still see the problem in the revised examples on the website?

Yes they're from 15. Tom may not have tested, or he may have just been lucky. Or processing may have changed a function a bit since he tested. I think I wrote the "hacking a Processing sketch" tutorial last year - I guess there's a date on change log, and the code worked fine then.

The bug only happens on first call to Serial.available (in processing) so could be a number of things that changed I imagine. As I said in my post, it can happen at any time the buffer has NewLine char but no other data.

BTW - it might not be that idea to have more error checking in the routines - but commented out. If there is a noisy serial line (e.g. radios) and a non-numeric char gets through - ParseInts gags.

Please post links to ParseInts source if you know it. The Processing guys apparently like to keep some things secret too.

Paul

Did you try the ones on the website? I think they've been updated not to have this problem.

BTW, parseInt() is built in to Java so there's no point in asking the Processing guys for the source code to it.

I see that the code has been changed on example page.
I'll try them out.

In the code below though (from virtual color mixer), what calls SerialEvent?

import processing.serial.*;

float redValue = 0;        // red value
float greenValue = 0;      // green value
float blueValue = 0;       // blue value

Serial myPort;

void setup() {
  size(200, 200);

  // List all the available serial ports
  println(Serial.list());
  // I know that the first port in the serial list on my mac
  // is always my  Arduino, so I open Serial.list()[0].
  // Open whatever port is the one you're using.
  myPort = new Serial(this, Serial.list()[0], 9600);
  // don't generate a serialEvent() unless you get a newline character:
  myPort.bufferUntil('\n');
}

void draw() {
  // set the background color with the color values:
  background(redValue, greenValue, blueValue);
}

void serialEvent(Serial myPort) { 
  // get the ASCII string:
  String inString = myPort.readStringUntil('\n');

  if (inString != null) {
    // trim off any whitespace:
    inString = trim(inString);
    // split the string on the commas and convert the 
    // resulting substrings into an integer array:
    float[] colors = float(split(inString, ","));
    // if the array has at least three elements, you know
    // you got the whole thing.  Put the numbers in the
    // color variables:
    if (colors.length >=3) {
      // map them to the range 0-255:
      redValue = map(colors[0], 0, 1023, 0, 255);
      greenValue = map(colors[1], 0, 1023, 0, 255);
      blueValue = map(colors[2], 0, 1023, 0, 255);
    }
  }
}

http://processing.org/reference/libraries/serial/serialEvent_.html