Exercise 1: The value obtained from the potentiometer makes the ellipse in p5 move on the horizontal axis, in the middle of the screen, and nothing on Arduino is controlled by p5.
p5.js
let rVal = 0; let xPos = 0; let rad = 50; function setup() { createCanvas(400, 400); textSize(18); } function draw() { background(255); if (!serialActive) { text("Press Space Bar to select Serial Port", 20, 30); } else { text("Connected", 20, 30); xPos = map(rVal, 0, 900, 0, 400); // Print the current values text('rVal = ' + str(rVal), 20, 50); ellipse(xPos, 200, rad, rad); text('xPos = ' + str(xPos), 20, 70); } } 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) { let fromArduino = split(trim(data), ","); if (fromArduino.length == 1) { rVal = fromArduino[0]; } ////////////////////////////////// //SEND TO ARDUINO HERE (handshake) ////////////////////////////////// let sendToArduino = 1 + "\n"; writeSerial(sendToArduino); } }
Arduino
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); }
Exercise 2: Change the LED brightness by moving the ellipse on p5.js left or right.
let left = 0; let right = 0; let brightness = 0; let rad = 50; function setup() { createCanvas(400, 400); textSize(18); } function draw() { background(255); if (!serialActive) { text("Press Space Bar to select Serial Port", 20, 30); } else { text("Connected", 20, 30); //the x position of the cirlce will control the brightness of the LED xPos = mouseX; ellipse(xPos, 200, rad, rad); brightness = map(xPos, 0, 400, 0, 255); brightness = int(brightness); // Print the current values text('Brightness = ' + str(brightness), 20, 60); text('xPos = ' + str(xPos), 20, 90); } } 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) { let fromArduino = split(trim(data), ","); if (fromArduino.length == 1) { // we're not getting input from arduino } ////////////////////////////////// //SEND TO ARDUINO HERE (handshake) ////////////////////////////////// let sendToArduino = brightness + "\n"; writeSerial(sendToArduino); } }
Arduino
int ledPin = 5; void setup() { Serial.begin(9600); pinMode(LED_BUILTIN, OUTPUT); pinMode(ledPin, OUTPUT); // 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 int brightness = Serial.parseInt(); if (Serial.read() == '\n') { delay(5); Serial.println("1"); } analogWrite(ledPin, brightness); } digitalWrite(LED_BUILTIN, LOW); }
Exercise 3: Alter the gravity wind example to make the LED light up and turn off every time the ball bounces , and control the wind using potentiometer.
p5.js
let velocity; let gravity; let position; let acceleration; let wind; let drag = 0.99; let mass = 50; 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); 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); 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; isBouncing = 1; } else { isBouncing = 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(); } else if (key == "ENTER") { mass = random(15, 80); position.y = -mass; velocity.mult(0); } } function readSerial(data) { 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 let potValue = int(fromArduino[0]); //change the wind based on the potentiometer value wind.x = map(potValue, 0, 900, -5, 5); } ////////////////////////////////// //SEND TO ARDUINO HERE (handshake) ////////////////////////////////// let sendToArduino = isBouncing + "\n"; writeSerial(sendToArduino); } }
Arduino
int ledPin = 5; const int potPin = A0; void setup() { 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 isBouncing = Serial.parseInt(); if (Serial.read() == '\n') { int potValue = analogRead(potPin); delay(5); Serial.println(potValue); } // Set LED brightness based on whether bouncing. if (isBouncing == 1) { digitalWrite(ledPin, HIGH); } else { digitalWrite(ledPin, LOW); } } digitalWrite(LED_BUILTIN, LOW); }
Final Project Idea
Concept
For the final project, me and Sanjana are thinking of creating a Virtual Fruit Ninja. We want to take the concept of this mobile game to the next level by creating an immersive and interactive game experience allowing players to slice fruits virtually with their hands! The following project and our love for the game fruit ninja is the inspiration for this project: (https://naziafakhruddin.medium.com/gesture-controlled-flower-art-with-ml5-js-posenet-and-p5-js-61b98fa3fc68)
For this project, we are thinking of using the ml5 library, built on top of Tensor.js, and the PoseNet function to accurately track the position of the player’s hand in real time through the camera video. The goal is to create a seamless integration between the player’s hand movements and a virtual sword or blade in the game, simulating the experience of slicing real fruits with a knife.
The game mechanics will be intuitive and engaging. Players can wave their hands across the screen to slice the fruits as they appear, and the PoseNet function will accurately track their hand movements in real time, providing precise and responsive slicing actions. We will also leverage p5.js to create visually appealing graphics and animations, creating an engaging game environment that enhances the overall gameplay experience.
Challenge
One of the main challenges of this project will be optimizing the game’s performance to ensure smooth gameplay and minimize latency. We will need to carefully understand the output of the PoseNet model and use the information to update the virtual sword’s position and orientation in real-time.