Recitation 8: Serial Communication
Instructor: Marcela
Exercise 1: Make a Processing Etch a Sketch
Using the code from Github and with the help of Jingyi, I was able to successfully create the Etch a Sketch. When I first started, I wasn’t able to move the ellipse coded on Processing when I turned the potentiometer connected to Arduino. I wasn’t getting a change in numbers shown on the serial monitor in Processing when I was turning the knob. Jingyi helped me understand that the values from the potentiometer were being printed horizontally on Arduino when I needed the values to be printed vertically so Processing could understand the information being transmitted. We solved the issue by adding Serial.println instead of just having Serial.print. We needed to make the values readable to Processing. Once we had the correct code in Arduino, I ran into the trouble of the ellipse always going out of the margins of Processing box. So to combat this issue, we added a map function to ellipses’s x position and y position values. Once we added this, we were able to keep the movement of the ellipse within the Processing box. Finally, we wanted to comment out background in the void draw () to allow the ellipse to draw a trail, imitating what an Etch a Sketch is like. We commented it out because every time I moved the ellipse via the potentiometer, the background would redraw itself and the whole thing would reset. So, we kept the background function in void setup ().
Model:
Exercise 2: Make a Musical Instrument with Arduino
I used the code from Github to send values from Processing to Arduino. I wanted to create something where when the mouse is pressed and moved, the pitch of the buzzer would sound accordingly. I was able to get to the point where when the mouse was pressed and moved, the buzzer would sound, but the buzzer made a really gross sound and would continue to increase in pitch even when I stopped pressing down the mouse. With the help of Leon, I was able to understand that that was happening because in Arduino, I was equating two things that were equal at once and it was stressing the Arduino out because it can only register information at a specific speed. It was reading the values as true and making sound at the same time.
We fixed this issue by replacing digitalWrite with tone() instead. With this, we were also able to map the frequency and fix the squeaky sound and have the sound be more smooth when I would press and move the mouse. Here, I searched up how to draw a continuous line on Processing, and integrated that into my code for mousePressed. Now, my code was able to draw a line and alter sound when I pressed down the mouse and moved it around the Processing box.
Model:
Code for Exercise 1:
Arduino:
// IMA NYU Shanghai
// Interaction Lab
// For sending multiple values from Arduino to Processingvoid setup() {
Serial.begin(9600);}
void loop() {
int sensor1 = analogRead(A0);
int sensor2 = analogRead(A1);
// keep this format
Serial.print(sensor1);
Serial.print(“,”); // put comma between sensor values
Serial.println(sensor2);
// too fast communication might cause some latency in Processing
// this delay resolves the issue.
delay(100);
}
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.*;
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 **/
void setup() {
size(500, 500);
background(0); //if background in draw not called, circles drawn on top of all
setupSerial();
}
void draw() {
updateSerial();
printArray(sensorValues);
fill(255);
ellipse(map(sensorValues[0],0,1023,0,width), map(sensorValues[1],0,1023,0,height),50,50);
//
}
void setupSerial() {
printArray(Serial.list());
myPort = new Serial(this, Serial.list()[ 5 ], 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:
Arduino:
// IMA NYU Shanghai
// Interaction Lab/**
#define NUM_OF_VALUES 2 /** 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);
pinMode(9,OUTPUT);
}
void loop() {
getSerialData();
if (values[0]==1){
tone(9,map(values[1],0,500,31,4990));
}
else{
noTone(9);
// }
//tone(9,values[1]);
}
//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;
}
}
}
Processing:
// IMA NYU Shanghai
// Interaction Lab
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()[ 5 ], 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);
stroke(255);
if (mousePressed == true) {
line(mouseX, mouseY, pmouseX, pmouseY);
values[0]=1;
}
else{
values [0]=0;
}
//if(mousePressed){
// values[0]=1;
//}
// if(keyPressed){
// values[1]=1;
// }
// else{
// values[1]=0;
//}
values[1]=mouseX;
//values[3]=mouseY;
// changes the values
//for (int i=0; i<values.length; i++) {
// values[i] = i; /** Feel free to change this!! **/
//}
// 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 );
}