Exercise 1: Make a Processing Etch-A-Sketch
code:
Arduino
// IMA NYU Shanghai // Interaction Lab // For sending multiple values from Arduino to Processing void setup() { Serial.begin(9600); } void loop() { // to send values to Processing assign the values you want to send //this is an example int sensor1 = analogRead(A0); int sensor2 = analogRead(A1); // int sensor3 = analogRead(A2); // send the values keeping 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); // end of example sending values }
Processing
// IMA NYU Shanghai // Interaction Lab // For receiving multiple values from Arduino to Processing /* * Based on the readStringUntil() example by Tom Igoe * https://processing.org/reference/libraries/serial/Serial_readStringUntil_.html */ import processing.serial.*; int NUM_OF_VALUES_FROM_ARDUINO = 2; /** YOU MUST CHANGE THIS ACCORDING TO YOUR PROJECT **/ int sensorValues[]; /** this array stores values from Arduino **/ String myString = null; Serial myPort; void setup() { size(500, 500); setupSerial(); } void draw() { background(229,187,129); getSerialData(); printArray(sensorValues); noStroke(); fill(161,23,21); float val1 = sensorValues[0]; float val2 = sensorValues[1]; circle(val1, val2, 100); } void setupSerial() { //printArray(Serial.list()); myPort = new Serial(this, Serial.list()[ 1 ], 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_FROM_ARDUINO]; } void getSerialData() { 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_FROM_ARDUINO) { for (int i=0; i<serialInArray.length; i++) { sensorValues[i] = int(serialInArray[i]); } } } } }
I didn’t get into trouble when I let the ball move. But when I change it into a line, the problem of background happened again. I didn’t find this problem and tried to modify other elements. Finally, I found that I need to delete the background() in the void draw to let the line appear on the screen.
code
Processing
// IMA NYU Shanghai // Interaction Lab // For receiving multiple values from Arduino to Processing /* * Based on the readStringUntil() example by Tom Igoe * https://processing.org/reference/libraries/serial/Serial_readStringUntil_.html */ import processing.serial.*; int NUM_OF_VALUES_FROM_ARDUINO = 2; /** YOU MUST CHANGE THIS ACCORDING TO YOUR PROJECT **/ int sensorValues[]; /** this array stores values from Arduino **/ String myString = null; Serial myPort; float x = random (width); float y = random (height); void setup() { size(500, 500); setupSerial(); background(229,187,129); } void draw() { getSerialData(); printArray(sensorValues); float lx = map ( sensorValues[0],0,1023,0,500); float ly = map ( sensorValues[1],0,1023,0,500); stroke(161,23,21); strokeWeight(3); line (lx,ly, x, y); x = lx; y = ly; } void setupSerial() { //printArray(Serial.list()); myPort = new Serial(this, Serial.list()[ 1 ], 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_FROM_ARDUINO]; } void getSerialData() { 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_FROM_ARDUINO) { for (int i=0; i<serialInArray.length; i++) { sensorValues[i] = int(serialInArray[i]); } } } } }
Exercise 2
Code
Arduino
#include <Servo.h> #define NUM_OF_VALUES_FROM_PROCESSING 3 /** YOU MUST CHANGE THIS ACCORDING TO YOUR PROJECT **/ Servo myservo; /** DO NOT REMOVE THESE **/ int tempValue = 0; int valueIndex = 0; /* This is the array of values storing the data from Processing. */ int processing_values[NUM_OF_VALUES_FROM_PROCESSING]; void setup() { Serial.begin(9600); myservo.attach(9); } void loop() { getSerialData(); if (processing_values[0] == 1){ myservo.write(180); delay(100); }else{ myservo.write(0); } } //receive serial data from Processing void getSerialData() { while (Serial.available()) { char c = Serial.read(); //switch - case checks the value of the variable in the switch function //in this case, the char c, then runs one of the cases that fit the value of the variable //for more information, visit the reference page: https://www.arduino.cc/en/Reference/SwitchCase switch (c) { //if the char c from Processing is a number between 0 and 9 case '0'...'9': //save the value of char c to tempValue //but simultaneously rearrange the existing values saved in tempValue //for the digits received through char c to remain coherent //if this does not make sense and would like to know more, send an email to me! tempValue = tempValue * 10 + c - '0'; break; //if the char c from Processing is a comma //indicating that the following values of char c is for the next element in the values array case ',': processing_values[valueIndex] = tempValue; //reset tempValue value tempValue = 0; //increment valuesIndex by 1 valueIndex++; break; //if the char c from Processing is character 'n' //which signals that it is the end of data case '\n': //save the tempValue //this will b the last element in the values array processing_values[valueIndex] = tempValue; //reset tempValue and valueIndex values //to clear out the values array for the next round of readings from Processing tempValue = 0; valueIndex = 0; break; } } }
Processing
import processing.serial.*; int NUM_OF_VALUES_FROM_PROCESSING = 1; int processing_values[] = new int[NUM_OF_VALUES_FROM_PROCESSING]; Serial myPort; String myString; float x; float speedX; float s; void setup() { fullScreen(); background(0); speedX = 5 ; setupSerial(); } void draw() { background(147,224,255); noStroke(); fill(255,66,93); circle (x, 350, 100); x= x+speedX; if (x > width || x < 0) { speedX = -speedX; } if (x > width) {// hit the left wall processing_values[0] = 1; } else { processing_values[0] = 0; } sendSerialData(); } void setupSerial() { printArray(Serial.list()); myPort = new Serial(this, Serial.list()[1], 9600); myPort.clear(); myString = myPort.readStringUntil( 10 ); // 10 = '\n' Linefeed in ASCII myString = null; } void sendSerialData() { String data = ""; for (int i=0; i<processing_values.length; i++) { data += processing_values[i]; if (i < processing_values.length-1) { data += ","; // add splitter character "," between each values element } else { data += "\n"; // add the end of data character linefeed "\n" } } myPort.write(data); print(data); // this prints to the console the values going to arduin0 }
When I made the Processing code, I found my motor didn’t move and only the bouncing ball worked. In addition, the number in the console of Processing is always 0. I asked Professor Godoy for help and she solved the coding problem by changing the “if (x > width-s/2)” into “if (x > width)” so that it represents 1 when the ball touches the side of the screen. And we also found I connect the circuit in the wrong way and it stopped the motor. (The right order is brown is ground, red is 5V and orange is special pin)
Homework
Code
Arduino
// IMA NYU Shanghai // Interaction Lab // For sending multiple values from Arduino to Processing int button1 = 4; int button2 = 8; int count1; int count2; void setup() { Serial.begin(9600); } void loop() { if (digitalRead(button1) == HIGH){ count1 = count1 +1; } if (digitalRead(button2) == HIGH){ count2 = count2 +1; } Serial.print(count1); Serial.print(","); // put comma between sensor values Serial.print(count2); 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); // end of example sending values }
Processing
// IMA NYU Shanghai // Interaction Lab // For receiving multiple values from Arduino to Processing /* * Based on the readStringUntil() example by Tom Igoe * https://processing.org/reference/libraries/serial/Serial_readStringUntil_.html */ import processing.serial.*; int NUM_OF_VALUES_FROM_ARDUINO = 2; /** YOU MUST CHANGE THIS ACCORDING TO YOUR PROJECT **/ int sensorValues[]; /** this array stores values from Arduino **/ String myString = null; Serial myPort; void setup() { size(600, 600); setupSerial(); } void draw() { background(0); getSerialData(); printArray(sensorValues); if (sensorValues[0] % 2 == 1) { pushMatrix(); translate(width*0.3, height*0.3); rotate(frameCount / 200.0); star(0, 0, 30, 70, 5); popMatrix(); } if (sensorValues[1] % 2 == 1) { pushMatrix(); translate(width*0.7, height*0.7); rotate(frameCount / 200.0); star(0, 0, 80, 100, 40); popMatrix(); } } 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()[3], 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_FROM_ARDUINO]; } void getSerialData() { 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_FROM_ARDUINO) { for (int i=0; i<serialInArray.length; i++) { sensorValues[i] = int(serialInArray[i]); } } } } }
At first, I write this Arduino code.
// Interaction Lab // For sending multiple values from Arduino to Processing int button1 = 4; int button2 = 8; void setup() { Serial.begin(9600); } void loop() { // to send values to Processing assign the values you want to send //this is an example int sensor1 = digitalRead(4); int sensor2 = digitalRead(8); Serial.print(sensor1); Serial.print(","); // put comma between sensor values Serial.print(sensor2); // Serial.print(","); // put comma between sensor values // Serial.print(sensor3); 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); // end of example sending values }
And I found only when I press the button, the star appears. The requirement is “when you press button 1 once, star 1 will appear on the canvas, and when you press button 1 once again, star 1 will disappear.”
So I decided to use count to solve this problem and when the number of pressing times is odd, the stars appear and the number is even, the stars disappear.
I research that sound can work as input and generate creative outputs. Music can draw be shown on the screen and let it become more visible.
Here is the example I have found. https://processing.org/tutorials/sound/#example-5-6-audio-analysis
/** * Processing Sound Library, Example 5 * * This sketch shows how to use the FFT class to analyze a stream * of sound. Change the number of bands to get more spectral bands * (at the expense of more coarse-grained time resolution of the spectrum). * * Load this example with included sound files from the Processing Editor: * Examples > Libraries > Sound > Analysis > FFTSpectrum */ import processing.sound.*; // Declare the sound source and FFT analyzer variables SoundFile sample; FFT fft; // Define how many FFT bands to use (this needs to be a power of two) int bands = 128; // Define a smoothing factor which determines how much the spectrums of consecutive // points in time should be combined to create a smoother visualisation of the spectrum. // A smoothing factor of 1.0 means no smoothing (only the data from the newest analysis // is rendered), decrease the factor down towards 0.0 to have the visualisation update // more slowly, which is easier on the eye. float smoothingFactor = 0.2; // Create a vector to store the smoothed spectrum data in float[] sum = new float[bands]; // Variables for drawing the spectrum: // Declare a scaling factor for adjusting the height of the rectangles int scale = 5; // Declare a drawing variable for calculating the width of the float barWidth; public void setup() { size(640, 360); background(255); // Calculate the width of the rects depending on how many bands we have barWidth = width/float(bands); // Load and play a soundfile and loop it. sample = new SoundFile(this, "beat.aiff"); sample.loop(); // Create the FFT analyzer and connect the playing soundfile to it. fft = new FFT(this, bands); fft.input(sample); } public void draw() { // Set background color, noStroke and fill color background(125, 255, 125); fill(255, 0, 150); noStroke(); // Perform the analysis fft.analyze(); for (int i = 0; i < bands; i++) { // Smooth the FFT spectrum data by smoothing factor sum[i] += (fft.spectrum[i] - sum[i]) * smoothingFactor; // Draw the rectangles, adjust their height using the scale factor rect(i*barWidth, height, barWidth, -sum[i]*height*scale); } }