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