Week 12: Serial Communication Assignment – Sarah & Redha

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

For this exercise, we used a potentiometer as our analog sensor. The Arduino program sends the reading from the sensor over to p5, where it is mapped to the range [ellipseWidth/2, canvasWidth-ellipseWidth/2]. The mapped value is then used to determine the x position of the center of the ellipse.  Since nothing on Arduino is controlled by p5, p5 sends dummy data that is ignored by p5 to maintain the two-way handshake.

// ===== P5 =========
let diameter = 60; 
let sensorVal; // read from p5 transmitted message 

function setup() {
  createCanvas(640, 480);
  sensorVal = 1023/2;
}

function draw() {
  background(220);


  if (!serialActive) {
    text("Press Space Bar to select Serial Port", 20, 30);
  } else {
    text("Connected", 20, 30);
    
    

  }
  fill(0);
  ellipse(map(sensorVal, 0, 1023, diameter/2, width-diameter/2), height/2, diameter, diameter)

}

// === ARDUINO ====
void loop() {
// wait for data from p5 before doing something
while(Serial.available()){
digitalWrite(LED_BUILTIN, HIGH); // led on while receiving data
int _ = Serial.parseInt(); // get dummy variable sent over by p5
if(Serial.read() == '\n'){
delay(5);
int sensor = analogRead(A1); // read sensor value
delay(5);
Serial.println(sensor); // send sensor value
}
}
digitalWrite(LED_BUILTIN, LOW);
}

2. Make something that controls the LED brightness from p5

For this exercise, we created a slider that controls the brightness of the LED. The range of the slider matches that of the LED analog value ranges, from 0 to 255. Hence, we only had to send that value over to the Arduino. Once received, the Arduino program writes that value to the LED PWM pin in an analog fashion. For visualization, our p5 sketch draws a circle whose diameter is proportional to the LED brightness.

// ===== p5 ======
let slider;

function setup() {
  createCanvas(640, 480);
  sensorVal = 1023/2;
  slider = createSlider(0, 255, 0);
}

function draw() {
  background(0);
  

  fill(0,0,255);
  noStroke();
  let diameter = map(slider.value(), 0, 255, 0, height); 
  ellipse(width/2, height/2, diameter, diameter); 

  fill(255);
  if (!serialActive) {
    text("Press Space Bar to select Serial Port", 20, 30);
  } else {
    text("Connected", 20, 30);
  }
}

function keyPressed() {
  if (key == " ") {
    setUpSerial();
  }
}

function readSerial(data) {
  if (data != null) {
    let sendToArduino = slider.value() + '\n';
    print(sendToArduino)
    writeSerial(sendToArduino);
  }
}

// ===== ARDUINO =====

void loop() {
  // analogWrite(leftLedPin, pwm); 
  // wait for data from p5 before doing something
  while (Serial.available()) {
    digitalWrite(LED_BUILTIN, HIGH); // led on while receiving data
    pwm = Serial.parseInt(); // get dummy variable sent over by p5
    if (Serial.read() == '\n') {
      delay(5);
      analogWrite(rightLedPin, pwm); 
      delay(5);
      Serial.println("0");
    }
  }
  digitalWrite(LED_BUILTIN, LOW);
}

3. Take the gravity wind example 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

We needed to establish bi-directional meaningful data exchange in this exercise. The first is to send the Arduino a signal from p5 when the ball hits the ground. This is done by checking if the bottom portion of the ellipse touches the canvas’s lower boundary position.y + mass/2 == height . If this evaluates to true, a signal of 1 is sent over. Otherwise, 0 is sent. When the Arduino program receives the signal, it turns the LED on or off accordingly. Similarly, the Arduino sends the value of the potentiometer (our chosen sensor) over to p5, where it gets mapped to the range [-1, 1]. The mapped value is set towind.x. The closer the potentiometer value is to the extremes, the stronger the wind effect on the ball. Sensor values below 512 also get mapped to negative values, and the ball motion trajectory goes leftward. Otherwise, the wind effect goes in the opposite direction.

// ===== p5 =======

let velocity;
let gravity;
let position;
let acceleration;
let wind;
let drag = 0.99;
let mass = 50;

let analogVal = 0; 
let dir = 0; 

function setup() {
  createCanvas(640, 360);
  noFill();
  position = createVector(width/2, 0);
  velocity = createVector(0,0);
  acceleration = createVector(0,0);
  gravity = createVector(0, 0.5*mass);
  wind = createVector(0,0);
}

function draw() {
  background(220);
  applyForce(wind);
  applyForce(gravity);
  velocity.add(acceleration);
  velocity.mult(drag);
  position.add(velocity);
  acceleration.mult(0);
  
  if (!serialActive) {
    text("Press S to select Serial Port", 20, 30);
  } else {
    text("Connected", 20, 30);
  }
  
  fill(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;
    }
}

function applyForce(force){
  // Newton's 2nd law: F = M * A
  // or A = F / M
  let f = p5.Vector.div(force, mass);
  acceleration.add(f);
}

function keyPressed(){
  if (keyCode==LEFT_ARROW){
    wind.x=-1;
  }
  if (keyCode==RIGHT_ARROW){
    wind.x=1;
  }
  if (key==' '){
    mass=random(15,80);
    position.y=-mass;
    velocity.mult(0);
  }
  if (key == 's') {
    // important to have in order to start the serial connection!!
    setUpSerial();
  }
}

function readSerial(data) {
  if (data != null) {
    // make sure there is actually a message
    let fromArduino = data; 
    // if the right length, then proceed
    if (fromArduino.length > 0) {
      analogVal = int(data);
      
    } 
    wind.x = map(analogVal, 0, 1023, -1, 1); 
    let sendToArduino; 
    if (position.y + mass/2 == height){
      sendToArduino = 1 + '\n'; 
    }
    else{
      sendToArduino = 0 + '\n'; 
    }
    
    writeSerial(sendToArduino);
  }
}



// ======= Arduino ====== 
void loop() {
  // wait for data from p5 before doing something
  while (Serial.available()) {
    digitalWrite(LED_BUILTIN, HIGH); // led on while receiving data
    ledState = Serial.parseInt(); // get ball bounce indicator from p5.js
    if (Serial.read() == '\n') {
      // turn on LED accrodingly 
      if (ledState == 1){
        digitalWrite(rightLedPin, HIGH);
      }
      else{
        digitalWrite(rightLedPin, LOW);
      }
      
      currSensorVal = analogRead(A1); // read sensor value 
      Serial.println(currSensorVal); // send sensor value 
    }
  }
  digitalWrite(LED_BUILTIN, LOW);
}

 

Leave a Reply