Jim's
Tutorials

Fall 2011
course
navigation

nov 11

Today I futzed around with trying to get the serial input and output more consistent and a few other things.
instead of receiving a list of values with fake values on each end (888, value1, value2, 999), now the arduino sends processing the values in the form of
Processing then checks whether or not the string begins with '<' and ends with '>'. I still think this doesn't catch all cases but it seems like an improvement over my last version.
I cleaned up the code a fair deal and also spliced in some smoothing code to make the noisy bend sensor input be less chaotic.
comparing strings in processing is a little weird. a (capital) String is always defined as having double quotes. single quotes imply a char. I had a bit of trouble finding why my code wasn't working until I stumbled upon this.
Also, Processing deals with list creation sort of strangely:
... float[] smoothlist = new float[smoothmax]; ...
...which is different from how C deals with arrays.
The code still crashes occasionally, not with any consistent pattern. I haven't tried commenting out large chunks yet as a means of diagnostics (I know, that's what I said I'd do). It's a little hard to piece through the error message it keeps sending me (when it does actually crash):
error, disabling serialEvent() for /dev/ttyUSB0 java.lang.reflect.InvocationTargetException at sun.reflect.GeneratedMethodAccessor2.invoke(Unknown Source) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) at java.lang.reflect.Method.invoke(Method.java:597) at processing.serial.Serial.serialEvent(Unknown Source) at gnu.io.RXTXPort.sendEvent(RXTXPort.java:772) at gnu.io.RXTXPort.eventLoop(Native Method) at gnu.io.RXTXPort$MonitorThread.run(RXTXPort.java:1641) Caused by: java.lang.StringIndexOutOfBoundsException: String index out of range: 0 at java.lang.String.charAt(String.java:686) at simple_analog_read_sound_11_10_11.serialEvent(simple_analog_read_sound_11_10_11.java:116) ... 7 more
Maybe we could try to figure out what's going on here. The "String index out of range: 0" looks important.
Here's the code in its present state:
// [Dual] Graphing sketch (modified to graph two inputs and output two sine waves (using Minim) // This program takes ASCII-encoded strings // from the serial port at 9600 baud and graphs them. It expects values in the // range 0 to 1023 [in a comma separated list (example: "10, 20, 30")], followed by a newline, or newline and carriage return // Created 20 Apr 2005 // Updated 18 Jan 2008 // by Tom Igoe // This example code is in the public domain. //MODIFIED BY: Aaron Evan-Browning 11-04-11 import ddf.minim.*; import ddf.minim.signals.*; //import controlP5.*; import processing.serial.*; Minim minim; AudioOutput out; SineWave sine1; SineWave sine2; float sin1Amp = 0.4; //these floats were public. I'm not sure why that was necessary. It was probably for the controlP5 GUI. float sin1Pan = 0; float sin1Freq = 440; float sin2Amp = 0.4; float sin2Pan = 1; float sin2Freq = 330; int sin1Glide = 40; // It freaks out and makes terrible noises if you drop this below about 10. int sin2Glide = 40; // int sin1_multiplier = 1; int sin2_multiplier = 1; //smoothing int smoothmax = 20; //changing this to a high value (say 100) makes the pitch change slower and //the slope of the line much more shallow. float[] smoothlist = new float[smoothmax]; int smoothindex = 0; int i = 0; float smoothlist_sum = 0; Serial myPort; // The serial port int xPos = 1; // horizontal position of the graph int x_size = 750; // x and y canvas sizes int y_size = 500; int switcher = 0; //used for emulation of transparency void setup () { // set the window size: size (x_size, y_size); // this line also had ", P3D" as a parameter of size. We're just using 2 dimensions right now. minim = new Minim(this); // get a stereo line out from Minim with a 2048 sample buffer, default sample rate is 44100, bit depth is 16 out = minim.getLineOut(Minim.STEREO, 2048); // create a sine wave Oscillator, set to 440 Hz, at 0.5 amplitude, sample rate 44100 to match the line out sine1 = new SineWave(440, 0.5, out.sampleRate()); sine2 = new SineWave(330, 0.5, out.sampleRate()); // set the portamento speed on the oscillator to 200 milliseconds sine1.portamento(sin1Glide); sine2.portamento(sin2Glide); // add the oscillator to the line out out.addSignal(sine1); out.addSignal(sine2); // 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'); // set inital background: background(0); //setup smoothing list for bend sensor //for(i = 0; i < SMOOTHMAX; i++){ //smoothlist[i] = 0; //} } void draw () { // everything happens in the serialEvent() } void serialEvent (Serial myPort) { // get the ASCII string: String inString = myPort.readStringUntil('\n'); inString = trim(inString); //surprisingly important. if (inString != null) { println(inString); //println(inString.charAt(0)); //println(inString.charAt(inString.length()-1)); //test whether the string begins with '<' and ends with '>' : if((inString.charAt(0) == '<') && (inString.charAt(inString.length()-1) == '>')){ //println("< and > !!!\n"); // convert to an array of ints, trimming off the '<' and '>' : int incomingValues[] = int(split((inString.substring(1, inString.length()-1)), ",")); print(incomingValues[0]); print(","); println(incomingValues[1]); //scale the output into the bounds of the box. //smoothing for noisy bend sensor input (one for now) //******* smoothindex %= smoothmax; smoothlist[smoothindex] = incomingValues[0]; smoothlist_sum = 0; for(i = 0; i < smoothmax; i++){ smoothlist_sum += smoothlist[i]; } float smoothed_incoming_values_0 = smoothlist_sum / smoothmax; smoothindex += 1; print(smoothed_incoming_values_0); //******* float graphline1 = map(smoothed_incoming_values_0, 0, 1023, 0, height); float graphline2 = map(incomingValues[1], 0, 1023, 0, height); sine1.setFreq(smoothed_incoming_values_0 * sin1_multiplier); //This updates the pitch of the sine wave every time the graph is drawn. sine2.setFreq(incomingValues[1] * sin2_multiplier); // draw the line: switcher += 1; if(switcher % 2 == 1){ stroke(0,0,255); line(xPos, height, xPos, (height - graphline1)); } else{ stroke(0, 255, 0); line(xPos, height, xPos, (height - graphline2)); } // at the edge of the screen, go back to the beginning: if (xPos >= width) { xPos = 0; background(0); } else { // increment the horizontal position: xPos++; } } delay(5); //I raised to 20 and it crashed. I'm not sure why this is. //worth noting, changing this value doesn't change how many separate notes are played. } } void stop() { out.close(); minim.stop(); super.stop(); }
http://cs.marlboro.edu/ courses/ fall2011/jims_tutorials/ aaron/ nov_11
last modified Friday November 11 2011 12:14 am EST