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);
}

 

Leave a Reply