Exercise 1: Make a Processing Etch A Sketch
Image from ebay.com ( I actually bought one exactly the same when traveling !)
Image I drew
(A to P) use Arduino to send two analog values to Processing via serial communication
For this exercise, I used Arduino to send two analog values to Processing via serial communication. Just like an Etch A Sketch, the potentiometer on the left control the ellipse’s x-axis movement, and the other one on the right control the ellipse’s y-axis movement. Once I have it working with an ellipse, I modify the code to use a line instead by tracing the previous x and y values.
Processing
My first draft of the code:
// Interaction Lab import processing.serial.*; float penX; float penY; 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 newvalue1; float newvalue2; void setup() { size(800, 800); background(0); noStroke(); fill(60, 120, 20 ); setupSerial(); penX = width/2; // starting x position of pen penY = height/2; // starting y position of pen } void draw() { penX = sensorValues[0]; penY = sensorValues[1]; updateSerial(); printArray(sensorValues); newvalue1= map(sensorValues[0], 0, 1023,0, width); newvalue2= map(sensorValues[1], 0, 1023,0, height); ellipse( newvalue1,newvalue2, 15, 20 ); ellipse( penX,penY, 15, 20 ); } void setupSerial() { printArray(Serial.list()); myPort = new Serial(this, Serial.list()[ 1 ], 9600); myPort.clear(); // Throw out the first reading, 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]); } } } } }
⬆️ My original coding from the example downloaded,
but I find a more convenient way from the Internet⤵️
http://graysonearle.com/edu/physcom/etch-a-sketch-arduino-processing/
My new coding:
import processing.serial.*; Serial myPort; // The serial port // a variable to store the incoming serial data to int inByte1 = 0; int inByte2 = 0; // keep track of old line positions float lastX = 0; float lastY = 0; void setup() { size(800, 800); printArray(Serial.list()); myPort = new Serial(this, Serial.list()[1], 9600); background(0); stroke(255); strokeWeight(3); } void draw() { while (myPort.available () > 1) { // read in the last byte sent from arduino (pot 2) inByte1 = myPort.read(); // and the next byte (first one was discarded) inByte2 = myPort.read(); } float x = map(inByte1, 0, 255, 0, width); float y = map(inByte2, 0, 255, 0, height); line(x, y, lastX, lastY); // reset the lastX and Y lastX = x; lastY = y; } void keyPressed() { background(0); }
Arduino
void setup() { Serial.begin(9600); } void loop() { int theValue = analogRead(A0); int theMappedValue = map(theValue, 0, 1023, 0, 255); Serial.write(theMappedValue); theValue = analogRead(A1); theMappedValue = map(theValue, 0, 1023, 0, 255); Serial.write(theMappedValue); delay(20); }
Exercise 2: Make a musical instrument with Arduino
This processing sketch sends values to Arduino based on mouse’s x and y positions and/or keyboard interactions. The corresponding Arduino code should read the serial values from Processing and translate them into frequency and duration for a tone, which will be sounded by the buzzer (hint: the tone()
function).
Processing
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]; void setup() { size(500, 500); background(0); printArray(Serial.list()); myPort = new Serial(this, Serial.list()[ 1 ], 9600); 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); values[0]=mouseX; values[1]=mouseY; // sends the values to Arduino. sendSerialData(); 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 ); }
Arduino
#define NUM_OF_VALUES 1 /** YOU MUST CHANGE THIS ACCORDING TO YOUR PROJECT **/ /** DO NOT REMOVE THESE **/ int tempValue = 0; int valueIndex = 0; /* This is the array of values storing the data from Processing. */ int values[NUM_OF_VALUES]; void setup() { Serial.begin(9600); pinMode(13, OUTPUT); } void loop() { getSerialData(); // add your code here // use elements in the values array // values[0] // values[1] tone(13, values[0]); } //recieve serial data from Processing void getSerialData() { if (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 ',': 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 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; //if the char c from Processing is character 'e' //it is signalling for the Arduino to send Processing the elements saved in the values array //this case is triggered and processed by the echoSerialData function in the Processing sketch case 'e': // to echo for (int i = 0; i < NUM_OF_VALUES; i++) { Serial.print(values[i]); if (i < NUM_OF_VALUES - 1) { Serial.print(','); } else { Serial.println(); } } break; } } }
Additional Homework
Use two pushbuttons connected to Arduino to control the display of two stars in Processing.
Arduino:
void setup() { Serial.begin(9600); } void loop() { int sensor1 = digitalRead(7); int sensor2 = digitalRead(8); Serial.print(sensor1); Serial.print(","); // put comma between sensor values Serial.print(sensor2); Serial.println(); // add linefeed after sending the last sensor value delay(100); }
Processing:
import processing.serial.*; String myString = null; Serial myPort; int NUM_OF_VALUES = 2; /** YOU MUST CHANGE THIS ACCORDING TO YOUR PROJECT **/ int[] Values; /** this array stores values from Arduino **/ int previousValues0 = 0; int previousValues1 = 0; boolean star1 = false; boolean star2 = false; void setup() { size(600, 600); background(0); setupSerial(); } void draw() { updateSerial(); printArray(Values); background(0); if (Values[0] == 1 && Values[0] != previousValues0) { star1 = !star1; } if (Values[1] == 1 && Values[1] != previousValues1) { star2 = !star2; } if(star1 == true){ pushMatrix(); translate(width*0.3, height*0.3); rotate(frameCount / 400.0); star(0, 0, 30, 70, 5); popMatrix(); } if (star2 == true) { pushMatrix(); translate(width*0.7, height*0.7); rotate(frameCount / -100.0); star(0, 0, 80, 100, 40); popMatrix(); } previousValues0 = Values[0]; previousValues1 = Values[1]; } 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()[ 1 ], 9600); myPort.clear(); myString = myPort.readStringUntil( 10 ); // 10 = '\n' Linefeed in ASCII myString = null; Values = 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++) { Values[i] = int(serialInArray[i]); } } } } }
Leave a Reply