Serial Communication Exercises

I worked with Armaan for the 3 exercises involving serial communication.

Exercise 1: Make something that uses only one sensor on Arduino and makes the ellipse in processing move on the horizontal axis, in the middle of the screen, and nothing on Arduino is controlled by processing.

For this exercise, we made the ellipse move in the middle of the screen using a potentiometer. I did this exercise in class with Shreya and it hardly took any time then, but it took some time to revise the concepts and get things right when I worked with Armaan on the weekend.

Arduino Code:

void setup() {
  Serial.begin(9600);
  Serial.println("0");
}
 
void loop() {
  while (Serial.available()) {
    if (Serial.read() == '\n') {
      int sensor = analogRead(A0);
      delay(1);
      Serial.println(sensor);
    }
  }
}

Processing Code:

import processing.serial.*;
Serial myPort;
int xPos=0;
int yPos=0;
 
void setup(){
  size(960,720);
  printArray(Serial.list());
  String portname=Serial.list()[1];
  println(portname);
  myPort = new Serial(this,portname,9600);
  myPort.clear();
  myPort.bufferUntil('\n');
}
 
void draw(){
  background(255);
  ellipse(xPos,height/2,30,30);
}
 
void serialEvent(Serial myPort){
  String s=myPort.readStringUntil('\n');
  s=trim(s);
  if (s!=null){
    println(s);
    int value=int(s);
    if (value >= 0){
      // changing the x position of the ellipse using the potentiometer
      xPos=(int)map(value,0,1023,0, width);
    }
  }
  myPort.write("\n");
}

 

Exercise 2: Make something that controls the LED brightness from Processing

For this exercise, we made use of the x coordinate of the mouse to control the brightness of the LED. This was fairly easy after completing the first exercise.

Arduino Code:

int brightness = 0;

void setup() {
  Serial.begin(9600);
  Serial.println("0");
  pinMode(3, OUTPUT);
}
 
void loop() {
  while (Serial.available()) {
    brightness = Serial.parseInt();
    if (Serial.read() == '\n') {
      analogWrite(3, brightness);
      int sensor = analogRead(A0);
      delay(1);
      Serial.println(sensor);
    }
  }
}

Processing code:

import processing.serial.*;
Serial myPort;
int xPos=0;
int yPos=0;
int brightness = 0;
 
void setup(){
  size(960,720);
  printArray(Serial.list());
  String portname=Serial.list()[1];
  println(portname);
  myPort = new Serial(this,portname,9600);
  myPort.clear();
  myPort.bufferUntil('\n');
}
 
void draw(){
  background(255);
  ellipse(xPos,height/2,30,30);
  // controlling a variable called brightness using the mouse value
  brightness = int(map(mouseX, 0, width, 0, 255));
}
 
void serialEvent(Serial myPort){
  String s=myPort.readStringUntil('\n');
  s=trim(s);
  if (s!=null){
    println(s);
  }
  myPort.write(brightness + "\n");
}

 

Exercise 3: take the gravity wind example (https://github.com/aaronsherwood/introduction_interactive_media/blob/master/processingExamples/gravityExamples/gravityWind/gravityWind.pde) and make it so every time the ball bounces one led lights up and then turns off, and you can control the wind from one analog sensor

I think this was the hardest exercise, because it was difficult to exactly determine the conditions when the LED had to be switched off. But then, we managed to handle this problem by using the y-position and y-velocity of the ball. Also, controlling the wind using the potentiometer was tricky. Eventually, we ended up the current value generated by the potentiometer and the previous value generated by the potentiometer and then sending them both to Processing. Processing would then compare the two values and decide if the ball had to move with the wind, and in case it did, decide the direction in which the wind was blowing (and the ball moving).

Arduino Code:

int brightness = 0;
int previousValue = 0;
int onOff = 0;

void setup() {
  Serial.begin(9600);
  Serial.println("0");
  pinMode(3, OUTPUT);
}
 
void loop() {
  while (Serial.available()) {
    onOff = Serial.parseInt();
    if (Serial.read() == '\n') {
      int sensor = analogRead(A0);
      delay(1);

      // sending the current and previous values to processing
      Serial.print(sensor);
      Serial.print(",");
      Serial.println(previousValue);

      // setting the previous value equal to current value
      previousValue = sensor;

      // turning the LED on or off based on signals from processing
      if (onOff == 1){
        analogWrite(3, 255);
      }
      else{
        analogWrite(3, 0);
      }
    }
  }
}

Processing Code:

PVector velocity;
PVector gravity;
PVector position;
PVector acceleration;
PVector wind;
float drag = 0.99;
float mass = 50;
float hDampening;

import processing.serial.*;
Serial myPort;
int wind_speed;

int xPos=0;
int yPos=0;
boolean onOff=false;

void setup() {
  size(640,360);
  printArray(Serial.list());
  String portname=Serial.list()[1];
  println(portname);
  myPort = new Serial(this,portname,9600);
  myPort.clear();
  myPort.bufferUntil('\n');
  
  noFill();
  position = new PVector(width/2, 0);
  velocity = new PVector(0,0);
  acceleration = new PVector(0,0);
  gravity = new PVector(0, 0.5*mass);
  wind = new PVector(0,0);
  hDampening=map(mass,15,80,.98,.96);
}

void draw() {
  background(255);
  if (!keyPressed){
    wind.x=wind_speed;
    velocity.x*=hDampening;
  }
  applyForce(wind);
  applyForce(gravity);
  velocity.add(acceleration);
  velocity.mult(drag);
  position.add(velocity);
  acceleration.mult(0);
  ellipse(position.x,position.y,mass,mass);
  if (position.y > height-mass/2) {
      velocity.y *= -0.9;  // A little dampening when hitting the bottom
      position.y = height-mass/2;
    }
}
  
void applyForce(PVector force){
  // Newton's 2nd law: F = M * A
  // or A = F / M
  PVector f = PVector.div(force, mass);
  acceleration.add(f);
}

void keyPressed(){
  if (keyCode==LEFT){
    wind.x=-1;
  }
  if (keyCode==RIGHT){
    wind.x=1;
  }
  if (key==' '){
    mass=random(25,80);
    position.y=-mass;
    velocity.mult(0);
  }
}

void serialEvent(Serial myPort){
  String s=myPort.readStringUntil('\n');
  s=trim(s);
  if (s!=null){
    println(s);
    int values[] = int(split(s,','));
    
    if (values.length == 2){
      // moving wind towards the right if the current value is greater than the previous value
      if (values[0] > values[1]){
        wind_speed = 20;
      }
      // moving wind towards the left if the current value is lesser than the previous value
      else if (values[0] < values[1]){
        wind_speed = -20;
      }
      // setting wind speed to 0 if both values are equal
      else if (values[1] == values[1]){
        wind_speed = 0;
      }
    }
  }
  
  if (round(position.y + mass) >= height && round(velocity.y) != 0){
    // sending a value of 1 if the ball touches the ground and is supposed to go back
    myPort.write(1 + "\n");
  }
  else{
    // sending a value of 0 if the ball doesn't touch the ground or touches and then stays on the ground (rest position)
    myPort.write(0 + "\n");
  }
}

The video for Exercise 3 is attached below

Leave a Reply