Week 12: Final Project Proposal

For my final project, I decided to bring my midterm project to life and create controllers for the game characters that I designed. If it’s possible, I would like to make two game pads which two players will have to press physically with their feet, which then controls the two characters on the screen. The game pads would be inspired by the video game Dance Dance Revolution (DDR). In addition to the game pads, I was also thinking about adding sound effects using the beeper when the health decreases in the game, the LCD display to depict some artwork or health bar, or the LEDs to give some feedback to the players. I would like to make use of the woodshop, but if time doesn’t permit this idea, I wouldn’t mind scaling down to use the 3D printers or laser cutters.

Some Code Snippet for the Week

const int UP_BUTTON = 11;
const int DOWN_BUTTON = 10;
const int RIGHT_BUTTON = 6;
const int LEFT_BUTTON = 5;

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

  // Set button pins as input with internal pull-up resistors
  pinMode(UP_BUTTON, INPUT_PULLUP); 
  pinMode(DOWN_BUTTON, INPUT_PULLUP);
  pinMode(RIGHT_BUTTON, INPUT_PULLUP);
  pinMode(LEFT_BUTTON, INPUT_PULLUP); 
}

void loop() {
  // Read the state of the UP_BUTTON (HIGH = not pressed, LOW = pressed)
  int upButtonState = digitalRead(UP_BUTTON); 
  int downButtonState = digitalRead(DOWN_BUTTON); 
  int rightButtonState = digitalRead(RIGHT_BUTTON); 
  int leftButtonState = digitalRead(LEFT_BUTTON); 

  // Print the value (HIGH or LOW) to the Serial Monitor
  Serial.print(upButtonState);
  Serial.print(",");
  Serial.print(downButtonState);
  Serial.print(",");
  Serial.print(rightButtonState);
  Serial.print(",");
  Serial.println(leftButtonState);

}

 

Week 12: Final Project Proposal

Hi everyone! 👋

I have a bit of a better idea now for my final project (though I’m not ruling out the possibility of doing something completely different 😅). I’m not really sure how best to describe it, but simply put, you have the power to manipulate objects with your hands, and you use to protect yourself and fight against a villain, who you must also chase down (a bit of a reference to my midterm).

# Design Description

Arduino:
Inputs:
  • Pressure sensor (inside of a stress ball), for detecting when the player closes their hand.
  • Capacitive touch sensor strip, as a control for firing.
  • Some game state info (from p5)
Outputs:
  • Neopixel (addressable LED strip)
  • Send values of pressure sensor and touch sensor to p5.
Circuit View:

Note: I used a flex sensor in place of the touch sensor as that wasn’t available right now.
Schematic:

Note: I used a flex sensor in place of the touch sensor as that wasn’t available right now.
p5:
Inputs:
  • MoveNet pose detection, to get angle of the player’s hand in relation with the screen.
  • Pressure sensor and touch sensor values from Arduino.
Outputs:
  • The game on screen.
  • Some game state info to the Arduino.

 

Final Project Concept

CONCEPT:

For my final project, I want to incorporate and showcase my interests. One of these interests of mines are penguins. Therefore, I have settled on making an interactive game called ‘Pingu Pounce’. Pingu Pounce is essentially an exhilarating game where players help a plucky penguin fly through icy platforms. With simple physical controls, players will use them to make their penguin leap from one slippery platform to the next, aiming to climb as high as possible while avoiding obstacles like sharp platforms. 

Week 11: In-Class Exercises

Final Video Demonstration can be found here: https://youtu.be/CTLXGrMEBxU

Cover image for this week’s production.
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 following code was utilized for this particular exercise:

let sensorValue = 0; // To store the sensor value from Arduino

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

function draw() {
  background(220);

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

    // Display the sensor value
    text('Sensor Value: ' + sensorValue, 20, 50);

    // Map the sensor value to the horizontal position of the ellipse
    let ellipseX = map(sensorValue, 0, 1023, 0, width);

    // Draw the ellipse in the middle of the canvas vertically
    fill(255, 0, 0);
    ellipse(ellipseX, height / 2, 50, 50);
  }
}

function keyPressed() {
  if (key == " ") {
    setUpSerial(); // Start the serial connection
  }
}

// This function is called by the web-serial library
function readSerial(data) {
  if (data != null) {
    let fromArduino = trim(data); // Trim any whitespace
    if (fromArduino !== "") {
      sensorValue = int(fromArduino); // Convert the sensor value to an integer
    }
  }
}

The following code was used in the Arduino IDE for this exercise:

// 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

int sensorPin = A0; // Single sensor connected to A0

void setup() {
  Serial.begin(9600);
}

void loop() {
  int sensorValue = analogRead(sensorPin); // Read sensor value
  Serial.println(sensorValue); // Send sensor value to p5.js
  delay(50); // Short delay for stability
}

 

Exercise 2:

“make something that controls the LED brightness from p5”

The following code was used to make this exercise come to fruition:

let brightness = 0; // Brightness value to send to Arduino

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

  // Create a slider to control brightness
  slider = createSlider(0, 255, 0);
  slider.position(20, 50);
}

function draw() {
  background(220);

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

    // Display brightness value
    text("Brightness: " + brightness, 20, 90);

    // Update brightness from the slider
    brightness = slider.value();
    
    // Send brightness to Arduino
    writeSerial(brightness + "\n");

  }
}

function keyPressed() {
  if (key == " ") {
    setUpSerial(); // Start the serial connection
  }
}

function readSerial(data) {
  if (data != null) {
    let fromArduino = trim(data); // Trim whitespace
    brightness = int(fromArduino); // Parse data into an integer
  }
}

The following Arduino code was used for this particular exercise:

//make something that controls the LED brightness from p5

int ledPin = 3;

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

void loop() {
  if (Serial.available()) {
    int brightness = Serial.parseInt();
    if (Serial.read() == '\n') {
      brightness = constrain(brightness, 0, 255);
      analogWrite(ledPin, brightness);
      Serial.println(brightness); // Send brightness to p5.js
    }
  }
}

 

Exercise 3:

The following code is an alteration of professor Aaron Sherwood’s code which was used for this exercise:

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

let windSensorValue = 0; // Value from the wind sensor
let connectButton; // Button for connecting to the serial port

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

  position = createVector(width / 2, 0); // Initial position of the ball
  velocity = createVector(0, 0); // Initial velocity
  acceleration = createVector(0, 0); // Initial acceleration
  gravity = createVector(0, 0.5 * mass); // Gravity force
  wind = createVector(0, 0); // Initial wind force

  // Create a button to initiate the serial connection
  connectButton = createButton("Connect to Serial");
  connectButton.position(10, 10);
  connectButton.mousePressed(setUpSerial); // Trigger serial connection on button press
}

function draw() {
  background(255);

  if (!serialActive) {
    text("Click 'Connect to Serial' to start", 20, 50);
    return; // Exit the draw loop until the serial connection is established
  }

  // Map wind sensor value to wind force (affects horizontal movement)
  wind.x = map(windSensorValue, 0, 1023, -1.5, 1.5); // Adjust force range as needed

  // Apply forces
  applyForce(wind); // Apply wind force
  applyForce(gravity); // Apply gravity force

  // Update velocity and position
  velocity.add(acceleration);
  velocity.mult(drag); // Apply drag (friction)
  position.add(velocity);
  acceleration.mult(0); // Reset acceleration

  // Ball bounce logic (vertical boundary)
  if (position.y > height - mass / 2) {
    position.y = height - mass / 2; // Place the ball on the ground
    velocity.y *= -0.9; // Reverse and dampen vertical velocity

    // Notify Arduino to toggle the LED when the ball touches the ground
    writeSerial("1\n"); // Send '1' to Arduino
  } else {
    // Ensure the LED is off when the ball is not touching the ground
    writeSerial("0\n"); // Send '0' to Arduino
  }

  // Draw the ball
  ellipse(position.x, position.y, mass, mass);
}

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

// Reset the ball to the top of the screen when the space key is pressed
function keyPressed() {
  if (key === " ") {
    position.set(width / 2, 0); // Reset position to top center
    velocity.set(0, 0); // Reset velocity to zero
    mass = random(15, 80); // Randomize mass
    gravity.set(0, 0.5 * mass); // Adjust gravity based on new mass
  }
}

// Serial communication: Read sensor value from Arduino
function readSerial(data) {
  if (data != null) {
    let trimmedData = trim(data);
    if (trimmedData !== "") {
      windSensorValue = int(trimmedData); // Read wind sensor value
    }
  }
}

The following code was used in the Arduino IDE to bring this to life:

//gravity wind example
int ledPin = 2;     // Pin connected to the LED
int windPin = A0;   // Analog pin for the potentiometer (A0)

void setup() {
  Serial.begin(9600);        // Start serial communication
  pinMode(ledPin, OUTPUT);   // Set the LED pin as an output
  digitalWrite(ledPin, LOW); // Turn the LED off initially
}

void loop() {
  // Read the analog value from the potentiometer
  int windValue = analogRead(windPin);

  // Send the wind value to p5.js over serial
  Serial.println(windValue);

  // Check if a signal is received from p5.js for the LED
  if (Serial.available()) {
    char command = Serial.read(); // Read the signal from p5.js
    if (command == '1') {
      digitalWrite(ledPin, HIGH); // Turn on the LED when the ball touches the ground
    } else if (command == '0') {
      digitalWrite(ledPin, LOW);  // Turn off the LED
    }
  }

  delay(5); // Small delay for stability
}


The following schematic was used for all 3 of the exercises with slight moderations, provided in class:

Reading Reflection 8

Reuse and Recycle: A reflection on Design Meets Disability

In Design Meets Disability, the idea of trickle-down effects made a lot of sense to me. The tech market’s priorities often align with majority demand, leaving designs for the disabled marginalized in terms of research and funding. Sectors like fashion or mass-market tech get the lion’s share of attention, while solutions for disabilities often lack the investment they deserve.

However, the book highlights a crucial skill for designers: recognizing the applicability of existing technology to new problems. While creating something original is commendable, repurposing an established design can be equally impactful. Legal hurdles, like patents, may limit financial gains from such adaptations, but progress shouldn’t be confined by a competitive or profit-driven mindset. True innovation lies in recognizing the value of existing tools to accelerate development and as designers or artists, we have the benefit of the sky being the limit to our creativity. Thus, repurposing existing technology is never frowned over by our kind as artists have the ability to bring their own touch to any project.

Week 11 – Production Exercises

Exercise 1

  • Drawing an ellipse and making it move horizontally based on photoresistor

Code:

let x=0;

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

function draw() {
  if (serialActive){
    background("white");
    ellipse(map(x,0,1023,0,400),height/2,50,50);
  }else{
    background("white");
    console.log("not connected");
  }
}

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

function readSerial(data) {
  
  if (data != null) {
    x = int(data);
  }else{
    x = 0;
  }
}

//Arduino code
// void setup() {
//     Serial.begin(9600);
//     pinMode(A0, INPUT);
// }

// void loop() {
//   Serial.println(analogRead(A0));
// }

Exercise 2

  • Increase the brightness of the LED with mouse click

Code:

let bright=0;

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

function draw() {
  if (serialActive){
    background("white");
    text(bright,10,10);
  }else{
    background("white");
    console.log("not connected");
  }
}

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

function mousePressed(){
  if(serialActive){
    bright+=1;
    writeSerial(bright);
  }
  
}
function readSerial(data) {
  
}

//Arduino code
// int brightness;
// void setup() {
//     Serial.begin(9600);
//     pinMode(9, OUTPUT);
// }

// void loop() {
//   brightness = Serial.parseInt();
//   analogWrite(9,brightness);
// }

Exercise 3

  • Turning on LED when the ball bounces and use photoresistor to control wind movement

Circuit

Video:

Code:

let velocity;
let gravity;
let position;
let acceleration;
let wind;
let drag = 0.99;
let mass = 50;
let bounce = 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);
  if(!serialActive){
    console.log("PRESS a TO CONNECT");
  }
   else{
    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;
        bounce = 1;
      }else{
        bounce = 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 (keyCode==LEFT_ARROW){
    wind.x=-1;
  }
  if (keyCode==RIGHT_ARROW){
    wind.x=1;
  }
  if (key==' '){
    mass=random(15,80);
    position.y=-mass;
    velocity.mult(0);
  }
   if (key == "a") {
    // important to have in order to start the serial connection!!
    setUpSerial();
  }
}
function readSerial(data) {
  if (data != null) {
        console.log(data);
        wind.x = map(int(data), 0, 1023, -2, 2);
        writeSerial(bounce + '\n');
  }
}

//Arduino code
// int bounce;
// void setup() {
//   Serial.begin(9600);
//   pinMode(9,OUTPUT);
//   while (Serial.available() <= 0) {
//     Serial.println("0"); // send a starting message
//   }
// }

// void loop() {
//   while(Serial.available()){
    
//     bounce = Serial.parseInt();
//     if (Serial.read() == '\n') {
//       digitalWrite(9,bounce);
      
//     }
    
//   }
//   int sensor = analogRead(A1);
//   Serial.println(sensor);
//   // Serial.println(analogRead(A0));
  
// }

 

 

Week 11: In-Class Exercises with Serial Communication

1. Make an ellipse in p5 move on the horizontal axis using only one sensor. Video Link

int leftLedPin = 4;
int rightLedPin = 6;
const int trigPin = 10;
const int echoPin = 9;

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

  // Set up the LED and ultrasonic sensor pins
  pinMode(LED_BUILTIN, OUTPUT);
  pinMode(leftLedPin, OUTPUT);
  pinMode(rightLedPin, OUTPUT);
  pinMode(trigPin, OUTPUT);
  pinMode(echoPin, INPUT);

  // Blink LEDs to check wiring
  digitalWrite(leftLedPin, HIGH);
  digitalWrite(rightLedPin, HIGH);
  delay(200);
  digitalWrite(leftLedPin, LOW);
  digitalWrite(rightLedPin, LOW);
}

void loop() {
  // Check if there is data available from p5.js
  if (Serial.available()) {
    int left = Serial.parseInt();   // Get the left LED value
    int right = Serial.parseInt();  // Get the right LED value

    // Update LEDs based on values from p5.js
    digitalWrite(leftLedPin, left);
    digitalWrite(rightLedPin, right);

    // Clear any remaining characters in the serial buffer (such as '\n')
    Serial.read();
  }

  // Trigger the ultrasonic sensor
  digitalWrite(trigPin, LOW);
  delayMicroseconds(2);
  digitalWrite(trigPin, HIGH);
  delayMicroseconds(10);
  digitalWrite(trigPin, LOW);

  // determine the time for the echo
  long timeTraveled = pulseIn(echoPin, HIGH);

  // the distance in centimeters
  int distance = timeTraveled * 3.4/2;
  
  int sensor = analogRead(A1);

  // Send the distance value to p5.js
  Serial.print(sensor);
  Serial.print(",");
  Serial.println(distance); 

  delay(100);  
}
 2. Control the LED brightness from p5 Video Link

const int blue_LED = 4;
const int red_LED = 6;

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

  // Initalization of LED pins 
  pinMode(blue_LED, OUTPUT);
  pinMode(red_LED, OUTPUT); 

  // Blink LEDs to check wiring
  digitalWrite(blue_LED, HIGH);
  digitalWrite(red_LED, HIGH);
  delay(200);
  digitalWrite(blue_LED, LOW);
  digitalWrite(red_LED, LOW);

}

void loop() {
  // put your main code here, to run repeatedly:
  Serial.println(0);
  if (Serial.available()) {
    int left = Serial.parseInt();   // Get the left LED value
    int right = Serial.parseInt();  // Get the right LED value

    // Update LEDs based on values from p5.js
    digitalWrite(blue_LED, left);
    digitalWrite(red_LED, right);

    // removes remaining characters in the serial buffer
  }
  Serial.read();
  delay(100);
}
3. Gravity and Wind Video Link

const int LED_pin = 6;

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

  // digitalWrite(LED_pin, HIGH);
  // delay(200);
  // digitalWrite(LED_pin, LOW);

}

void loop() {
  // put your main code here, to run repeatedly:
  if (Serial.available()) {
    int LED_value = Serial.parseInt();   // Get the LED value

    // Update LEDs based on values from p5.js
    digitalWrite(LED_pin, LED_value);

    // Clear any remaining characters in the serial buffer (such as '\n')
    Serial.read();
  }
  
  int sensor = analogRead(A0);
  Serial.println(sensor); 
}

 

Final Project Proposal

For my final project, my goal is to build upon my midterm project of bring my game to life. As a reminder, my midterm project was a co-op game which two individuals needed to work together with the WASD and arrow keys to input the right order or combination to proceed to the next level. While the p5 side is mostly complete, I would still need to update the code to communicate with the Arduino and determine sensors for which the Arduino can then communicate with p5.

My end goal is to hopefully build a live, immersive experience which two plays can maybe interact in some fashion to control the characters on screen, defeat the creatures, and proceed to the next level. At the very core, I could have the WASD and arrow keys map certain sensors. On the other hand, I am thinking about using the laser cutter or 3D print to make something visually appealing and fun.

Reading Response 11

For the reading this week, we had to read on the topic of the design of assistive technology and individuals’ opinions on its design and capabilities. Since I don’t typically think task that might be more difficult for someone with a disability, I feel reading on this topic was especially interesting and reminder that simple task may not always be simple. For example, tremors that typically affect the elder cause the involuntarily shaking of the joints. When effected individuals need to eat, write, shower, etc, it oftentimes become difficult because they cannot control the movement of their hands. One assistive technology that aims to tackle the issue is a reactive spoon that remains stable despite extensive shaking or movement.

In the reading, it had mentioned the drive to make assistive tool standard across all individuals with that disability. When I read it, I felt a strong disagreement with that end goal because a disability does not affect everyone the same. As such making a standard tool make not always end up with the right individual and making their lives exponentially better. Not to say tool will not aid them in their daily lives, however certain disabilities require more attention and customization to fit the individuals’ need.

Final Project: Preliminary Idea

Armenian Culture Navigator.

For my final project, I have an idea of making something related to Armenian culture. As of now, I imagine the project as a digital map displayed on p5.js with tactile and sensory inputs facilitated by Arduino. Users can explore iconic Armenian symbols by clicking on them on the map, like the pomegranate, lavash (Armenian bread), and Mount Ararat through engaging tasks which I still have to develop. For instance, the pomegranate can be colored by touching a conductive pad connected to an Arduino sensor. Similarly, users might virtually “stretch” the lavash by pulling on an elastic sensor. To add another layer of interactivity, blowing into a microphone sensor might simulate wind, and make digitally drawn clouds to drift across Mount Ararat on the map.

Areas for development:

I’m thinking about other objects that represent Armenian culture and symbols like the duduk (Armenian musical instrument), or recognisable carpets. I will also need to think about the ways I will build meaningful p5 and Arduino interactions with these symbols.