In this recitation, we start to build bridges between Processing and Arduino. Basing on the sample given in class, realizing interaction between Processing and Arduino is not a tough task.
exercise 1:
import processing.serial.*; String myString = null; Serial myPort; int NUM_OF_VALUES = 2; /** YOU MUST CHANGE THIS ACCORDING TO YOUR PROJECT **/ int[] sensorValues; /** this array stores values from Arduino **/ float preX=0; float preY=0; void setup() { size(500, 500); background(255); setupSerial(); } void draw() { updateSerial(); printArray(sensorValues); float posX=map(sensorValues[0],0,1023,0,width); float posY=map(sensorValues[1],0,1023,0,height); line(preX,preY,posX,posY); preX=posX; preY=posY; // use the values like this! // sensorValues[0] // add your code // } void setupSerial() { printArray(Serial.list()); myPort = new Serial(this, Serial.list()[ 2 ], 9600); // WARNING! // You will definitely get an error here. // Change the PORT_INDEX to 0 and try running it again. // And then, check the list of the ports, // find the port "/dev/cu.usbmodem----" or "/dev/tty.usbmodem----" // and replace PORT_INDEX above with the index number of the port. myPort.clear(); // Throw out the first reading, // in case we started reading in the middle of a string from the sender. myString = myPort.readStringUntil( 10 ); // 10 = '\n' Linefeed in ASCII myString = null; sensorValues = new int[NUM_OF_VALUES]; } void updateSerial() { while (myPort.available() > 0) { myString = myPort.readStringUntil( 10 ); // 10 = '\n' Linefeed in ASCII if (myString != null) { String[] serialInArray = split(trim(myString), ","); if (serialInArray.length == NUM_OF_VALUES) { for (int i=0; i<serialInArray.length; i++) { sensorValues[i] = int(serialInArray[i]); } } } } }
exercise 2:
import processing.serial.*; int NUM_OF_VALUES = 2; /** YOU MUST CHANGE THIS ACCORDING TO YOUR PROJECT **/ Serial myPort; String myString; // This is the array of values you might want to send to Arduino. int values[] = new int[NUM_OF_VALUES]; PVector[] p = new PVector[100]; void setup() { size(500, 500); background(0); printArray(Serial.list()); myPort = new Serial(this, Serial.list()[ 2 ], 9600); // check the list of the ports, // find the port "/dev/cu.usbmodem----" or "/dev/tty.usbmodem----" // and replace PORT_INDEX above with the index of the port myPort.clear(); // Throw out the first reading, // in case we started reading in the middle of a string from the sender. myString = myPort.readStringUntil( 10 ); // 10 = '\n' Linefeed in ASCII myString = null; } void draw() { background(0); for(int i=0;i<p.length;i++){ p[i] = new PVector(width/2,height/2); } for(int i=0;i<p.length-1;i++){ p[i].x = p[i+1].x; p[i].y = p[i+1].y; } p[p.length-1].x = mouseX; p[p.length-1].y = mouseY; circle(mouseX,mouseY,10); // changes the values values[0] = mouseX; /** Feel free to change this!! **/ values[1]=mouseY; // sends the values to Arduino. sendSerialData(); // This causess the communication to become slow and unstable. // You might want to comment this out when everything is ready. // The parameter 200 is the frequency of echoing. // The higher this number, the slower the program will be // but the higher this number, the more stable it will be. echoSerialData(200); } void sendSerialData() { String data = ""; for (int i=0; i<values.length; i++) { data += values[i]; //if i is less than the index number of the last element in the values array if (i < values.length-1) { data += ","; // add splitter character "," between each values element } //if it is the last element in the values array else { data += "n"; // add the end of data character "n" } } //write to Arduino myPort.write(data); } void echoSerialData(int frequency) { //write character 'e' at the given frequency //to request Arduino to send back the values array if (frameCount % frequency == 0) myPort.write('e'); String incomingBytes = ""; while (myPort.available() > 0) { //add on all the characters received from the Arduino to the incomingBytes string incomingBytes += char(myPort.read()); } //print what Arduino sent back to Processing print( incomingBytes ); }
The only problem I met is when I was trying to send multiple messages from processing to Arduino, I couldn’t declare the total number of the values array, because I thought I could be infinite. But soon I realize the values should be refreshed all the time, so the number of values is simply the number of parameters I want to change during the communication, which are mouseX and mouseY. By figuring this out, I’ve got a deeper understanding about how the data is transported between the two platform.
Interactions in each exercise:
- In Processing Etch A Sketch, how we turn the potentiometer decides on the route of lines draw in the screen. And start point of the next line is the stop point of the last line, so the interaction is a continuous process building on the previous work.
- In the buzzer exercise, different coordinate in the screen relate to different sounds of the buzzer. So that out of the curiosity about what the sound would be like in different position, we continue to move the mouse, so that form an on-going interaction process.
Homework
codes for arduino:
// IMA NYU Shanghai // Interaction Lab // For sending multiple values from Arduino to Processing void setup() { Serial.begin(9600); } void loop() { int sensor1 = digitalRead(4); int sensor2 = digitalRead(2); // keep this format Serial.print(sensor1); Serial.print(","); // put comma between sensor values Serial.print(sensor2); Serial.println(); // add linefeed after sending the last sensor value // too fast communication might cause some latency in Processing // this delay resolves the issue. delay(100); }
codes for Processing:
import processing.serial.*; String myString = null; Serial myPort; int NUM_OF_VALUES = 2; /** YOU MUST CHANGE THIS ACCORDING TO YOUR PROJECT **/ int[] sensorValues; /** this array stores values from Arduino **/ int stateOne=0; int stateTwo=3; int oldOne=0; int oldTwo=3; void setup() { size(500, 500); background(0); setupSerial(); star(width*0.3, height*0.3, 30, 70, 5); star(width*0.7, height*0.7, 80, 100, 40); } void draw() { updateSerial(); printArray(sensorValues); if(sensorValues[0]==1){ if(oldOne==0){ stateOne=1;}else{stateOne=0;} oldOne=stateOne; delay(220); } if(sensorValues[1]==1){ if(oldTwo==3){ stateTwo=4;}else{stateTwo=3;} oldTwo=stateTwo; delay(220); } if(stateOne==0){ fill(255); star(width*0.3, height*0.3, 30, 70, 5);} if(stateTwo==3){ fill(255); star(width*0.7, height*0.7, 80, 100, 40);} if(stateOne==1){ fill(0); star(width*0.3, height*0.3, 30, 70, 5); //fill(255); //star(width*0.7, height*0.7, 80, 100, 40); //if(sensorValues[0]==1){stateOne=stateOne-1;} } if(stateTwo==4){ fill(0); star(width*0.7, height*0.7, 80, 100, 40); //fill(255); //star(width*0.3, height*0.3, 30, 70, 5); //if(sensorValues[1]==1){stateTwo=stateTwo-1;} } // if(stateOne==1){ // if(sensorValues[0]==1){ // stateOne=0;} //} // if(stateTwo==4){ // if(sensorValues[1]==1){ // stateTwo=3;} //} } void star(float x, float y, float radius1, float radius2, int npoints) { float angle = TWO_PI / npoints; float halfAngle = angle/2.0; beginShape(); for (float a = 0; a < TWO_PI; a += angle) { float sx = x + cos(a) * radius2; float sy = y + sin(a) * radius2; vertex(sx, sy); sx = x + cos(a+halfAngle) * radius1; sy = y + sin(a+halfAngle) * radius1; vertex(sx, sy); } endShape(CLOSE); } void setupSerial() { printArray(Serial.list()); myPort = new Serial(this, Serial.list()[ 2 ], 9600); // WARNING! // You will definitely get an error here. // Change the PORT_INDEX to 0 and try running it again. // And then, check the list of the ports, // find the port "/dev/cu.usbmodem----" or "/dev/tty.usbmodem----" // and replace PORT_INDEX above with the index number of the port. myPort.clear(); // Throw out the first reading, // in case we started reading in the middle of a string from the sender. myString = myPort.readStringUntil( 10 ); // 10 = '\n' Linefeed in ASCII myString = null; sensorValues = new int[NUM_OF_VALUES]; } void updateSerial() { while (myPort.available() > 0) { myString = myPort.readStringUntil( 10 ); // 10 = '\n' Linefeed in ASCII if (myString != null) { String[] serialInArray = split(trim(myString), ","); if (serialInArray.length == NUM_OF_VALUES) { for (int i=0; i<serialInArray.length; i++) { sensorValues[i] = int(serialInArray[i]); } } } } }
*bonus
import processing.serial.*; String myString = null; Serial myPort; int NUM_OF_VALUES = 2; /** YOU MUST CHANGE THIS ACCORDING TO YOUR PROJECT **/ int[] sensorValues; /** this array stores values from Arduino **/ int stateOne=0; int stateTwo=3; int oldOne=0; int oldTwo=3; void setup() { size(500, 500); background(0); setupSerial(); } void draw() { updateSerial(); printArray(sensorValues); if(sensorValues[0]==1){ if(oldOne==0){ stateOne=1;}else{stateOne=0;} oldOne=stateOne; delay(220); } if(sensorValues[1]==1){ if(oldTwo==3){ stateTwo=4;}else{stateTwo=3;} oldTwo=stateTwo; delay(220); } if(stateOne==0){ fill(255); pushMatrix(); translate(width*0.3, height*0.3); rotate(frameCount / -100.0); star(0, 0, 30, 70, 5); popMatrix();} if(stateTwo==3){ fill(255); star(width*0.7, height*0.7, 80, 100, 40);} if(stateOne==1){ fill(0); pushMatrix(); translate(width*0.3, height*0.3); rotate(frameCount / -100.0); star(0, 0, 30, 70, 5); popMatrix(); //fill(255); //star(width*0.7, height*0.7, 80, 100, 40); //if(sensorValues[0]==1){stateOne=stateOne-1;} } if(stateTwo==4){ fill(0); star(width*0.7, height*0.7, 80, 100, 40); //fill(255); //star(width*0.3, height*0.3, 30, 70, 5); //if(sensorValues[1]==1){stateTwo=stateTwo-1;} } // if(stateOne==1){ // if(sensorValues[0]==1){ // stateOne=0;} //} // if(stateTwo==4){ // if(sensorValues[1]==1){ // stateTwo=3;} //} } void star(float x, float y, float radius1, float radius2, int npoints) { float angle = TWO_PI / npoints; float halfAngle = angle/2.0; beginShape(); for (float a = 0; a < TWO_PI; a += angle) { float sx = x + cos(a) * radius2; float sy = y + sin(a) * radius2; vertex(sx, sy); sx = x + cos(a+halfAngle) * radius1; sy = y + sin(a+halfAngle) * radius1; vertex(sx, sy); } endShape(CLOSE); } void setupSerial() { printArray(Serial.list()); myPort = new Serial(this, Serial.list()[ 2 ], 9600); // WARNING! // You will definitely get an error here. // Change the PORT_INDEX to 0 and try running it again. // And then, check the list of the ports, // find the port "/dev/cu.usbmodem----" or "/dev/tty.usbmodem----" // and replace PORT_INDEX above with the index number of the port. myPort.clear(); // Throw out the first reading, // in case we started reading in the middle of a string from the sender. myString = myPort.readStringUntil( 10 ); // 10 = '\n' Linefeed in ASCII myString = null; sensorValues = new int[NUM_OF_VALUES]; } void updateSerial() { while (myPort.available() > 0) { myString = myPort.readStringUntil( 10 ); // 10 = '\n' Linefeed in ASCII if (myString != null) { String[] serialInArray = split(trim(myString), ","); if (serialInArray.length == NUM_OF_VALUES) { for (int i=0; i<serialInArray.length; i++) { sensorValues[i] = int(serialInArray[i]); } } } } }