Recitation 8: Serial Communication

For this recitation, we did many exercises to get familiar with the connection between Arduino and processing.

Exercise 1:

The first exercise is using Arduino to send two analog values to Processing via serial communication. I find this one the most confident one for me to do. 
Below is the Arduino code:

void setup() {
  Serial.begin(9600);
}

void loop() {
  int sensor1 = analogRead(A0);
  int sensor2 = analogRead(A1);
  Serial.print(sensor1);
  Serial.print(",");  // put comma between sensor values
  Serial.print(sensor2);
  Serial.println();
  
}

Processing:

import processing.serial.*;
float x;
float y;

int NUM_OF_VALUES_FROM_ARDUINO = 2;   /** YOU MUST CHANGE THIS ACCORDING TO YOUR PROJECT **/
int sensorValues[];      /** this array stores values from Arduino **/
int sensorp[];
String myString = null;
Serial myPort;

void setup() {
  size(500, 500);
  setupSerial();
  sensorp = new int[NUM_OF_VALUES_FROM_ARDUINO];
  background(0);
}

void draw() {
  getSerialData();
  printArray(sensorValues);  
  x = map(sensorValues[0],0,1023,0,width);
  y = map(sensorValues[1],0,1023,0,width);

  stroke(255);
  line(sensorp[0], sensorp[1],x, y);
  sensorp[0]=int(x);
  sensorp[1]=int(y);
}

void setupSerial() {
  printArray(Serial.list());
  myPort = new Serial(this, Serial.list()[2], 9600);
  
  myPort.clear();
  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]);
        }
      }
    }
  }
}

Video: 

Exercise 2:

For this exercise, I found two codes for the bouncing circle. The first one is like this:

/**
 * Bounce. 
 * 
 * When the shape hits the edge of the window, it reverses its direction. 
 */
 
int rad = 60;        // Width of the shape
float xpos, ypos;    // Starting position of shape    

float xspeed = 2.8;  // Speed of the shape
float yspeed = 2.2;  // Speed of the shape

int xdirection = 1;  // Left or Right
int ydirection = 1;  // Top to Bottom


void setup() 
{
  fullScreen();
  noStroke();
  frameRate(30);
  ellipseMode(RADIUS);
  // Set the starting position of the shape
  xpos = width/2;
  ypos = height/2;
}

void draw() 
{
  background(102);
  
  // Update the position of the shape
  xpos = xpos + ( xspeed * xdirection );
  ypos = ypos + ( yspeed * ydirection );
  
  // Test to see if the shape exceeds the boundaries of the screen
  // If it does, reverse its direction by multiplying by -1
  if (xpos > width-rad || xpos < rad) {
    xdirection *= -1;
  }
 
    ydirection *= 0;
  

  // Draw the shape
  ellipse(xpos, ypos, rad, rad);
}

However, I found it really hard to use this code to communicate with processing, I tried several times but don’t know how to use “if statement” in this case. And later Tracy and I figured another way to code the bouncing circle. My servo isn’t working, so I did the coding part with Tracy and she filmed how the servo interacts with the bouncing circle.

Arduino code:

#define NUM_OF_VALUES_FROM_PROCESSING 1    /** YOU MUST CHANGE THIS ACCORDING TO YOUR PROJECT **/
#include <Servo.h>
/** DO NOT REMOVE THESE **/
int tempValue = 0;
int valueIndex = 0;
bool prevState = false;
bool currentState = false;
Servo myservo;
int processing_values[NUM_OF_VALUES_FROM_PROCESSING];
void setup() {
  Serial.begin(9600);
  pinMode(12, OUTPUT);
  myservo.attach(10);
}
void loop() {
  getSerialData();
  currentState = processing_values[0];
 
  if (currentState != prevState && currentState == 1) {
    myservo.write(90);
   
    myservo.write(0);
  } else {
    myservo.write(0);
  }
  prevState = currentState;
}
//receive serial data from Processing
void getSerialData() {
  while (Serial.available()) {
    char c = Serial.read();
    switch (c) {
      case '0'...'9':
        tempValue = tempValue * 10 + c - '0';
        break;
      case ',':
        processing_values[valueIndex] = tempValue;
        tempValue = 0;
        valueIndex++;
        break;
      case '\n':
        processing_values[valueIndex] = tempValue;
        tempValue = 0;
        valueIndex = 0;
        break;
    }
  }
}

Processing:

import processing.serial.*;
int NUM_OF_VALUES_FROM_PROCESSING = 1;  /** YOU MUST CHANGE THIS ACCORDING TO YOUR PROJECT **/
int processing_values[] = new int[NUM_OF_VALUES_FROM_PROCESSING]; /** this array stores values you might want to send to Arduino **/
Serial myPort;
String myString;
int x=30;
int speedX = 5;
void setup() {
  fullScreen();
  background(0);
  setupSerial();
}
void draw() {
  background(0);
  circle (x, 100, 100);
  x= x+speedX;
  if (x > width-40 || x < 0+30) {
    speedX = -speedX;
  }
  if (x > width-30) {
    processing_values[0] = 1;
  } else {
    processing_values[0] = 0;
  }
  sendSerialData();
}
void setupSerial() {
  printArray(Serial.list());
  myPort = new Serial(this, Serial.list()[2], 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 is less than the index number of the last element in the values array
    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"
    }
  }
  //write to Arduino
  myPort.write(data);
  print(data); // this prints to the console the values going to arduino
}

Video:

Additional homework:

I found the communication quite confusing for there are many sections and it’s sometimes even impossible to figure out which part goes wrong. So I participated in the workshop and learnt more about the whole logic behind this.

Arduino code:

// IMA NYU Shanghai
// Interaction Lab
// For recitation 8 homework, controlling the display of two stars with two buttons


void setup() {
  Serial.begin(9600);
}

void loop() {
  int button1 = digitalRead(9);
  int button2 = digitalRead(10);

  // keep this format
  Serial.print(button1);
  Serial.print(",");  // put comma between values
  Serial.print(button2);
  Serial.println(); // add linefeed after sending the last value

  // too fast communication might cause some latency in Processing
  // this delay resolves the issue.
  delay(100);
}

Processing:

// IMA NYU Shanghai
// Interaction Lab
// For recitation 8 homework, controlling the display of two stars with two buttons

/*
 * 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[] buttonValues;      /** this array stores values from Arduino **/
int prevButtonValue0 = 0;
int prevButtonValue1 = 0;
boolean star1Display = false;
boolean star2Display = false;


void setup() {
  size(600, 600);
  background(0);
  setupSerial();
}


void draw() {
  updateSerial();
  printArray(buttonValues);

  background(0);

  if (buttonValues[0]==1 && buttonValues[0]!= prevButtonValue0) {
    star1Display = !star1Display;
  }
  if (buttonValues[1]==1 && buttonValues[1]!= prevButtonValue1) {
    star2Display = !star2Display;
  }

  if (star1Display) {
    pushMatrix();
    translate(width*0.3, height*0.3);
    rotate(frameCount / 200.0);
    star(0, 0, 30, 70, 5); 
    popMatrix();
  }

  if (star2Display) {
    pushMatrix();
    translate(width*0.7, height*0.7);
    rotate(frameCount / 400.0);
    star(0, 0, 80, 100, 40); 
    popMatrix();
  }

  prevButtonValue0 = buttonValues[0];
  prevButtonValue1 = buttonValues[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()[ 6 ], 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;

  buttonValues = 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++) {
          buttonValues[i] = int(serialInArray[i]);
        }
      }
    }
  }
}

Video:

  

Research:

 For the coming classes we will be learning how to manipulate image, video and sound. I’m really excited about this, I think it can add a lot more interesting effects to the interaction. It also is so relevant to the final project as well. 

For our project, one of our ideas is to visualize the sound. Since originally, sound is a wave that comes from vibration. If it’s impossible for people with hearing problems to hear, it would be great for them to see the wave and feel the vibration, which are the two parts that builds the sound. By research we found that it’s possible to use processing to code wave or random shapes for different pitches, which I find really interesting.

Also, by searching for “processing image” on Google, I found that Processing currently works with GIF, JPEG, and PNG images. So it’s also possible to add actual pictures to the final result, which can also be very useful. I believe that using a GIF can have very funny effect.

Leave a Reply

Your email address will not be published. Required fields are marked *