Week 12: Serial Communication

For this week’s assignment, Aysha and I worked on three different exercises that focused on serial communication.

Exercise 1: Moving p5.js ball with potentiometer

p5.js code:

//Variable to declare the ellipse moving acorss the x-axis
let ellipseX;

function setup() {
  //Canvas dimensions
  createCanvas(400, 400);
  //Set text size to 18 pixels
  textSize(18);
  //Initializes ellipse to half the width of the canvas, essentially centers it
  ellipseX = width/2; 
}

function draw() {
  //Sets background to a light purple shade
  background("rgb(185,185,228)");
   // SetS fill color for the ellipse
  fill("rgb(142,142,228)");
  // Sets stroke color/outline for the ellipse
  stroke("rgb(91,91,233)");
  // Draw ellipse at ellipseX position, centered vertically, with a diameter of 120 pixels
  ellipse(ellipseX, height / 2, 120, 120);
  
  // If serial connection is not active, display message to prompt user to select serial port
  if (!serialActive) {
    //Sets fill color to white
    fill('white');
    // Sets stroke color to a gray shade
    stroke('#666666')
     // Display instructions at (15, 30)
    text("Press Space Bar to select Serial Port", 15, 30);
  } 
  // If serial connection is active, display "Connected" message
  else {
    // Display instructions at (15, 30)
    text("Connected", 15, 30);
  }
}

// Function to handle key presses
function keyPressed() {
  // If space bar is pressed, call setUpSerial() function
  if (key == " ") {
    setUpSerial();
  }
}

// Function to read data from the serial port
function readSerial(data) {
  // Check if data is not null
  if (data != null) {
    // Split the received data into an array using comma as delimiter
    let fromArduino = split(trim(data), ",");
    // Map the potentiometer value to adjust the position of the ellipse
    ellipseX = map(int(fromArduino[0]), 0, 1023, 0, width); 
  }
}

 

Arduino Code:

const int potPin = A1;  // Analog pin connected to the potentiometer
void setup() {
  Serial.begin(9600);
}
void loop() {
    int potValue = analogRead(potPin);  // Read the value from the potentiometer
      // Send the potentiometer value to p5.js
      Serial.println(potValue);
}

 

Exercise 2: Controlling LED with p5.js slider

p5.js code:

// Variable to hold the brightness value
let brightness = 0;
// Variable to hold the slider
let slider;

function setup() {
  //Canvas dimensions
  createCanvas(400, 400);
  // Create slider with range from 0 to 255 and initial value of 100
  slider = createSlider(0, 255, 100);
  // Positions slider horizontally centered and vertically centered
  slider.position(132, height/2);
}

function draw() {
  // Sets background color to a light gray shade
  background('#ADB9C7');
  // Gets  current value of the slider
  let val = slider.value();
  // Updates brightness variable with the slider value
  brightness = val;
  //If brightness is maximum (255), change background color to light blue
  if (brightness == 255) {
    // Changes background color to gold when brightness is max
    background('#DCECFF');  
  }
  
  // If serial connection is not active, display message to prompt user to select serial port
  if (!serialActive) { 
    // Set fill color to blue
    fill('#0876FF');
    // Set stroke color to a light gray shade
    stroke('#B2B2B2');
    // Set text size to 16 pixels
    textSize(16);
    // Display instructions at (20, 30)
    text("Press Space Bar to select Serial Port", 20, 30);
  } 
  // If serial connection is active, display "Connected" message
  else {
    textSize(16);
    // Display instructions at (29, 30)
    text("Connected",29,30);
  }
}

// Function to handle key presses
function keyPressed() {
   // If space bar is pressed, start the serial connection
  if (key == " ") {
    setUpSerial();  
  }
}

// Function to send data to the serial port
function readSerial(data) {
  // Check if data is not null
  if (data != null) {
    
  //Creates a string to send to Arduino with brightness value followed by newline character (HANDSHAKE)
    let sendToArduino = brightness + "\n";
  // Send data to Arduino
    writeSerial(sendToArduino);
  }
}

Arduino code:

int LED = 5; //PWM PIN
void setup() {
  pinMode(LED, OUTPUT);
  Serial.begin(9600);
  
  
  // initializing handshake
  while (Serial.available() <= 0) {
    Serial.println("Initializing Connection");  
    delay(200);               // wait 1/2 second
  }
}
void loop() {
  // wait for data to load from p5 before continuing code
  while (Serial.available()) {
    int brightness = Serial.parseInt(); 
    if (Serial.read() == '\n') {
      analogWrite(LED, brightness); // turn on LED and adjusts brightness
      Serial.println("ON"); 
    }
  }
}

 

Exercise 3: Blink LED with bouncing ball and move wind with potentiometer

p5.js code:

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

// ball bounce check to control LED
let ballBouncing = 0;

function setup() {
  createCanvas(400, 400);
  textSize(width/25);

  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(210, 230, 250);

  if (!serialActive) {
    text("Press Space Bar to select Serial Port", 20, 30);
  } else {
    applyForce(wind);
    applyForce(gravity);
    velocity.add(acceleration);
    velocity.mult(drag);
    position.add(velocity);
    acceleration.mult(0);
   
 // Check boundaries for right and left movement
    if (position.x > width - mass / 2) {
      position.x = width - mass / 2;
      velocity.x *= -0.9; // Reverse velocity when hitting right boundary
    } else if (position.x < mass / 2) {
      position.x = mass / 2;
      velocity.x *= -0.9; // Reverse velocity when hitting boundary
    }

    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;
      ballBouncing = 1;
    } else {
      ballBouncing = 0;
    }
  }
}

function keyPressed() {
  if (key == " ") {
    // to start serial connection
    setUpSerial();
  } else if (key == "ENTER") {
    mass = random(15, 80);
    position.y = -mass;
    velocity.mult(0);
  }
}

function readSerial(data) {
  if (data != null) {
    // make sure there is a message and split it
    let fromArduino = split(trim(data), ",");
    // if it's the right length, then proceed
    if (fromArduino.length == 1) {
      // only store values here

      let potentiometerValue = int(fromArduino[0]);
      wind.x = map(potentiometerValue, 0, 1023, -1, 1);
    }

// ARDUINO HANDSHAKE
   
    let sendToArduino = ballBouncing + "\n";
    writeSerial(sendToArduino);
  }
}

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

Arduino code:

//int ledPin = 5;
//const int potPin=A1;

//void setup() {
  // Start serial communication so we can send data
  // over the USB connection to our p5js sketch
  //Serial.begin(9600);

  //pinMode(LED_BUILTIN, OUTPUT);

  //pinMode(ledPin, OUTPUT);
  //pinMode(potPin, INPUT);


  // start the handshake
  //while (Serial.available() <= 0) {
    //digitalWrite(LED_BUILTIN, HIGH); // on/blink while waiting for serial data
    //Serial.println("0,0"); // send a starting message
    //delay(300);            // wait 1/3 second
    //digitalWrite(LED_BUILTIN, LOW);
    //delay(50);
  //}
//}

//void loop() {
  // wait for data from p5 before doing something
  //while (Serial.available()) {
    //digitalWrite(LED_BUILTIN, HIGH); // led on while receiving data
   //digitalWrite(ledPin, LOW);
   //int ballBouncing =Serial.parseInt();
   
    //if (Serial.read() == '\n') {
    
    //int potPinValue = analogRead(potPin);      delay(5);
      
      //Serial.println(potPinValue);
    //}
  
// Set LED brightness based on whether the ball is bouncing
    //if (ballBouncing == 1) {
      //digitalWrite(ledPin, HIGH);
    //} else {
      //digitalWrite(ledPin, LOW);
    //}
  //}
  //digitalWrite(LED_BUILTIN, LOW);
//}

 

Final project proposal

Idea:

My final project idea is to make a robotic car that acts as a phone cleaner. The spray would be lying somewhere on top of the car and the mini towel would be somewhere under the wheels in which the car can slide over the phone and wipe it. To control this, the user has to use the buttons on p5.js.

Arduino:

  • Distance sensor to sense if the phone is available.
  • Servo motor for the screen spray.
  • Wheels for the car to move. (x2 or x4)

P5.js:

  • Click button to control spray.
  • Click button and Up and Down keys to control car.

Communications:

At first, the screen on p5.js will ask for the user to insert their phone in front of the car. Once it is detected by the distance sensor, it will send a signal to p5.js and the screen will display a phone with two buttons. The first button will have a spray icon. When it is clicked, it will send a signal to the servo motor and spray the phone. Therefore, it will show a sprayed phone on the screen. The second button will have a wiping icon. When it is clicked, it will allow the user to move the car by clicking the up and down buttons. This way, the car will only move vertically. It will show the phone being dried on the screen while it is wiping.

W12- Design Meets Disability

In Design Meets Disability, Graham Pulin delves into the significance of crafting designs with both accessibility and inclusivity in mind. Something Pulin seems to continue to highlight though is the transformative potential of inclusive design in the design world we know of today. Pulin’s emphasis on reframing disability aids as fashion statements, for example, challenges the prolonged societal perception of aid being designed simply for it to be functional. This highlights the impact that design can have on shaping cultural attitudes, particularly towards certain communities, which in this case are those who are classified as people of determination. In my eyes, this perspective showcases the need for designers to push against their own assumptions about certain communities and consider not only the functional purpose of objects those people might need but also the aesthetics and means of personal expression that can come through with these creations. 

This, however, is easier said than done. Designing for disability within a societal context filled with stigmas, biases, and misperceptions makes it incredibly difficult for people to design creations that are complex in terms of aesthetics and functionality. Given this, I believe that the first step to actually being able to design for disability in a way that is void from any biases is to acknowledge one’s own thoughts and how it may impact the way one would design. By actively engaging in understanding the ways one might think about certain communities such as people of determination, designers can gain invaluable insight into the lived experiences and preferences of those within the disability community, ensuring that these designs are reflective of their needs and desires. Actively engaging in a form of human-centered design can lead to not only more effective and sustainable designs but also fosters a sense of empowerment among those they serve, something that many current disability aids lack. It is only by truly rethinking the traditional paradigms and embracing a more human-centered and holistic approach to designing can we celebrate inclusivity and empower those we help through our designs. 

W12- Serial Communication Exercises 1-3

Team Members: Alreem and Aysha:)

Exercise 1- 

Using a potentiometer, we made an ellipse move left and right on the horizontal axis, ensuring that nothing on the Arduino is controlled by p5.

Schematic

P5js Code

//Variable to declare the ellipse moving acorss the x-axis
let ellipseX;

function setup() {
  //Canvas dimensions
  createCanvas(400, 400);
  //Set text size to 18 pixels
  textSize(18);
  //Initializes ellipse to half the width of the canvas, essentially centers it
  ellipseX = width/2; 
}

function draw() {
  //Sets background to a light purple shade
  background("rgb(185,185,228)");
   // SetS fill color for the ellipse
  fill("rgb(142,142,228)");
  // Sets stroke color/outline for the ellipse
  stroke("rgb(91,91,233)");
  // Draw ellipse at ellipseX position, centered vertically, with a diameter of 120 pixels
  ellipse(ellipseX, height / 2, 120, 120);
  
  // If serial connection is not active, display message to prompt user to select serial port
  if (!serialActive) {
    //Sets fill color to white
    fill('white');
    // Sets stroke color to a gray shade
    stroke('#666666')
     // Display instructions at (15, 30)
    text("Press Space Bar to select Serial Port", 15, 30);
  } 
  // If serial connection is active, display "Connected" message
  else {
    // Display instructions at (15, 30)
    text("Connected", 15, 30);
  }
}

// Function to handle key presses
function keyPressed() {
  // If space bar is pressed, call setUpSerial() function
  if (key == " ") {
    setUpSerial();
  }
}

// Function to read data from the serial port
function readSerial(data) {
  // Check if data is not null
  if (data != null) {
    // Split the received data into an array using comma as delimiter
    let fromArduino = split(trim(data), ",");
    // Map the potentiometer value to adjust the position of the ellipse
    ellipseX = map(int(fromArduino[0]), 0, 1023, 0, width); 
  }
}

Arduino Code

const int potPin = A1;  // Analog pin connected to the potentiometer
void setup() {
  Serial.begin(9600);
}
void loop() {
    int potValue = analogRead(potPin);  // Read the value from the potentiometer
      // Send the potentiometer value to p5.js
      Serial.println(potValue);
}
Exercise 2- 

Using a slider, we controlled the LED brightness from p5.

Schematic

P5js Code

// Variable to hold the brightness value
let brightness = 0;
// Variable to hold the slider
let slider;

function setup() {
  //Canvas dimensions
  createCanvas(400, 400);
  // Create slider with range from 0 to 255 and initial value of 100
  slider = createSlider(0, 255, 100);
  // Positions slider horizontally centered and vertically centered
  slider.position(132, height/2);
}

function draw() {
  // Sets background color to a light gray shade
  background('#ADB9C7');
  // Gets  current value of the slider
  let val = slider.value();
  // Updates brightness variable with the slider value
  brightness = val;
  //If brightness is maximum (255), change background color to light blue
  if (brightness == 255) {
    // Changes background color to gold when brightness is max
    background('#DCECFF');  
  }
  
  // If serial connection is not active, display message to prompt user to select serial port
  if (!serialActive) { 
    // Set fill color to blue
    fill('#0876FF');
    // Set stroke color to a light gray shade
    stroke('#B2B2B2');
    // Set text size to 16 pixels
    textSize(16);
    // Display instructions at (20, 30)
    text("Press Space Bar to select Serial Port", 20, 30);
  } 
  // If serial connection is active, display "Connected" message
  else {
    textSize(16);
    // Display instructions at (29, 30)
    text("Connected",29,30);
  }
}

// Function to handle key presses
function keyPressed() {
   // If space bar is pressed, start the serial connection
  if (key == " ") {
    setUpSerial();  
  }
}

// Function to send data to the serial port
function readSerial(data) {
  // Check if data is not null
  if (data != null) {
    
  //Creates a string to send to Arduino with brightness value followed by newline character (HANDSHAKE)
    let sendToArduino = brightness + "\n";
  // Send data to Arduino
    writeSerial(sendToArduino);
  }
}

Arduino Code

// Define the pin for the LED (PWM PIN)
int LED = 5;

void setup() {
  // Set the LED pin as an output
  pinMode(LED, OUTPUT);
  // Start serial communication at 9600 
  Serial.begin(9600);
  
  // Perform initialization handshake
  while (Serial.available() <= 0) {
    // Send a message to indicate initializing connection
    Serial.println("Initializing Connection");  
    // Delay for a short time
    delay(200);               
  }
}

void loop() {
  // Wait for data from p5.js sketch
  while (Serial.available()) {
    // Read the brightness value from serial communication
    int brightness = Serial.parseInt(); 
    // Check if the next character received is a newline character
    if (Serial.read() == '\n') {
      // Set the brightness of the LED using PWM (analogWrite)
      analogWrite(LED, brightness); 
      // Send a message to indicate that LED is turned on
      Serial.println("ON"); 
    }
  }
}
Exercise 3- 

Taking the gravity wind example provided, we made it so that every time the ball bounces and touches the bottom of the canvas, the led lights up and then turns off. We also added a potentiometer in order to control the wind of the ball, helping it move left and right.  

Schematic

P5js Code

// Variables for physics simulation
// Velocity vector
let velocity; 
// Gravity vector
let gravity;
 // Position vector
let position;
// Acceleration vector
let acceleration;
// Wind vector
let wind;
 // Drag coefficient
let drag = 0.99;
// Mass of the ellipse
let mass = 70;

// Flag to control LED based on ball bounce
let ballBouncing = 0;

function setup() {
  //Canvas dimensions
  createCanvas(400, 400);
  // Set text size based on canvas width
  textSize(width/25);

  // Initialize vectors for position, velocity, acceleration, gravity, and wind
  //Creates vector representing the initial position of the ellipse,set to be horizontally centered (width / 2) and positioned at the top of the canvas (0 on the y-axis)
  position = createVector(width / 2, 0);
  // Creates vector representing the initial velocity of the object,horizontal and vertical components are set to 0, so object is at rest
  velocity = createVector(0, 0);
  //Creates vector representing the initial acceleration of the object,horizontal and vertical components are set to 0, so object is at rest
  acceleration = createVector(0, 0);
  //Creates vector representing the gravitational force acting on the object, set to have a vertical component that depends on the mass of the object, stimulating the effect of gravity pulling the object downwards
  gravity = createVector(0, 0.5 * mass);
  //Creates vector representing the force of wind acting on the object, horizontal and vertical components are set to 0, so no wind affecting the object
  wind = createVector(0, 0);
}

function draw() {
  // Set background color
  background(210, 230, 250);

 // If serial connection is not active, display message to prompt user to select serial port
  if (!serialActive) {
    // Display instructions at (20, 30)
    text("Press Space Bar to select Serial Port", 20, 30);
  } 
  else {
    // Apply forces (gravity and wind)
    applyForce(wind);
    applyForce(gravity);
     // Update position
    // Updates the velocity of the object by adding the current acceleration to it
    velocity.add(acceleration);
    //Multiplies the velocity vector by the drag coefficient, reducing its magnitude and stimulating air resistance
    velocity.mult(drag);
    //Updates the position of the object by adding the current velocity vector to it, helps move ellipse based on velocity
    position.add(velocity);
    //Resets acceleration to 0
    acceleration.mult(0);
   
 // Check boundaries for right and left movement
    //If condition to check if the x-coordinate of the object is exceeding the right boundary of the canvas
    if (position.x > width - mass / 2) {
      //If object's x-coordinate exceeds the right boundary, set the x-coordinate of the object's position to exactly width - mass / 2, placing the object right at the right boundary
      position.x = width - mass / 2;
      // Reverses velocity when hitting right boundary by multiplying it by -0.9, applying a dampening effect to the velocity
      velocity.x *= -0.9; 
    } 
   //Condition to check if the x-coordinate of the object is exceeding the left boundary of the canvas
    else if (position.x < mass / 2) {
      //If object's x-coordinate exceeds the left boundary, set the x-coordinate of the object's position to exactly width - mass / 2, placing the object right at the right boundary
      position.x = mass / 2;
      // Reverses velocity when hitting left boundary by multiplying it by -0.9, applying a dampening effect to the velocity
      velocity.x *= -0.9; 
    }

    // Draw the bouncing ball
    ellipse(position.x, position.y, mass, mass);
    
    //Check boundary for vertical movement (bottom of the canvas)
    if (position.y > height - mass / 2) {
      //Set the y-coordinate of the object's position so that the bottom of the object aligns with the bottom edge of the canvas
      position.y = height - mass / 2;
       // Reverses velocity when hitting bottom boundary by multiplying it by -0.9, applying a dampening effect to the velocity
      velocity.y *= -0.9; 
      //Sets flag to indicate ball bouncing
      ballBouncing = 1;
    } 
    //Resets flag if ball is not bouncing
    else {
      ballBouncing = 0;
    }
  }
}

// Function to handle key presses
function keyPressed() {
   // If space bar is pressed, start the serial connection
  if (key == " ") {
    setUpSerial();
  } 
  // Change mass and reset ball position when Enter key is pressed
  else if (key == "ENTER") {
    // Randomly set the mass of the object within the range of 15 to 80
    mass = random(15, 80);
    // Set the initial y-coordinate of the object's position above the canvas to simulate it entering the scene
    position.y = -mass;
    // Reset the velocity of the object to zero to ensure it starts from rest
    velocity.mult(0);
  }
}

// Function to send data to the serial port
function readSerial(data) {
  // Check if data is not null
  if (data != null) {
// Parse incoming data
    let fromArduino = split(trim(data), ",");
    // If it's the accurate length, then proceed
    if (fromArduino.length == 1) {
      // Store values here
       // Extract potentiometer value and map it to wind force
      let potentiometerValue = int(fromArduino[0]);
      //Mapping pontentiometer value to wind force
      wind.x = map(potentiometerValue, 0, 1023, -1, 1);
    }
   //Creates a string to send to Arduino with brightness value followed by newline character (HANDSHAKE)
    let sendToArduino = ballBouncing + "\n";
    writeSerial(sendToArduino);
  }
}

// Function to apply force to the object
function applyForce(force) {
  // Newton's 2nd law: F = M * A or A = F / M
  // Calculate the force acting on the object by dividing the applied force vector by the mass of the object
  let f = p5.Vector.div(force, mass);
  // Add the resulting force vector to the object's acceleration to calculate its new acceleration
  acceleration.add(f);
}

Arduino Code

// Define the pin for the LED
int ledPin = 5;
// Define the pin for the potentiometer
const int potPin = A1;

void setup() {
  // Start serial communication at 9600 
  Serial.begin(9600);
  
  // Set the built-in LED pin as an output
  pinMode(LED_BUILTIN, OUTPUT);
  // Set the LED pin as an output
  pinMode(ledPin, OUTPUT);
  // Set the potentiometer pin as an input
  pinMode(potPin, INPUT);

  // Start the handshake
  while (Serial.available() <= 0) {
    // Blink the built-in LED while waiting for serial data
    digitalWrite(LED_BUILTIN, HIGH);
    // Send a starting message to the p5.js sketch
    Serial.println("0,0");
    // Delay for a short time
    delay(300);
    // Turn off the built-in LED
    digitalWrite(LED_BUILTIN, LOW);
    // Delay for a short time
    delay(50);
  }
}

void loop() {
  // Wait for data from p5.js sketch
  while (Serial.available()) {
    // Turn on the built-in LED while receiving data
    digitalWrite(LED_BUILTIN, HIGH);
    // Turn off the LED connected to ledPin
    digitalWrite(ledPin, LOW);
    // Read the integer value representing whether the ball is bouncing
    int ballBouncing = Serial.parseInt();
    
    // Check if the next character received is a newline character
    if (Serial.read() == '\n') {
      // Read the value from the potentiometer
      int potPinValue = analogRead(potPin);
      // Short delay to stabilize the reading
      delay(5);
      // Send the potentiometer value to the p5.js sketch
      Serial.println(potPinValue);
    }

    // Set LED brightness based on whether the ball is bouncing
    if (ballBouncing == 1) {
      digitalWrite(ledPin, HIGH); // Turn on the LED
    } else {
      digitalWrite(ledPin, LOW); // Turn off the LED
    }
  }
  // Turn off the built-in LED
  digitalWrite(LED_BUILTIN, LOW);
}

 

Week 12 – Serial Communication (Group Assignment)

Team Members: Muhammed Hazza, Yaakulya Sabbani

Exercise 1: ARDUINO TO P5 COMMUNICATION

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.

Arduino Code

void setup() {
  Serial.begin(9600);
  //pinMode(LED_BUILTIN, OUTPUT);

//start the handshake
  while (Serial.available() <= 0) {
    //digitalWrite(LED_BUILTIN, HIGH);
    Serial.println("0,0"); // send a starting message
    delay(300);
    //digitalWrite(LED_BUILTIN, LOW);
    delay(50);

  }
}

void loop() {
  // wait for data from p5 before doing something
  while (Serial.available()) {
     //digitalWrite(LED_BUILTIN, HIGH);
    int isMoving = Serial.parseInt();
    if (Serial.read() == '\n') {
      int photoVal = analogRead(A0); 
      delay(5);
      Serial.println(photoVal);
   }
  }
  //digitalWrite(LED_BUILTIN, LOW);
}

P5 code

// Initialize variables to store values from Arduino
let rVal = 0; // Stores the received value from Arduino
let xPos = 0; // Stores the mapped x-position value
let rad = 50; // Radius of the ellipse to be drawn

// Setup function - runs once at the beginning
function setup() {
  // Create a canvas with dimensions 400x400
  createCanvas(400, 400);
  // Set text size to 18 pixels
  textSize(18);
}  

// Draw function - runs continuously
function draw() {
  // Set background color to white
  background(255);

  // Check if serial communication is active
  if (!serialActive) {
    // Display message to prompt user to press Space Bar to select Serial Port
    text("Press Space Bar to select Serial Port", 20, 30);
  } else {
    // If serial communication is active, display "Connected" message
    text("Connected", 20, 30);
    
    // Map the received value (rVal) to the x-position within the canvas
    xPos = map(rVal, 0, 900, 0, 400);
    // Display the current received value (rVal)
    text('rVal = ' + str(rVal), 20, 50);
    // Draw an ellipse at the mapped x-position with fixed y-position (200) and radius (rad)
    ellipse(xPos, 200, rad, rad);
    // Display the mapped x-position (xPos)
    text('xPos = ' + str(xPos), 20, 70);
  }
}

// Function to handle key presses
function keyPressed() {
  // Check if Space Bar is pressed
  if (key == " ") {
    // Call setUpSerial() function to start serial connection
    setUpSerial();
  }
}

// Function to read data from Arduino
function readSerial(data) {
  // Check if data is not null
  if (data != null) {
    // Split the received data into an array using comma as delimiter
    let fromArduino = split(trim(data), ",");
    
    // Check if the array contains only one element
    if (fromArduino.length == 1) {
      // Update rVal with the received value from Arduino
      rVal = fromArduino[0];
    }
    
    // Send a handshake message to Arduino
    let sendToArduino = 1 + "\n";
    writeSerial(sendToArduino);
  }
}

Schematic

Video Demonstation

Exercise 2: P5 TO ARDUINO COMMUNICATION

Something that controls the LED brightness from p5.

Arduino Code

//Exercise 2 Arduino Code

const int ledPin =9;
int brightness = 0;
void setup() {
  Serial.begin(9600); // This will start serial communication at 9600 bps

  pinMode(LED_BUILTIN, OUTPUT);
  pinMode(ledPin, OUTPUT);
// start the handshake
  while (Serial.available() <= 0) {
    digitalWrite(LED_BUILTIN, HIGH); // on blink when waiting for serial data
    Serial.println("0,0"); // sending a starting message 
    delay(300);            // waiting for the delar
  }
}
void loop() 
{
  // wait for data from p5 before doing something
    while (Serial.available()) 
    {
    digitalWrite(LED_BUILTIN, HIGH); // led on while receiving data
    int brightness = Serial.parseInt(); //get slider value from p5
    Serial.println(brightness); //just to view the value
    
     if (Serial.read() == '\n') {
       analogWrite(ledPin, brightness); // will set brightness of LED
     
      }else
      {
        digitalWrite(LED_BUILTIN, HIGH);
      }
    }
}

P5 Code

//Exercise 2 - P5js Code
let slider;
function setup() {
   createCanvas(400, 400); // Creating canvas of 400x400 pixels
  slider = createSlider("0, 255, 0");
  slider.position(100, height/2); // Set the position of the slider
  slider.style('width', '80px'); // Set the width of the slider 
 
  
  noStroke(); // No stroke for the ellipse initially
}
function draw() {
  
  background(255); // Refresh background on each frame
  
  if (!serialActive) {
    text("Press Space Bar to select Serial Port", 20, 30);
  } else {
    text("Connected", 20, 30);}
}
function keyPressed() {
  if (key == " ") {
    // setting the serial connection!!
    setUpSerial();
  }   
}
// this callback function
function readSerial(data) {
    ////////////////////////////////////
    //READ FROM ARDUINO HERE
    ////////////////////////////////////
    //////////////////////////////////
    //SEND TO ARDUINO HERE (handshake)
    //////////////////////////////////
    console.log(slider.value());
    let sendToArduino = slider.value() + "\n";
    writeSerial(sendToArduino);
  
}

Video Demonstration

 

Schematic

Exercise 3: BI-DIRECTIONAL COMMUNICATION

Every time the ball bounces one led lights up and then turns off, potentiometer is used as the analog sensor to control the wind.

Arduino Code

//Exercise 3 Arduino Code

const int poten_pin = A0;
const int ledPin = 2;
void setup() {
 Serial.begin(9600); // Start serial communication at 9600 bps
 pinMode(LED_BUILTIN, OUTPUT);
 pinMode(ledPin, OUTPUT);
 pinMode(poten_pin, INPUT);
 // start the handshake
 while (Serial.available() <= 0) {
   digitalWrite(LED_BUILTIN, HIGH); // on/blink while waiting for serial data
   Serial.println("0,0"); // send a starting message
   delay(300);            // wait 1/3 second
   digitalWrite(LED_BUILTIN, LOW);
   delay(50);
 }
}
void loop()
{
 // wait for data from p5 before doing something
   while (Serial.available())
   {
     digitalWrite(LED_BUILTIN, HIGH);
     digitalWrite(ledPin, LOW);
//read the position of ball from p5
     int position = Serial.parseInt();
  
     if (Serial.read() == '\n') {
       // Read potentiometer value
     int sensorValue = analogRead(poten_pin);
     //send value to p5
     Serial.println(sensorValue);
     }
//if ball is touching the ground i.e. height is zero, turn LED on
     if (position == 0)
     {
       digitalWrite(ledPin, HIGH);
     }
     else{
       digitalWrite(ledPin, LOW);
     }
   }
     digitalWrite(LED_BUILTIN, LOW);
   }

p5 Code

//Exercise 3 - P5js Code

let velocity;
let gravity;
let position;
let acceleration;
let breeze;
let drag = 0.99;
let mass = 50;
let heightOfBall = 0;
function setup() {
  createCanvas(640, 360); // Create a canvas of 800x400 pixels
 
  noFill();
  position = createVector(width/2, 0);
  velocity = createVector(0,0);
  acceleration = createVector(0,0);
  gravity = createVector(0, 0.5*mass);
  breeze = createVector(0,0); 
}
function draw() {
  background(215);
  fill(0);
  
  if (!serialActive) {
    text("Press the space bar to select the serial Port", 20, 30);
  }
  else 
  {
    text("Arduino is connected! Press b to jump.", 20, 30);
  
  applyForce(breeze);
  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;
    
    heightOfBall = 0;
    
    } 
    else {
      heightOfBall = 1;
    }
  }
}
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 (key == " ") {
    // important to have in order to start the serial connection!!
    setUpSerial();
  }   
  else if (key=='b'){
    mass=random(15,80);
    position.y=-mass;
    velocity.mult(0);
  }
}
// this callback function
function readSerial(data) {
    ////////////////////////////////////
    //READ FROM ARDUINO HERE
    ////////////////////////////////////
  
     if (data != null) {
    // make sure there is actually a message
    
    let fromArduino = split(trim(data), ",");
    
       // if the right length, then proceed
    if (fromArduino.length == 1) {
//sensor value is the input from potentiometer
      let sensorVal = int(fromArduino[0]);
      
//potentiometer value ranges from 0 - 1023
//for values less than 400,wind blows to right
      if (sensorVal < 400){
        breeze.x=1
      }
//if value between 400 and 500, wind stops so ball stops
      else if(sensorVal >= 400 && sensorVal < 500){
        breeze.x = 0
      }
//if value greater than 500, wind blows to left
      else {
        breeze.x = -1
      }
          //////////////////////////////////
          //SEND TO ARDUINO HERE (handshake)
          //////////////////////////////////
    }
//height of ball sent to arduino to check if ball on floor or not
    let sendToArduino = heightOfBall  + "\n";
    writeSerial(sendToArduino);
  }
}

Schematic

Video Demonstration

 

 

Reading Reflection – Week 12

I clearly remember from one of the core classes I had taken that disability is made. For example, if you have visual problems, you can wear glasses. Now, you don’t have any disability. Thus, society has the power to change the discomfort we experience every day. By simply installing ramps instead of stairs, you are making someone undisabled. Everyone has some discomforts in life. Before, contacting someone was very difficult and time-consuming. So, someone invented the telephone to resolve that problem. Until then, people were not able to contact each other easily. I am trying to say that disability is not something special that cannot be resolved. Like the everyday problems we face today, disability can be solved with simple design. That is the power of design.

As the author says, disability inspires design; every single constraint we have in life can be a motivation to make something that can simplify our actions. I believe that design for disability is not a small market that should be ignored but rather a market that can inspire so many good designs for a larger population. As I have said before, we make disability. Every single design can actually solve disability. Just as ramps have replaced steps to aid those who cannot use stairs, various other design innovations can transform daily challenges into seamless activities. This transformative potential of design demonstrates its role not just in accommodating but in enabling and empowering individuals, thus reshaping our understanding of what it means to live with a disability.

Final Project – Draft 1

Idea Proposal & Inspiration

For the final project, my goal is to create digital musical instruments. My inspiration came from GarageBand which is an application found on Apple devices. For me, I used this app to play the piano. While this app met my desire to play the piano, I always wished the app provided more instruments. For instance, if I want to play the guitar online, I had to download a separate application. This created inconvenience and took up a lot of storage on my device. Therefore, the product of this project will allow the users to play the instrument of their choice on one interface.

Components

Main materials: p5, Arduino, potentiometer, buttons, and speaker.

I will be using potentiometer to allow the users to control the volume of the sound that is projected through the speaker and buttons to play the musical notes. These components will be connected to the Arduino.

I will be using p5 to display the interface. On the screen, options of instruments will be displayed and once the user chooses an instrument, a zoom-in shot of the instrument will be depicted.

Something like this:

For the interaction or the handshake between Arduino and p5, when the user selects an instrument by clicking on the screen, p5 will send this information to Arduino and call up the sound file that corresponds to the selection. Then when the user presses a button, the corresponding sound will be played through Arduino.

Other Thoughts

As of now, the instruments that I am thinking of include piano, drum, flute and guitar. However, this will depend on the availability of the sound files.

My concern for this project is that my project is heavy code based. I see myself spending a lot of time on coding and I hope I don’t encounter a lot of difficulties with the code.

Assignment 8: Handshake Exercises

Partner: Hyein Kim

EXERCISE 01: ARDUINO TO P5 COMMUNICATION: 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.

To complete this exercise, we built a simple circuit as illustrated below. We used the photocell to control the horizontal movement of the ball in p5.

Exercise 1 Illustration

As it is shown in the code for Arduino, most of it is similar to that of the one provided to the class. The things we changed are mostly done inside the void loop(). Since the Arduino is sending information to p5, we readjusted the code so that data is sent unidirectionally to p5: the value collected in A0 from the photocell is sent to p5.

Arduino code:

int leftLedPin = 2;
int rightLedPin = 5;


void setup() {
 // Start serial communication so we can send data
 // over the USB connection to our p5js sketch
 Serial.begin(9600);


 // We'll use the builtin LED as a status output.
 // We can't use the serial monitor since the serial connection is
 // used to communicate to p5js and only one application on the computer
 // can use a serial port at once.
 pinMode(LED_BUILTIN, OUTPUT);


 // Outputs on these pins
 pinMode(leftLedPin, OUTPUT);
 pinMode(rightLedPin, OUTPUT);


 // Blink them so we can check the wiring
 digitalWrite(leftLedPin, HIGH);
 digitalWrite(rightLedPin, HIGH);
 delay(200);
 digitalWrite(leftLedPin, LOW);
 digitalWrite(rightLedPin, LOW);


 // start the handshake
 while (Serial.available() <= 0) {
   digitalWrite(LED_BUILTIN, HIGH); // on/blink while waiting for serial data
   Serial.println("0,0"); // send a starting message
   delay(300);            // wait 1/3 second
   digitalWrite(LED_BUILTIN, LOW);
   delay(50);
 }
}


void loop() {
 // wait for data from p5 before doing something
     int sensor = analogRead(A0);
     delay(5);
     Serial.println(sensor);
 }

On p5, we drew an ellipse and initialized a variable ‘xposition’ that is used to move the horizontal position of the ball. Then under ‘if (data != null) {}’, we set the xposition = data where data refers to the value that is collected and sent from Arduino. This data is used to change the xposition of the ball in p5. 

p5 code:

let rVal = 0;
let alpha = 255;
let xposition = 100;


function setup() {
  createCanvas(640, 480);
  textSize(18);
}


function draw() {
  // one value from Arduino controls the background's red color
  background(map(rVal, 0, 1023, 0, 255), 255, 200);


  ellipse(xposition, height/2, 50, 50);
  
  // the other value controls the text's transparency value
  fill(255, 0, 255, map(alpha, 0, 1023, 0, 255));


  if (!serialActive) {
    text("Press Space Bar to select Serial Port", 20, 30);
  } else {
    text("Connected", 20, 30);
    // Print the current values
    text('rVal = ' + str(rVal), 20, 50);
    text('alpha = ' + str(alpha), 20, 70);
  }


function keyPressed() {
  if (key == " ") {
    // important to have in order to start the serial connection!!
    setUpSerial();
  }
}


// This function will be called by the web-serial library
// with each new *line* of data. The serial library reads
// the data until the newline and then gives it to us through
// this callback function
function readSerial(data) {
  ////////////////////////////////////
  //READ FROM ARDUINO HERE
  ////////////////////////////////////


  if (data != null) {
    // make sure there is actually a message
    // split the message
    xposition = data;
    }


    //////////////////////////////////
    //SEND TO ARDUINO HERE (handshake)
    //////////////////////////////////
    let sendToArduino = left + "," + right + "\n";
    writeSerial(sendToArduino);
  }

EXERCISE 02: P5 TO ARDUINO COMMUNICATION: Make something that controls the LED brightness from p5.

For this exercise, we utilized the position of mouseX from p5 to control the brightness of the LED on Arduino. The circuit we made looks like this: 

circuit 2

Exercise 2 Illustration

Here, Arduino receives information from p5 and changes the brightness of the LED. Under void loop(), we used the map function to convert the values to PWM range and used analogWrite to set the LED brightness according to the value received from p5. 

Arduino Code:

int LEDpin = 3;  // Ensure this pin supports PWM
void setup() {
 Serial.begin(9600);
 pinMode(LED_BUILTIN, OUTPUT);
 pinMode(LEDpin, OUTPUT);


 // Initial blink to confirm working setup
 digitalWrite(LEDpin, HIGH);
 delay(200);
 digitalWrite(LEDpin, LOW);


 // Wait for initial data before proceeding
 while (Serial.available() <= 0) {
   digitalWrite(LED_BUILTIN, HIGH);  // Blink LED to indicate waiting for connection
   Serial.println("0,0");  // Send a starting message
   delay(300);
   digitalWrite(LED_BUILTIN, LOW);
   delay(50);
 }
}


void loop() {
 if (Serial.available() > 0) {
   digitalWrite(LED_BUILTIN, HIGH);  // LED on while receiving data
   int bright = Serial.parseInt();
   bright = map(bright, 0, 640, 0, 255);  // Adjust received value to PWM range


   if (Serial.read() == '\n') {
     analogWrite(LEDpin, bright);  // Set LED brightness
   }
   digitalWrite(LED_BUILTIN, LOW);  // Turn off status LED after handling data
   Serial.println(0);
 }
}

In p5, we used mouseX and its position on the canvas to control the brightness of the LED on Arduino. We initialized a variable LEDbright to 0 but then let it change according to the if statement. If mouseX <= width && mouseX >= 0 && mouseY <= height && mouseY >= 0 , then the variable LEDbright is mouseX and this data is then sent to Arduino which controls the brightness of the LED. However, if the condition is not satisfied, then the variable LEDbright remains 0. Simply put, the LED lights up brighter when the mouse is on the right side of the screen and dimmer when it is on the left side of the screen. 

p5 code:

let LEDbright = 0;

function setup() {
  createCanvas(640, 480);
  textSize(18);
}

function draw() {
  
  background(205);

  // the other value controls the text's transparency value
  fill(0)

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

  }

  // when clicked, digital LED will turn on,
  // other analog write LED will have brightness corresponding to the height of the mouse when it is press. can be pressed and dragged for controlling brightness
  if (mouseX <= width && mouseX >= 0 && mouseY <= height && mouseY >= 0) {
      LEDbright = mouseX;
  } else {
    LEDbright = 0;
  }
}

function keyPressed() {
  if (key == " ") {
    // important to have in order to start the serial connection!!
    setUpSerial();
  }
}

function readSerial(data) {
  ////////////////////////////////////
  //READ FROM ARDUINO HERE
  ////////////////////////////////////

    //////////////////////////////////
    //SEND TO ARDUINO HERE (handshake)
    //////////////////////////////////
    
    //send the posiiton of mouseY when clicked to control brightness
    let sendToArduino = LEDbright + "\n";
    writeSerial(sendToArduino);

}

EXERCISE 03: BI-DIRECTIONAL COMMUNICATION: 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.

To complete this assignment, we used a potentiometer as an input to control wind and an LED as an output controlled by the bouncing ball in p5.js.

Exercise 3 Illustration

p5 code:

let velocity;
let gravity;
let position;
let acceleration;
let wind;
let drag = 0.99;
let mass = 50;
let light = 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(255);
  applyForce(wind);
  applyForce(gravity);
  velocity.add(acceleration);
  velocity.mult(drag);
  position.add(velocity);
  acceleration.mult(0);
  fill('black')
  
   if (!serialActive) {
    text("Press Space Bar to select Serial Port", 20, 30);
  } else {
    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;
    light=1
    
    }
    else{
      light=0
    }
  }
}

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 (key == " ") {
    // important to have in order to start the serial connection!!
    setUpSerial();
  }
}


function readSerial(data) {
  ////////////////////////////////////
  //READ FROM ARDUINO HERE
  ////////////////////////////////////

  if (data != null) {
    // make sure there is actually a message
    // split the message
    let fromArduino = split(trim(data), ",");
    // if the right length, then proceed
    if (fromArduino.length == 1) {
      // only store values here
      // do everything with those values in the main draw loop
      
      // We take the string we get from Arduino and explicitly
      // convert it to a number by using int()
      // e.g. "103" becomes 103
      
      let sensorValue = int(fromArduino[0]);
      wind.x = map(sensorValue, 0, 1023, -1, 1);
    }
    }
    

    //////////////////////////////////
    //SEND TO ARDUINO HERE (handshake)
    //////////////////////////////////
    let sendToArduino = light + "\n";
    writeSerial(sendToArduino);
  }

Arduino code:

int LEDpin = 2;
int wind = A0;

void setup() {
  // Start serial communication so we can send data
  // over the USB connection to our p5js sketch
  Serial.begin(9600);

  // We'll use the builtin LED as a status output.
  // We can't use the serial monitor since the serial connection is
  // used to communicate to p5js and only one application on the computer
  // can use a serial port at once.
  pinMode(LED_BUILTIN, OUTPUT);

  // Outputs on these pins
  pinMode(LEDpin, OUTPUT);
  pinMode(wind, INPUT);


  // start the handshake
  while (Serial.available() <= 0) {
    digitalWrite(LED_BUILTIN, HIGH); // on/blink while waiting for serial data
    Serial.println("0,0"); // send a starting message
  }
}

void loop() {
  // wait for data from p5 before doing something
  while (Serial.available()) {
    digitalWrite(LED_BUILTIN, HIGH); // led on while receiving data

    int light = Serial.parseInt();
    if (Serial.read() == '\n') {
      digitalWrite(LEDpin, light);
      int sensor = analogRead(A0);
      delay(5);
      Serial.println(sensor);
    }
  }
  digitalWrite(LED_BUILTIN, LOW);
}

To briefly explain this code, every time the ball hits the ground, the variable ‘light’ is set to 1. If this is not the case, ‘light’ is set to 0.

if (!serialActive) {
    text("Press Space Bar to select Serial Port", 20, 30);
  } else {
    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;
    light=1
    
    }
    else{
      light=0
    }
  }
}

Then, p5.js sends the value of ‘light’ to the Arduino.

let sendToArduino = light + "\n";
    writeSerial(sendToArduino);

When the Arduino receives the light value from p5.js, it turns on if the value is 1 and turns off if the value equals 0.

int light = Serial.parseInt();
    if (Serial.read() == '\n') {
      digitalWrite(LEDpin, light);

To control the wind value, if the length of the data sensed by the Arduino is equal to 1, p5.js receives the data value of the potentiometer. We then use the map function to convert the analog input value from 0 to 1023 to a range of -1 to 1.

if (data != null) {
   // make sure there is actually a message
   // split the message
   let fromArduino = split(trim(data), ",");
   // if the right length, then proceed
   if (fromArduino.length == 1) {
     // only store values here
     // do everything with those values in the main draw loop
     
     // We take the string we get from Arduino and explicitly
     // convert it to a number by using int()
     // e.g. "103" becomes 103
     
     let sensorValue = int(fromArduino[0]);
     wind.x = map(sensorValue, 0, 1023, -1, 1);
   }
   }

 

 

Reading Reflection: Week 12

The author gave the market of eyewear as an example in which fashion and disability overlap. As a user of glasses, I used to think that wearing glasses was unfashionable and hence, in a broader sense, thought that disability and fashion were two separate things. However, nowadays, with emphasis on fashion and appearances, disability goes well along with fashion. Therefore, people with bad eyesight look for glasses that not only provide vision but also style. In this way, customers in the eyewear market do not have to stress about giving up either vision or fashion. Furthermore, the eyewear market has expanded so much to the point where people without vision disability wear glasses for fashion. The term “fashion glasses” is used to identify products in the eyewear market that are intended to attract customers who wish to buy glasses for fashion. I think the eyewear market is a great example that shows how incorporating both fashion and disability not only benefits the producers by maximizing their profit but also the customers who obtain clear vision and style. 

Innovating designs for people with disability pushes people to develop various skills. Hearing aid devices, for instance, are being designed for disability where discretion is still a priority. Therefore, many designs try to conceal the devices or make them invisible when in use. Technological miniaturization is constantly used to make devices invisible for the user’s comfort. In this way, in an attempt to create designs for people with disability, technological advancements can be made and new skills can be obtained. One downside, however, of technological advancement is that it is often costly. Therefore, extra effort and time must be invested to bring out the best in the process.

In short, the reading made me realize the embracement of fashion. Fashion designers collaborate with designers who create products for people with disability to allow customers to enjoy comfort and style. Through the exploration of developing designs, new skills and technological advancements can be obtained which is good for both the producers and consumers. The reading helped me appreciate the developments that does not force me to give up one over the other and helped me realize that we can get a hold on both. 

Week 12 Production Hyein Kim & Hayeon Jeong

Partner: Hayeon Jeong

EXERCISE 01: ARDUINO TO P5 COMMUNICATION

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.

To complete this exercise, we built a simple circuit as illustrated below. We used the photocell to control the horizontal movement of the ball in p5. 

As it is illustrated in the code for Arduino, most of it is similar to that of the one provided to the class. The things we changed are mostly done inside the void loop(). Since the Arduino is sending information to p5, we readjusted the code so that data is sent unidirectionally to p5: the value collected in A0 from the photocell is sent to p5.

Arudino Code

int leftLedPin = 2;
int rightLedPin = 5;


void setup() {
 // Start serial communication so we can send data
 // over the USB connection to our p5js sketch
 Serial.begin(9600);


 // We'll use the builtin LED as a status output.
 // We can't use the serial monitor since the serial connection is
 // used to communicate to p5js and only one application on the computer
 // can use a serial port at once.
 pinMode(LED_BUILTIN, OUTPUT);


 // Outputs on these pins
 pinMode(leftLedPin, OUTPUT);
 pinMode(rightLedPin, OUTPUT);


 // Blink them so we can check the wiring
 digitalWrite(leftLedPin, HIGH);
 digitalWrite(rightLedPin, HIGH);
 delay(200);
 digitalWrite(leftLedPin, LOW);
 digitalWrite(rightLedPin, LOW);



 // start the handshake
 while (Serial.available() <= 0) {
   digitalWrite(LED_BUILTIN, HIGH); // on/blink while waiting for serial data
   Serial.println("0,0"); // send a starting message
   delay(300);            // wait 1/3 second
   digitalWrite(LED_BUILTIN, LOW);
   delay(50);
 }
}


void loop() {
 // wait for data from p5 before doing something
     int sensor = analogRead(A0);
     delay(5);
     Serial.println(sensor);
 }

On p5, we drew an ellipse and initialized a variable ‘xposition’ that is used to move the horizontal position of the ball. Then under ‘if (data != null) {}’, we set the xposition = data where data refers to the value that is collected and sent from Arduino. This data is used to change the xposition of the ball in p5. 

let rVal = 0;
let alpha = 255;
let xposition = 100;


function setup() {
  createCanvas(640, 480);
  textSize(18);
}


function draw() {
  // one value from Arduino controls the background's red color
  background(map(rVal, 0, 1023, 0, 255), 255, 200);


  ellipse(xposition, height/2, 50, 50);
  
  // the other value controls the text's transparency value
  fill(255, 0, 255, map(alpha, 0, 1023, 0, 255));


  if (!serialActive) {
    text("Press Space Bar to select Serial Port", 20, 30);
  } else {
    text("Connected", 20, 30);
    // Print the current values
    text('rVal = ' + str(rVal), 20, 50);
    text('alpha = ' + str(alpha), 20, 70);
  }


function keyPressed() {
  if (key == " ") {
    // important to have in order to start the serial connection!!
    setUpSerial();
  }
}


// This function will be called by the web-serial library
// with each new *line* of data. The serial library reads
// the data until the newline and then gives it to us through
// this callback function
function readSerial(data) {
  ////////////////////////////////////
  //READ FROM ARDUINO HERE
  ////////////////////////////////////


  if (data != null) {
    // make sure there is actually a message
    // split the message
    xposition = data;
    }


    //////////////////////////////////
    //SEND TO ARDUINO HERE (handshake)
    //////////////////////////////////
    let sendToArduino = left + "," + right + "\n";
    writeSerial(sendToArduino);
  }

 

EXERCISE 02: P5 TO ARDUINO COMMUNICATION

Make something that controls the LED brightness from p5.

For this exercise, we utilized the position of mouseX from p5 to control the brightness of the LED on Arduino. The circuit we made looks like this: 

circuit 2

 

Here, Arduino receives information from p5 and changes the brightness of the LED. Under void loop(), we used the map function to convert the values to PWM range and used analogWrite to set the LED brightness according to the value received from p5. 

ARDUINO CODE

int LEDpin = 3;  // Ensure this pin supports PWM
void setup() {
 Serial.begin(9600);
 pinMode(LED_BUILTIN, OUTPUT);
 pinMode(LEDpin, OUTPUT);


 // Initial blink to confirm working setup
 digitalWrite(LEDpin, HIGH);
 delay(200);
 digitalWrite(LEDpin, LOW);


 // Wait for initial data before proceeding
 while (Serial.available() <= 0) {
   digitalWrite(LED_BUILTIN, HIGH);  // Blink LED to indicate waiting for connection
   Serial.println("0,0");  // Send a starting message
   delay(300);
   digitalWrite(LED_BUILTIN, LOW);
   delay(50);
 }
}


void loop() {
 if (Serial.available() > 0) {
   digitalWrite(LED_BUILTIN, HIGH);  // LED on while receiving data
   int bright = Serial.parseInt();
   bright = map(bright, 0, 640, 0, 255);  // Adjust received value to PWM range


   if (Serial.read() == '\n') {
     analogWrite(LEDpin, bright);  // Set LED brightness
   }
   digitalWrite(LED_BUILTIN, LOW);  // Turn off status LED after handling data
   Serial.println(0);
 }
}

In p5, we used mouseX and its position on the canvas to control the brightness of the LED on Arduino. We initialized a variable LEDbright to 0 but then let it change according to the if statement. If mouseX <= width && mouseX >= 0 && mouseY <= height && mouseY >= 0 , then the variable LEDbright is mouseX and this data is then sent to Arduino which controls the brightness of the LED. However, if the condition is not satisfied, then the variable LEDbright remains 0. Simply put, the LED lights up brighter when the mouse is on the right side of the screen and dimmer when it is on the left side of the screen. 

P5.JS CODE

let LEDbright = 0;

function setup() {
  createCanvas(640, 480);
  textSize(18);
}

function draw() {
  
  background(205);

  // the other value controls the text's transparency value
  fill(0)

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

  }

  // when clicked, digital LED will turn on,
  // other analog write LED will have brightness corresponding to the height of the mouse when it is press. can be pressed and dragged for controlling brightness
  if (mouseX <= width && mouseX >= 0 && mouseY <= height && mouseY >= 0) {
      LEDbright = mouseX;
  } else {
    LEDbright = 0;
  }
}

function keyPressed() {
  if (key == " ") {
    // important to have in order to start the serial connection!!
    setUpSerial();
  }
}

function readSerial(data) {
  ////////////////////////////////////
  //READ FROM ARDUINO HERE
  ////////////////////////////////////

    //////////////////////////////////
    //SEND TO ARDUINO HERE (handshake)
    //////////////////////////////////
    
    //send the posiiton of mouseY when clicked to control brightness
    let sendToArduino = LEDbright + "\n";
    writeSerial(sendToArduino);

}

EXERCISE 03: BI-DIRECTIONAL COMMUNICATION

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

To complete this assignment, we used a potentiometer as an input to control wind and an LED as an output controlled by the bouncing ball in p5.js.

P5.JS CODE

let velocity;
let gravity;
let position;
let acceleration;
let wind;
let drag = 0.99;
let mass = 50;
let light = 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(255);
  applyForce(wind);
  applyForce(gravity);
  velocity.add(acceleration);
  velocity.mult(drag);
  position.add(velocity);
  acceleration.mult(0);
  fill('black')
  
   if (!serialActive) {
    text("Press Space Bar to select Serial Port", 20, 30);
  } else {
    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;
    light=1
    
    }
    else{
      light=0
    }
  }
}

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 (key == " ") {
    // important to have in order to start the serial connection!!
    setUpSerial();
  }
}


function readSerial(data) {
  ////////////////////////////////////
  //READ FROM ARDUINO HERE
  ////////////////////////////////////

  if (data != null) {
    // make sure there is actually a message
    // split the message
    let fromArduino = split(trim(data), ",");
    // if the right length, then proceed
    if (fromArduino.length == 1) {
      // only store values here
      // do everything with those values in the main draw loop
      
      // We take the string we get from Arduino and explicitly
      // convert it to a number by using int()
      // e.g. "103" becomes 103
      
      let sensorValue = int(fromArduino[0]);
      wind.x = map(sensorValue, 0, 1023, -1, 1);
    }
    }
    

    //////////////////////////////////
    //SEND TO ARDUINO HERE (handshake)
    //////////////////////////////////
    let sendToArduino = light + "\n";
    writeSerial(sendToArduino);
  }

ARDUINO CODE

int LEDpin = 2;
int wind = A0;

void setup() {
  // Start serial communication so we can send data
  // over the USB connection to our p5js sketch
  Serial.begin(9600);

  // We'll use the builtin LED as a status output.
  // We can't use the serial monitor since the serial connection is
  // used to communicate to p5js and only one application on the computer
  // can use a serial port at once.
  pinMode(LED_BUILTIN, OUTPUT);

  // Outputs on these pins
  pinMode(LEDpin, OUTPUT);
  pinMode(wind, INPUT);


  // start the handshake
  while (Serial.available() <= 0) {
    digitalWrite(LED_BUILTIN, HIGH); // on/blink while waiting for serial data
    Serial.println("0,0"); // send a starting message
  }
}

void loop() {
  // wait for data from p5 before doing something
  while (Serial.available()) {
    digitalWrite(LED_BUILTIN, HIGH); // led on while receiving data

    int light = Serial.parseInt();
    if (Serial.read() == '\n') {
      digitalWrite(LEDpin, light);
      int sensor = analogRead(A0);
      delay(5);
      Serial.println(sensor);
    }
  }
  digitalWrite(LED_BUILTIN, LOW);
}

 

To briefly explain this code, every time the ball hits the ground, the variable ‘light’ is set to 1. If this is not the case, ‘light’ is set to 0.

if (!serialActive) {
    text("Press Space Bar to select Serial Port", 20, 30);
  } else {
    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;
    light=1
    
    }
    else{
      light=0
    }
  }
}

Then, p5.js sends the value of ‘light’ to the Arduino.

let sendToArduino = light + "\n";
    writeSerial(sendToArduino);

When the Arduino receives the light value from p5.js, it turns on if the value is 1 and turns off if the value equals 0.

int light = Serial.parseInt();
    if (Serial.read() == '\n') {
      digitalWrite(LEDpin, light);

To control the wind value, if the length of the data sensed by the Arduino is equal to 1, p5.js receives the data value of the potentiometer. We then use the map function to convert the analog input value from 0 to 1023 to a range of -1 to 1.

if (data != null) {
   // make sure there is actually a message
   // split the message
   let fromArduino = split(trim(data), ",");
   // if the right length, then proceed
   if (fromArduino.length == 1) {
     // only store values here
     // do everything with those values in the main draw loop
     
     // We take the string we get from Arduino and explicitly
     // convert it to a number by using int()
     // e.g. "103" becomes 103
     
     let sensorValue = int(fromArduino[0]);
     wind.x = map(sensorValue, 0, 1023, -1, 1);
   }
   }