Assignment 11: In Class Exercises (Serial Communication)

Exercise 1 – Moving Ellipse

Prompt: 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

Arduino Code

P5.js Sketch

Exercise 2 – LED Brightness

Prompt: Make something that controls the LED brightness from p5

Arduino Code

P5.js Sketch

Exercise 3 – Bouncing Ball

Prompt: Take the gravity wind example (https://editor.p5js.org/aaronsherwood/sketches/I7iQrNCul) 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

Arduino Code

P5.js Sketch

Assignment 11: Preliminary Concept for Final Project

I want to create a mini pet cat experience! The idea is to build a physical figure of a cat and have it connect to a p5.js sketch which shows the cat’s current mood. Users can pet the cat, and using some sensor (pressure sensor? or flex sensor?), the arduino will send this reading to p5.js and displays the cat’s mood on the screen.

Another way I could implement the cat is if I have it illustrated in p5.js. This way, users can also play yarn with the cat and watch the cat on the screen move to the user’s hand movements (perhaps tracked by an ultrasonic sensor).

This third way of implementation is I think on the harder side to implement, but I could try making a physical figure of a cat and use wheels so that it is able to move. Perhaps I could make the user control this movement using an ultrasonic sensor as well.

Reading Reflection 11: Design Meets Disability

As someone who has been wearing glasses for almost all her life, I never considered it as an assistive device (even though it is, since I would be blind without them). It really just proves how the use of eyewear has become so normalized, and somehow capitalized into this fashion wear. I’m all for it honestly, I love when people get creative with self expression and using a variety of glasses is one of the ways people do so. I think the same can be said about contact lenses. They are technically an assistive device too, yet it is also commonly used to enhance one’s look; another form of self expression.

I really appreciate the comment on simplicity; it reminds me of the saying “less is more.” Sometimes it’s so easy to go overboard with features and always wanting to improve or update a work in progress, but it only ends up messy and overwhelming to work with. So this was a great reminder to keep it simple, because not everything that has extensive features are always considered good; as long as it does what it’s intended to do, I think that’s a success. And sometimes if we focus too much on adding features, we tend to lose track of the original intention, so it’s definitely better to keep it simple and try to not lose sight of what’s intended.

Assignment #9: Serial Communication [in team with Ryan]

Exercise 1.

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

p5 code:

let position;
let mass = 50;
let potValue = 0; 
function setup() {
  createCanvas(640, 360);
  noFill();
  // Initialize position of the ellipse
  position = createVector(width / 2, height / 2);
}
function draw() {
  background(255);
  // Map potentiometer value to horizontal position
  position.x = map(potValue, 0, 1023, 0, width);
  // Keep the ellipse in the middle 
  ellipse(position.x, height / 2, mass, mass);
}
function keyPressed(){
   if (key == " ") { //set up serial
     setUpSerial();
   } 
}
function readSerial(value) {
  potValue = int(value); // Parse the potentiometer value
}

Arduino:

void setup() {
  Serial.begin(9600); // Start serial communication 
}
void loop() {
  int potValue = analogRead(A0); // Read the potentiometer value 
  Serial.println(potValue);     // Send the value to p5.js
  delay(10);                    
}

Exercise 2.

Make something that controls the LED brightness from p5.

p5 code:

function setup() {
  createCanvas(400, 400);
}
function draw() {
  background(225);
  // brightness based on cursor's x position
  let brightness = map(mouseX, 0, width, 0, 255);
  brightness = constrain(brightness, 0, 255); // Ensure brightness stays within range
  // Send brightness value to Arduino if serial is active
  if (serialActive) {
    writeSerial(`${brightness}\n`); 
  }
}
function keyPressed(){
   if (key == " ") { //set up serial
     setUpSerial();
   } 
}
function readSerial(value) {
  potValue = int(value); // Parse the potentiometer value
}

Arduino:

int ledPin = 9; 
int brightness = 0; 
void setup() {
  Serial.begin(9600); // Start serial communication
  pinMode(ledPin, OUTPUT); //LED pin as output
}
void loop() {
  if (Serial.available() > 0) {
    // Read the incoming brightness value
    brightness = Serial.parseInt();
    brightness = constrain(brightness, 0, 255);
    // Set the LED brightness
    analogWrite(ledPin, brightness);
  }
}

Exercise 3.

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.

p5 code:

let velocity;
let gravity;
let position;
let acceleration;
let wind;
let drag = 0.99;
let mass = 50;
let potValue = 0; // potentiometer value
let serialConnected = false; 
let onGround = false; // whether ball is on the ground
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 (!serialConnected) {
    textAlign(CENTER, CENTER);
    fill(0);
    text("Press 'Space' key on the keyboard", width / 2, height / 2);
    return;
  }
  applyForce(wind);
  applyForce(gravity);
  velocity.add(acceleration);
  velocity.mult(drag);
  position.add(velocity);
  acceleration.mult(0);
  
// check for bounce on the x axis
  if (position.x > width - mass / 2) {
    if(!onGround){
    position.x = width - mass / 2; 
    velocity.x *= -0.9;
    }
  }
    else if (position.x < mass / 2) {
      position.x = mass / 2; 
    velocity.x *= -0.9;
    }
  
  // check for bounce on the y axis
if (position.y > height - mass / 2) {
  velocity.y *= -0.9; 
  position.y = height - mass / 2; 
  if (!onGround) {
    sendBounceSignal(); 
    onGround = true; 
  }
} else {
  onGround = false; 
}
  wind.x = map(potValue, 0, 1023, -1, 1); 
  ellipse(position.x, position.y, mass, mass);
  // boundaries on x axis
  if (position.x > width - mass / 2 || position.x < mass / 2) {
    velocity.x *= -0.9; 
  }
}
function applyForce(force) {
  let f = p5.Vector.div(force, mass);
  acceleration.add(f);
}
// bouncing signal to Arduino
function sendBounceSignal() {
  if (serialActive) {
    let sendToArduino = "1\n"; 
    writeSerial(sendToArduino);
  }
}
// receive data from Arduino
function readSerial(data) {
    potValue = int(trim(data)); 
}
// initialize serial connection
function keyPressed() {
  if (key == ' ') {
    mass = random(10,100);
    setUpSerial(); 
    serialConnected = true; 
  }
}
function serialOpened() {
  serialActive = true; 
}

Arduino:

const int potPin = A0; 
const int ledPin = 13; 
int potValue = 0; 
bool ledState;     
void setup() {
  pinMode(ledPin, OUTPUT);
  Serial.begin(9600);
}
void loop() {
  // read the potentiometer value
  potValue = analogRead(potPin);
  // send potentiometer value to p5
  Serial.println(potValue);
  // check for data from p5
  if (Serial.available() > 0) {
    char received = Serial.read(); 
    if (received == '1' && !ledState) {
      // turn on the LED 
      digitalWrite(ledPin, HIGH);
      ledState = true;
      delay(100); 
      // turn off the LED
      digitalWrite(ledPin, LOW);  
    }
    else if (received != '1'){
      ledState = false;
    }
  }
  delay(50); 
}

Video demonstration:

Final Project Concept

After reading the chapter from Graham Pullin’s book Design Meets Disability and thinking about my personal experiences related to this topic, I decided work on an unconventional model of eyeglasses. My final project will be a synthesis on an interactive artwork and an assistive device, inviting audience to think about the stigma around certain types of products for disabled people.

Drawing inspiration from Meta Ray Ban smart glasses,  I want to combine audio with visuals by adding small speakers to the ends of the temples, so that the user can hear the sound clearly only when they wear the product. In terms of visuals, I want to use camera mode in p5.js to detect the eye area of the user, with the help of glasses designed in a specific way to facilitate this. I will be modelling the glasses myself using Rhino and then printing them on 3D printer in order to create a precise structure that would fit desired electronic components. The speakers will be connected to Arduino, which in its turn will be connected to p5.js sketch using serial communication. Depending on the gazing sequences of the user, the visuals on the screen will be changing, depicting eyes of changing sizes. For user’s eye-tracking WebGazer.js library will be used.

From my individual experience and observations, one of the key reasons why people feel awkward about wearing glasses is because of the way they distort the size of their eyes depending on the prescription, hence altering the familiar look of the face. Such minor things are often invisible to strangers, but people wearing glasses can become extremely conscious about this. By providing an exaggerated illustration of such distortion, I wish to draw attention to the way people with disabilities perceive themselves.

Week #11 – Final Project Preliminary

Concept

I have been thinking long on my final idea project and for now I stopped on idea of utilizing my midterm project and adding Arduino circuits to it.

Here is my previous Midterm project

The reason I decided to pursue my Friends Game House project was because I felt there is still room for its improvement in terms of interactivity. For example, I feel like the interfaces for the Ross, Joey, Monica characters can be designed more interestingly with greater room for unusual interactions. Therefore, I thought of transferring these interactions from software to real life. Currently, my focus stays on transferring important details from the Friends series into smaller things that I can build myself or recreate with elements that we learned to use in Arduino.
For example, in Phoebe interface, there is interaction with the user, where he has to press certain keys to voice specific lines of the songs. I think this can be transformed to the buttons on Arduino, especially bigger buttons that I saw in many final projects of previous students.

Here are some ideas that I’ve been noting to myself about the ways I can implement Arduino to the project:

  • Joey’s interface – there was an idea initially that “Joey doesn’t share food”, so I could transfer it to Arduino, by making red LEDs go bright, when somebody is touching the plate with the food.
  • Potentiometer to adjust the volume of the song on Phoebe’s screen or overall if the Friends theme song is implemented on the background.
  • Using motors recreate the scene with umbrellas, so they could spin while the user is playing
    This may contain: a group of people standing next to each other with umbrellas in front of them

Assignment 9 – Serial Communication

Task 1

Prompt: 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.

We decided to approach all the tasks following Christmas style.

P5 Code:
let positionX = 0; 
function setup() {
  createCanvas(600, 600);
  noFill();
}
function draw() {
  background("#bb010b");
  stroke("#ffcf00");
  // maping the values from light sensor to the width of the canvas
  ellipse(map(positionX, 0, 1023, 0, width), height / 2, 100, 100);
  if (!serialActive) {
  // the initial screen of p5, when it is not connected to arduino, this helps to start serial communication
    background("#2d661b");
    stroke("#white");
    textSize(50);
    text("Press Space Bar to select Serial Port", 20, 30, width - 30, 200);
  }
}
function keyPressed() {
  // starting serial communication when space bar is pressed
  if (key == " ") setUpSerial(); 
}
function readSerial(data) {
  if (data != null)
    // ensuring there is actual data, then storing it in a variable
    positionX = int(data);
}
Arduino Code
int lightPin = A0;

void setup() {
Serial.begin(9600);
pinMode(lightPin, INPUT);
}

void loop() {
int sensorValue = analogRead(A0);
Serial.println(sensorValue);
delay(5);
}

Task 2

Prompt: Make something that controls the LED brightness from p5

For this assignment, we decided to control LED brightness using 4 circles/buttons on p5 interface. By pressing different circles, you increased the brightness of LED.

P5 Code 
let LEDbrightness = 0; 
function setup() {
  createCanvas(600, 600);
  background('#2d661b');
  stroke ('#white');
  noFill();
}
function draw() {
  
  if (serialActive){  
  
  //circles-buttons
  circle (150, height/2, 50);
  circle (250, height/2, 50);
  circle (350, height/2, 50);
  circle (450, height/2, 50);
  
  // to understand whether user pressed specific circles, we used distance function. the LED brightness had 4 variations
  if (dist (mouseX, mouseY, 150, height/2) <= 50){
    LEDbrightness = 60;
  }
  if (dist(mouseX, mouseY, 250, height/2)<=50){
    LEDbrightness = 120;
  }
  if (dist(mouseX, mouseY, 350, height/2)<=50){
    LEDbrightness = 180;
  }
  if (dist(mouseX, mouseY, 450, height/2)<=50){
    LEDbrightness = 255;
  }
    }
  
  if (!serialActive) {
    // to understand if serial communication is happening
    textSize(50);
    text ("Press Space Bar to select Serial Port", 20, 30, width-30, 200);
    }
  }
function keyPressed() {
    if (key == " ")
      // starting the serial connection using space bar press
        setUpSerial(); 
}
function readSerial(data) {
  //sending data to arduino
    writeSerial(LEDbrightness);
}

 

Arduino Code
void setup() {
Serial.begin(9600);
pinMode(5, OUTPUT);
}

void loop() {
analogWrite(5, Serial.parseInt());
Serial.println();
}

IMG_9258

Task 3

Prompt: Take the gravity wind example and make it so every time the ball bounces one led lights up and then turns off, and you can control the wind from one analog sensor.

We decided to use light sensor as analog sensor, which controlled the wind on p5 that affected movement of ball.

P5 Code
let position, velocity, acceleration, gravity, wind;
let drag = 0.99,
  mass = 50,
  hasBounced = false;
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);
  textSize(18);
}
function draw() {
  background(255);
  if (!serialActive) {
    background("#2d661b");
    fill("white");
    text("Press F to select Serial Port", 20, 30, width - 30, 200);
  } else {
    applyForce(wind);
    applyForce(gravity);
    velocity.add(acceleration);
    velocity.mult(drag);
    position.add(velocity);
    acceleration.mult(0);
    if (hasBounced) {
      fill("red");
    } else {
      fill("white");
    }
    ellipse(position.x, position.y, mass, mass);
    if (position.y > height - mass / 2) {
      velocity.y *= -0.9; // dampening
      position.y = height - mass / 2;
      if (!hasBounced && abs(velocity.y) > 1) {
        hasBounced = true;
        setTimeout(() => (hasBounced = false), 100);
      }
    }
  }
}
function applyForce(force) {
  let f = p5.Vector.div(force, mass);
  acceleration.add(f);
}
function keyPressed() {
  if (key == " ") {
    mass = 20;
    position.set(width / 2, -mass);
    velocity.mult(0);
    gravity.y = 0.5 * mass;
    wind.mult(0);
  } else if (key == "f") {
    setUpSerial();
  }
}
function readSerial(data) {
  if (data != null) {
    let value = int(trim(data)); 
    wind.x = map(value, 0, 1023, -1, 1);
    let bounceState = 0;
    if (hasBounced) {
      bounceState = 1;
    }
    writeSerial(bounceState + "\n");
  }
}

 

Arduino Code
const int ledPin = 5;
const int lightPin = A0;
void setup() {
    Serial.begin(9600);
    pinMode(ledPin, OUTPUT);
    pinMode(lightPin, INPUT);
    while (Serial.available() <= 0) {
        Serial.println("0"); 
;    }
}
void loop() {
    while (Serial.available()) {
        int ledState = Serial.parseInt(); 
        
        if (Serial.read() == '\n') {
            digitalWrite(ledPin, ledState);
            Serial.println(analogRead(lightPin));
        }
    }
}

 

IMG_9260

Assignment 8 – In-Class Exercises (by Jheel and Linda)

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.

In our solution, the we used a photoresistor to detect the surroundling light level. The ball in the screen then moves to the left when it’s dark and to the right when it’s bright.

Please find the demonstration video here:

Exercise 1

Please find the p5.js sketch here 

let port, reader, writer;
let serialActive = false;

async function getPort(baud = 9600) {
  let port = await navigator.serial.requestPort();
  await port.open({ baudRate: baud });

  // create read & write streams
  textDecoder = new TextDecoderStream();
  textEncoder = new TextEncoderStream();
  readableStreamClosed = port.readable.pipeTo(textDecoder.writable);
  writableStreamClosed = textEncoder.readable.pipeTo(port.writable);

  reader = textDecoder.readable
    .pipeThrough(new TransformStream(new LineBreakTransformer()))
    .getReader();
  writer = textEncoder.writable.getWriter();

  return { port, reader, writer };
}

class LineBreakTransformer {
  constructor() {
    this.chunks = "";
  }

  transform(chunk, controller) {
    this.chunks += chunk;
    const lines = this.chunks.split("\r\n");
    this.chunks = lines.pop();
    lines.forEach((line) => controller.enqueue(line));
  }

  flush(controller) {
    controller.enqueue(this.chunks);
  }
}

async function setUpSerial() {
  noLoop();
  ({ port, reader, writer } = await getPort());
  serialActive = true;
  runSerial();
  loop();
}

async function runSerial() {
  try {
    while (true) {
      const { value, done } = await reader.read();
      if (done) {
        reader.releaseLock();
        break;
      }
      readSerial(value);
    }
  } catch (e) {
    console.error(e);
  }
}

let rVal = 0; // Value from photoresistor

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

function draw() {
  background(245, 245, 200);
  fill(0);

  if (!serialActive) {
    text("Press Space Bar to select Serial Port", 20, 30);
  } else {
    text("Connected", 20, 30);
    text('Photoresistor Value = ' + str(rVal), 20, 50);

    // Map the sensor value to the x-position of the ellipse
    let xPos = map(rVal, 0, 1023, 0, width);
    fill(100, 123, 158);
    ellipse(xPos, height / 2, 50, 50);
  }
}

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

function readSerial(data) {
  if (data != null) {
    let fromArduino = trim(data); // Remove any whitespace
    rVal = int(fromArduino); // Convert the string to an integer
  }
}

Please find the Arduino code here:

void setup() {
  // put your setup code here, to run once:
  Serial.begin(9600);
}


void loop() {
  // put your main code here, to run repeatedly:
  int sensorValue = analogRead (A2);
  Serial.println (sensorValue);
  Serial.write(sensorValue);
  delay (1);
}

EXERCISE 02: P5 TO ARDUINO COMMUNICATION 

Make something that controls the LED brightness from p5.

In our solution, we used an LED whose brightness changes according to the slider value.

  • Please find the demonstration video here

Exercise 2

  • Please find the p5.js sketch here 
let brightness = 0; 
let slider;

function setup() {
  createCanvas(400, 200);
  //make the slider
  slider = createSlider(0, 255, 127); 
  slider.position(10, 10);
  slider.style('width', '300px');

  let serialButton = createButton("Connect to Arduino");
  serialButton.position(10, 50);
  serialButton.mousePressed(setUpSerial);
}

//troubleshoot
function readSerial(data) {
  console.log("Received data:", data); // Log the received data to the console
}

function draw() {
  background(220);
  brightness = slider.value(); 
  fill(0);
  textSize(16);
  text(LED Brightness: ${brightness}, 10, 100);

  // Send brightness value to Arduino via Serial
  if (serialActive) {
    writeSerial(brightness + "\n"); // Append a newline character
  }
}
  • Please find the Arduino code here:
int ledPin = 9; // PWM pin connected to LED

void setup() {
  Serial.begin(9600);
  pinMode(ledPin, OUTPUT);
}

void loop() {
  int bright;

  if (Serial.available() > 0) {
    bright = Serial.parseInt();
    analogWrite(ledPin, bright);
  }
}

EXERCISE 03: BI-DIRECTIONAL COMMUNICATION

Every time the ball bounces one led lights up and then turns off, and you can control the wind from one analog sensor.

  • Please find the p5.js sketch here 
let port, reader, writer;
let serialActive = false;

async function getPort(baud = 9600) {
  let port = await navigator.serial.requestPort();
  await port.open({ baudRate: baud });

  // create read & write streams
  textDecoder = new TextDecoderStream();
  textEncoder = new TextEncoderStream();
  readableStreamClosed = port.readable.pipeTo(textDecoder.writable);
  writableStreamClosed = textEncoder.readable.pipeTo(port.writable);

  reader = textDecoder.readable
    .pipeThrough(new TransformStream(new LineBreakTransformer()))
    .getReader();
  writer = textEncoder.writable.getWriter();

  return { port, reader, writer };
}

class LineBreakTransformer {
  constructor() {
    this.chunks = "";
  }

  transform(chunk, controller) {
    this.chunks += chunk;
    const lines = this.chunks.split("\r\n");
    this.chunks = lines.pop();
    lines.forEach((line) => controller.enqueue(line));
  }

  flush(controller) {
    controller.enqueue(this.chunks);
  }
}

async function setupSerial() {
  noLoop();
  ({ port, reader, writer } = await getPort());
  serialActive = true;
  runSerial();
  loop();
}

async function runSerial() {
  try {
    while (true) {
      const { value, done } = await reader.read();
      if (done) {
        reader.releaseLock();
        break;
      }
      readSerial(value);
    }
  } catch (e) {
    console.error(e);
  }
}


////////////////////////////////////////////////////////////

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


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);
  textSize(16);
}

function draw() {
  background(0);
  
  if (serialActive){
    wind.x = map(windSpeed, 0, 1023, -1, 1);
  }
  applyForce(wind);
  applyForce(gravity);
  velocity.add(acceleration);
  velocity.mult(drag);
  position.add(velocity); 
  acceleration.mult(0);
  ellipse(position.x, position.y, mass, mass);
  console.log("Wind Speed: " + windSpeed); // For debugging

  if (position.y > height - mass / 2) {
    velocity.y *= -0.9; // A little dampening when hitting the bottom
    position.y = height - mass / 2;

    // Send signal to Arduino on bounce
    if (serialActive) {
      sendBounceSignal();
    }
  }

  if (!serialActive) {
    fill(255);
    text("Press SPACE to connect to Serial Port", 20, 30);
  } else {
    fill(0, 255, 0);
    text("Connected to Serial Port", 20, 30);
  }
}

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

function keyPressed() {
  if (keyCode == LEFT_ARROW) {
    wind.x = -1;
  }
  if (keyCode == RIGHT_ARROW) {
    wind.x = 1;
  }
  if (key == " ") {
    if (!serialActive) {
      setupSerial();
    } else {
      mass = 50;
      position.y = -mass;
      velocity.mult(0);
    }
  } 
}

async function setupSerial() {
  try {
    noLoop();
    // ({ port, reader, writer } = await getPort());
    
    port = await navigator.serial.requestPort();
    await port.open({ baudRate: 9600 });
    
    
    // Create a TextDecoderStream to decode incoming bytes to text
    const textDecoder = new TextDecoderStream();
    const readableStreamClosed = port.readable.pipeTo(textDecoder.writable);

    // Create the reader to read from the decoded text stream
    reader = textDecoder.readable
    .pipeThrough(new TransformStream(new LineBreakTransformer())) // Optional: split data by lines
    .getReader();
    
    writer = port.writable.getWriter();
    serialActive = true;
    // Start reading data after successfully opening the port
    runSerial();
    loop();
  } catch (err) {
    console.error("Serial connection failed:", err);
    serialActive = false;
  }
}

function readSerial(data) {
  if (data != null) {
    let fromArduino = trim(data); // Remove any whitespace
    console.log(data);
    if (fromArduino !== "") {
      fromArduino = parseInt(fromArduino, 10);
      windSpeed = int(fromArduino); // Convert the string to an integer
      
    }
  }
}


async function sendBounceSignal() {
  try {
    if (writer) {
      await writer.write(new TextEncoder().encode("bounce\n"));
    }
  } catch (err) {
    console.error("Failed to send bounce signal:", err);
  }
}

  • Please find the Arduino code here:
int ledPin = 13; // LED pin#
int sensorPin = A0;
int windValue;

void setup() {
  pinMode(ledPin, OUTPUT);
  Serial.begin(9600);
  
}

void loop() {
  windValue = analogRead(sensorPin); // Read the sensor value
  Serial.println(windValue); // Send the value to the serial port
  // Serial.write(windValue);
  

  if (Serial.available() > 0) {
    String data = Serial.readStringUntil('\n'); // Read data until newline
    if (data == "bounce") {
      digitalWrite(ledPin, HIGH);
      delay(100); // Keep the LED on for 100ms
      digitalWrite(ledPin, LOW);
    }
  }
}

 

Assignment 9 – Serial Communication

Exercise 1.

p5 code:

let position;
let mass = 50;
let potValue = 0; 


function setup() {
  createCanvas(640, 360);
  noFill();

  // Initialize position of the ellipse
  position = createVector(width / 2, height / 2);

}

function draw() {
  background(255);

  // Map potentiometer value to horizontal position
  position.x = map(potValue, 0, 1023, 0, width);

  // Keep the ellipse in the middle 
  ellipse(position.x, height / 2, mass, mass);
}

function keyPressed(){
   if (key == " ") { //set up serial
     setUpSerial();
   } 
}

function readSerial(value) {
  potValue = int(value); // Parse the potentiometer value
}

Arduino Code:

void setup() {
  Serial.begin(9600); // Start serial communication 
}

void loop() {
  int potValue = analogRead(A0); // Read the potentiometer value 
  Serial.println(potValue);     // Send the value to p5.js
  delay(10);                    
}

Exercise 2.

p5 code:

function setup() {
  createCanvas(400, 400);
}

function draw() {
  background(225);

  // brightness based on cursor's x position
  let brightness = map(mouseX, 0, width, 0, 255);
  brightness = constrain(brightness, 0, 255); // Ensure brightness stays within range

  // Send brightness value to Arduino if serial is active
  if (serialActive) {
    writeSerial(`${brightness}\n`); 
  }
}

function keyPressed(){
   if (key == " ") { //set up serial
     setUpSerial();
   } 
}

function readSerial(value) {
  potValue = int(value); // Parse the potentiometer value
}

Arduino Code:

int ledPin = 9; 
int brightness = 0; 

void setup() {
  Serial.begin(9600); // Start serial communication
  pinMode(ledPin, OUTPUT); //LED pin as output
}

void loop() {
  if (Serial.available() > 0) {
    // Read the incoming brightness value
    brightness = Serial.parseInt();
    brightness = constrain(brightness, 0, 255);

    // Set the LED brightness
    analogWrite(ledPin, brightness);
  }
}

Exercise 3.

p5 code:

let velocity;
let gravity;
let position;
let acceleration;
let wind;
let drag = 0.99;
let mass = 50;
let potValue = 0; // potentiometer value
let serialConnected = false; 
let onGround = false; // whether ball is on the ground

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 (!serialConnected) {
    textAlign(CENTER, CENTER);
    fill(0);
    text("Press 'Space' key on the keyboard", width / 2, height / 2);
    return;
  }

  applyForce(wind);
  applyForce(gravity);
  velocity.add(acceleration);
  velocity.mult(drag);
  position.add(velocity);
  acceleration.mult(0);
  
// check for bounce on the x axis
  if (position.x > width - mass / 2) {
    if(!onGround){
    position.x = width - mass / 2; 
    velocity.x *= -0.9;
    }
  }
    else if (position.x < mass / 2) {
      position.x = mass / 2; 
    velocity.x *= -0.9;
    }
  
  // check for bounce on the y axis
if (position.y > height - mass / 2) {
  velocity.y *= -0.9; 
  position.y = height - mass / 2; 
  if (!onGround) {
    sendBounceSignal(); 
    onGround = true; 
  }
} else {
  onGround = false; 
}

  wind.x = map(potValue, 0, 1023, -1, 1); 
  ellipse(position.x, position.y, mass, mass);

  // boundaries on x axis
  if (position.x > width - mass / 2 || position.x < mass / 2) {
    velocity.x *= -0.9; 
  }
}

function applyForce(force) {
  let f = p5.Vector.div(force, mass);
  acceleration.add(f);
}

// bouncing signal to Arduino
function sendBounceSignal() {
  if (serialActive) {
    let sendToArduino = "1\n"; 
    writeSerial(sendToArduino);
  }
}

// receive data from Arduino
function readSerial(data) {
    potValue = int(trim(data)); 
}

// initialize serial connection
function keyPressed() {
  if (key == ' ') {
    mass = random(10,100);
    setUpSerial(); 
    serialConnected = true; 
  }
}

function serialOpened() {
  serialActive = true; 
}

Arduino code:

const int potPin = A0; 
const int ledPin = 13; 
int potValue = 0; 
bool ledState;     

void setup() {
  pinMode(ledPin, OUTPUT);
  Serial.begin(9600);
}

void loop() {
  // read the potentiometer value
  potValue = analogRead(potPin);

  // send potentiometer value to p5
  Serial.println(potValue);

  // check for data from p5
  if (Serial.available() > 0) {
    char received = Serial.read(); 

    if (received == '1' && !ledState) {
      // turn on the LED 
      digitalWrite(ledPin, HIGH);
      ledState = true;
      delay(100); 
      // turn off the LED
      digitalWrite(ledPin, LOW);  
    }
    else if (received != '1'){
      ledState = false;
    }
  }
  delay(50); 
}

Video demonstration:

 

 

Week 11 Exercises

Exercise 1:

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

The location of the x of ellipse is being altered by the potentiometer.

The value from the potentiometer is mapped between 0 and 640, the width of the canvas.

Utilizing a Potentiometer, the ellipse moves along the horizontal axis, while also changing colors by making changes to the B value of fill.

Arduino code

P5 code:

let ellipseX = 0; //x value of ellipse to be changed by potentiometer
let B =0;

function setup() {
  createCanvas(640, 480);
  ellipseMode(CENTER);
}

function draw() {
  clear();
  background(0)
  fill(255,0,B);
  ellipse(ellipseX, height/2, 50, 50);


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

function keyPressed() {
  if (key == " ") {
   
    setUpSerial(); //establish serial communication
  }
}

function readSerial(data) {  
  if (data) {    //run only if data is received
    data = data.trim(); // Remove any whitespace
    if (!isNaN(data)) { //check whether data is a number or not
      //debug: console.log("Received:", data);
      ellipseX = int(data);
    }
  }

Exercise 2:

Make something that controls the LED brightness from p5.

A slider is created and data from it is sent to the arduino. Based on the input from the p5 sketch, the LED’s brightness is adjusted accordingly.

Arduino code

P5 code:

let slider;
let brightness = 0;
function setup() {
  createCanvas(400, 400);
  // Create a brightness slider
  slider = createSlider(0, 255, 128);
  slider.position(width/2, height/2);
  slider.style('width', '100px');
}
function draw() {
  background(255);
  if (!serialActive) {
    textAlign(CENTER)
    text("Press Space Bar to select Serial Port", width/2, height/3);
  } else {
    text("Connected", width/2, height/3);
  }
  brightness = slider.value();
}
function keyPressed() {
  if (key == " ") {
    // important to have in order to start the serial connection!!
    setUpSerial();
  }
}
function readSerial(data) {
  console.log(data);
    let dataToSend = brightness + ", \n";
    writeSerial(dataToSend);  
}

Exercise 3:

Take the gravity wind example and make it so every time the ball bounces one led lights up and then turns off, and you can control the wind from one analog sensor.

Using a potentiometer mapped from -2 to 2, when the potentiometer is towards the left, the wind blows towards the left, and vice versa. The LED lights up every time the ball touches the bottom edge of the canvas.

A serial signal is sent to arduino everytime the ball touches the bottom of the canvas, resulting in the led to light up on the arduino. The potentiometer’s value will be reflected in the direction that the wind is blowing on the ball. I also added two walls on the right and left sides of the canvas, to prevent the wind from blowing the ball outside of the canvas.

Arduino code

P5 code:

let led;
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);
  applyForce(wind);
  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;
    
    
    if(serialActive){
      writeSerial("bounced\n");
    }
    }
  // Check for collisions with the left wall
  if (position.x < mass / 2) {
    velocity.x =0; // Reverse horizontal velocity (bounce)
    position.x = mass / 2; // Correct position
  }

  // Check for collisions with the right wall
  if (position.x > width - mass / 2) {
    velocity.x =0; // Reverse horizontal velocity (bounce)
    position.x = width - mass / 2; // Correct position
  }
}

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();
  }
  if (keyCode==DOWN_ARROW){
    //mass=random(15,80);
    position.y=-mass;
    velocity.mult(0);
  }
}


function readSerial(data){
  
  if (data != null){
    wind.x=int(data);
    console.log("working");

  }
}