Recitation 8: Serial Communication

Exercise 1: Make a Processing Etch-A-Sketch

I first connect the circuit and run the Arduino Code, which went very well. Then, I tried to connect my Arduino with Processing. During this part, I met two difficulties. And a bid problem I met here was that I didn’t know how to restore the previous value of the variables. I searched for this question on the internet and learned that I could declare another variable and use this one to restore the previous value. The specific part in my code was to declare float xp and float yp, and let xp = x and yp = y at the end of the loop.

codes

Arduino code

/*
  AnalogReadSerial

  Reads an analog input on pin 0, prints the result to the Serial Monitor.
  Graphical representation is available using Serial Plotter (Tools > Serial Plotter menu).
  Attach the center pin of a potentiometer to pin A0, and the outside pins to +5V and ground.

  This example code is in the public domain.

  https://www.arduino.cc/en/Tutorial/BuiltInExamples/AnalogReadSerial
*/

// the setup routine runs once when you press reset:
void setup() {
  // initialize serial communication at 9600 bits per second:
  Serial.begin(9600);
}

// the loop routine runs over and over again forever:
void loop() {
  // read the input on analog pin 0:
  int sensorValue1 = analogRead(A0);
  int sensorValue2 = analogRead(A1);
  // print out the value you read:
  Serial.print(sensorValue1);
  Serial.print(",");
  Serial.print(sensorValue2);
Serial.println();   
  delay(100);        // delay in between reads for stability
}

Processing code

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 xp;
float yp;
void setup() {
 
  setupSerial(); 
  size(800, 800);
  background(255);
}
void setupSerial() {
  printArray(Serial.list());
  myPort = new Serial(this, Serial.list()[2], 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;

  sensorValues = new int[NUM_OF_VALUES_FROM_ARDUINO];
}
void draw() {
  getSerialData();
  printArray(sensorValues);
  
float x = map(sensorValues[0], 0, 1023, 0, 800);
float y = map(sensorValues[1], 0, 1023, 0, 800);
 line(x, y, xp, yp);
  
  xp = x;
  yp = y;
}

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&photo

Exercise 2:

I first wrote the code in processing. At first, in the void draw loop, to make the ball bounce, my code was like this:

if (x > width - 50 | x < 50 ){
  xs = -xs;
  processing_values[0] = 1;
}else{
processing_values[0] = 0;

Then I connected the Arduino. Since I only had one servo and this servo should only move when the ball reached either the left side or the right side of the screen. However, according to the above code, the servo moved when the ball reached both side, so I changed the code to this:

if (x > width - 50 ){
  xs = -xs;
  processing_values[0] = 1;
}else if ( x < 50){
  xs = -xs;
processing_values[0] = 0;
}else{
  processing_values[0] = 0;
}

Finally, it worked quite well.

Codes

Processing code

// IMA NYU Shanghai
// Interaction Lab

/**
 * This example is to send multiple values from Processing to Arduino.
 * You can find the arduino example file in the same folder which works with this Processing file.
 **/

import processing.serial.*;

int NUM_OF_VALUES_FROM_PROCESSING = 3;  /** 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 **/
int x = 50;
int xs = 7;
Serial myPort;
String myString;


void setup() {
  //size(1000, 1000);
  fullScreen();
  background(0);
  setupSerial();
}

void draw() {
  background(0);
fill(255);
x = x + xs;
circle(x, height/2, 100);

if (x > width - 50 ){
  xs = -xs;
  processing_values[0] = 1;
}else if ( x < 50){
  xs = -xs;
processing_values[0] = 0;
}else{
  processing_values[0] = 0;
}
println(x);
  // send the values to Arduino.
  sendSerialData();

}

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;

}

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
    } 
    //if it is the last element in the values array
    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 
  
}

Arduino code

// IMA NYU Shanghai
// Interaction Lab

/**
  This example is to send multiple values from Processing to Arduino.
  You can find the Processing example file in the same folder which works with this Arduino file.
 **/

#define NUM_OF_VALUES_FROM_PROCESSING 3    /** 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 processing_values[NUM_OF_VALUES_FROM_PROCESSING];
#include<Servo.h>
Servo Myservo;

void setup() {
  Serial.begin(9600);
  //  pinMode(13, OUTPUT);
  Myservo.attach(10);
}

void loop() {
  getSerialData();

  // add your code here using elements in the values array


  if (processing_values[0] == 1) {
    //turn on an LED when the mouse is pressed
    Myservo.write(90);
    delay(1000);
     Serial.println("servo moves 90");
  } else {
    Myservo.write(0);
     Serial.println("servo moves 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;
    }
  }
}

Video

Homework

Step1

Step2

// 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);
  background(0);
  setupSerial();
}

void draw() {
  getSerialData();
  printArray(sensorValues);
star(width*0.3, height*0.3, 30, 70, 5); 
star(width*0.7, height*0.7, 80, 100, 40);
  // use the values like this!
  // sensorValues[0] 

  // add your code

  //
}
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_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]);
        }
      }
    }
  }
}

Step3

Leave a Reply

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