Final Project – “Interactive NYUAD Campus Explorer”

Concept

Since my midterm project was related to our campus, I wanted to work on something similar for the final project. I came up with the idea to create an interactive NYUAD campus explorer. I thought it would be a great project to showcase the beauty and resourcefulness of our campus.

My project consists of a physical 3D model of our campus and a p5.js sketch that provides information about individual buildings.

https://editor.p5js.org/hk3863/full/5MT2OTbHL

Code

The first thing the user sees is the “MAINPAGE” function, where serial communication begins.

 

 background(mainpage)
  fill('white')
  textSize(width / 20);
  textAlign(CENTER, CENTER);
  textFont(boldFont);
  text("INTERACTIVE \nNYUAD \nCAMPUS EXPLORER", width / 4, height / 2);
  
  textSize(width / 30)
  textFont(regularFont);
  mainpage_message = "PRESS SPACEBAR TO START \nSERIAL COMMUNICATION"
  text(mainpage_message, width / 4, height / 1.2);
  
  if (serialcommunication == "TRUE") {
    mainpage_message = "CLICK TO START";
  }
}

Afterward, the user sees the ID explanation page, where the narrator welcomes them to NYUAD and explains how the virtual tour works. I used the subscription logic from this source (https://editor.p5js.org/hk3863/sketches/OSSNouhkg ), but I’ve adjusted the texts and timings to fit my project.

An essential and creative aspect of this project is the NYU ID card, which is required to access buildings on the NYUAD campus. I’ve used an RFID sensor to replicate the ID card.

When the user clicks on the page, they’re taken to the instruction page, where they can press buttons for specific buildings to obtain information. Here’s the interesting part: after pressing a button, they must scan their ID card to access the information, just as they would when using their ID card to enter buildings.

 

My model includes five buttons, each linked to a page with information about a building: Campus Center, Dining Halls, Research Buildings, Residences, and the Arts Center. Each page includes photographs and buttons to navigate to the next or previous photo.

function information() {
 
  background(87, 6, 140);
  imageMode(CENTER);
  textAlign(CENTER, CENTER);
  
  textSize(width / 15)
  textFont(boldFont);
  text(title, width / 2, height / 12);
  image(photo[i], imageCenterX, imageCenterY, picturesWidth, picturesHeight);

  fill('white');
  noStroke();

  // Right Triangle Button
  triangle(rightXBase + width / 50, imageCenterY, rightXBase, imageCenterY - height / 40, rightXBase, imageCenterY + height / 40);

  // Left Triangle Button
  triangle(leftXBase - width / 50, imageCenterY, leftXBase, imageCenterY - height / 40, leftXBase, imageCenterY + height / 40);
  

  imageMode(CENTER);
  image(photo[i], width * 0.3, height * 0.5, picturesWidth, picturesHeight);
  
  textAlign(LEFT, CENTER);
  textSize(width / 50)
  textFont(regularFont);
  text(information_text, width * 0.6, height * 0.5)
  
  textAlign(CENTER, CENTER);
  textSize(width / 30);
  textFont(boldFont);
  text('PRESS THE BUTTONS OF OTHER BUILDINGS', width / 2, height * 0.9)  

}

Arduino

My Arduino code is sending two types of data. The first is the digital input from the buttons. I’ve created arrays so that when a specific button is pressed, the button number is sent to p5.js, which then triggers the relevant function about that particular building. The second data type comes from the RFID sensor. I watched several tutorials on YouTube to understand how RFID works. In my code, you’ll see that when the tag name of my card is detected by the RFID sensor, the sensor sends a “1” to p5.js, granting access to the information.

#include <SPI.h>
#include <MFRC522.h>

// RFID Setup
#define SS_PIN 10
#define RST_PIN 9
MFRC522 mfrc522(SS_PIN, RST_PIN);  // Create MFRC522 instance

// Button Setup
const int buttonPins[] = {2, 3, 4, 5, 6};  // Digital pins for buttons
const int numButtons = sizeof(buttonPins) / sizeof(buttonPins[0]);
bool lastButtonState[numButtons] = {0};

// RFID Access Card UID
const String AUTHORIZED_CARD_UID = "70 91 42 55";
bool isAuthorized = false;
int cardAccessStatus = 0;
int buttonPressed = -1;

void setup() {
  // Initialize Serial Communication
  Serial.begin(9600);

  // Initialize RFID Reader
  SPI.begin();
  mfrc522.PCD_Init();


  // Initialize Button Pins (Input Mode, assuming external pull-down resistors)
  for (int i = 0; i < numButtons; i++) {
    pinMode(buttonPins[i], INPUT);
  }
}

void loop() {
  // Check RFID Access
  checkRFID();

  // Process Button Presses
  checkButtons();

  // Send Combined Data
  Serial.print(buttonPressed);
  Serial.print(",");
  Serial.println(cardAccessStatus);

  // Reset button state only if no button is currently pressed
  if (buttonPressed != -1) {
    buttonPressed = -1;
  }

  delay(100);  // Debounce delay
}

void checkRFID() {
  // Look for new cards
  if (!mfrc522.PICC_IsNewCardPresent()) {
    return;
  }
  // Select one of the cards
  if (!mfrc522.PICC_ReadCardSerial()) {
    return;
  }
  // Show UID on Serial Monitor
  String content = "";
  for (byte i = 0; i < mfrc522.uid.size; i++) {
    content.concat(String(mfrc522.uid.uidByte[i] < 0x10 ? " 0" : " "));
    content.concat(String(mfrc522.uid.uidByte[i], HEX));
  }

  content.toUpperCase();
  Serial.println("UID tag: " + content);

  // Check if the card is authorized
  if (content.substring(1) == AUTHORIZED_CARD_UID) {
    isAuthorized = true;
    cardAccessStatus = 1;  // Set to 1 for authorized access
    isAuthorized = false;
  } else {
    isAuthorized = false;
    cardAccessStatus = 0;  // Set to 0 for denied access
  }
}

void checkButtons() {
  for (int i = 0; i < numButtons; i++) {
    // Button logic without pull-ups: HIGH = Button pressed
    bool currentButtonState = digitalRead(buttonPins[i]) == HIGH;
    if (currentButtonState != lastButtonState[i]) {
      lastButtonState[i] = currentButtonState;
      if (currentButtonState) {
        buttonPressed = i;  // Store the pressed button index
      }
    }
  }
}

Circuit

What I Am Proud Of

I am particularly proud of creating the physical 3D model. It was my first time using Illustrator and laser cutting, and it was exciting to see the results. Through this project, I learned how to use Illustrator to turn my ideas into reality. Additionally, I’m happy I tried using a new sensor (RFID), which wasn’t covered in class. I believe it aligns well with the project’s concept.

Further Improvements

Because I didn’t have enough time, I couldn’t paint the campus model. However, with more time, I believe I could have made this model much more beautiful. Additionally, I couldn’t include information about some buildings, such as D1, so I decided to combine D2 and D1.

Overall, I am satisfied with the project’s outcome and pleased that I tried several new things and learned so much from this experience.

IM Show

A lot of people came to see my project! I really enjoyed the experience of presenting my work to others. Through this, I was able to identify some bugs I hadn’t noticed before. People loved the 3D model of the campus I created. They suggested it could be used for Marhaba or campus tours.

Final Project Proposal

My final project idea is to create a virtual tour of the NYUAD campus. This interactive tour will serve as a unique introduction to our campus for incoming students, new students, and faculty. The project will consist of three components: a physical 3D campus map, miniature figure, and an informational page featuring photographs on p5.js.

I will create a physical 3D model of our campus based on the campus map.

Using laser cutting, I will create several layers based on the map and then assemble them to form the buildings. Each building will have an RFID sensor at the entrance.

Users will utilize a miniature figure equipped with an RFID magnet sensor to interact with these buildings. When the user places the miniature figure in front of a building, the p5.js application will display photographs and information about that specific building.

The information page on p5.js will be designed as follows:

In summary, the functions of the Arduino and p5.js in this project are as follows:

– Arduino: Manages sensor inputs located in front of each building.

– p5.js: Displays photographs and information about the building when the sensors send data.

Reading Reflection – Week 12

I clearly remember from one of the core classes I had taken that disability is made. For example, if you have visual problems, you can wear glasses. Now, you don’t have any disability. Thus, society has the power to change the discomfort we experience every day. By simply installing ramps instead of stairs, you are making someone undisabled. Everyone has some discomforts in life. Before, contacting someone was very difficult and time-consuming. So, someone invented the telephone to resolve that problem. Until then, people were not able to contact each other easily. I am trying to say that disability is not something special that cannot be resolved. Like the everyday problems we face today, disability can be solved with simple design. That is the power of design.

As the author says, disability inspires design; every single constraint we have in life can be a motivation to make something that can simplify our actions. I believe that design for disability is not a small market that should be ignored but rather a market that can inspire so many good designs for a larger population. As I have said before, we make disability. Every single design can actually solve disability. Just as ramps have replaced steps to aid those who cannot use stairs, various other design innovations can transform daily challenges into seamless activities. This transformative potential of design demonstrates its role not just in accommodating but in enabling and empowering individuals, thus reshaping our understanding of what it means to live with a disability.

Week 12 Production Hyein Kim & Hayeon Jeong

Partner: Hayeon Jeong

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.

To complete this exercise, we built a simple circuit as illustrated below. We used the photocell to control the horizontal movement of the ball in p5. 

As it is illustrated in the code for Arduino, most of it is similar to that of the one provided to the class. The things we changed are mostly done inside the void loop(). Since the Arduino is sending information to p5, we readjusted the code so that data is sent unidirectionally to p5: the value collected in A0 from the photocell is sent to p5.

Arudino Code

int leftLedPin = 2;
int rightLedPin = 5;


void setup() {
 // Start serial communication so we can send data
 // over the USB connection to our p5js sketch
 Serial.begin(9600);


 // We'll use the builtin LED as a status output.
 // We can't use the serial monitor since the serial connection is
 // used to communicate to p5js and only one application on the computer
 // can use a serial port at once.
 pinMode(LED_BUILTIN, OUTPUT);


 // Outputs on these pins
 pinMode(leftLedPin, OUTPUT);
 pinMode(rightLedPin, OUTPUT);


 // Blink them so we can check the wiring
 digitalWrite(leftLedPin, HIGH);
 digitalWrite(rightLedPin, HIGH);
 delay(200);
 digitalWrite(leftLedPin, LOW);
 digitalWrite(rightLedPin, LOW);



 // 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
     int sensor = analogRead(A0);
     delay(5);
     Serial.println(sensor);
 }

On p5, we drew an ellipse and initialized a variable ‘xposition’ that is used to move the horizontal position of the ball. Then under ‘if (data != null) {}’, we set the xposition = data where data refers to the value that is collected and sent from Arduino. This data is used to change the xposition of the ball in p5. 

let rVal = 0;
let alpha = 255;
let xposition = 100;


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


function draw() {
  // one value from Arduino controls the background's red color
  background(map(rVal, 0, 1023, 0, 255), 255, 200);


  ellipse(xposition, height/2, 50, 50);
  
  // the other value controls the text's transparency value
  fill(255, 0, 255, map(alpha, 0, 1023, 0, 255));


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


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


// This function will be called by the web-serial library
// with each new *line* of data. The serial library reads
// the data until the newline and then gives it to us through
// this callback function
function readSerial(data) {
  ////////////////////////////////////
  //READ FROM ARDUINO HERE
  ////////////////////////////////////


  if (data != null) {
    // make sure there is actually a message
    // split the message
    xposition = data;
    }


    //////////////////////////////////
    //SEND TO ARDUINO HERE (handshake)
    //////////////////////////////////
    let sendToArduino = left + "," + right + "\n";
    writeSerial(sendToArduino);
  }

 

EXERCISE 02: P5 TO ARDUINO COMMUNICATION

Make something that controls the LED brightness from p5.

For this exercise, we utilized the position of mouseX from p5 to control the brightness of the LED on Arduino. The circuit we made looks like this: 

circuit 2

 

Here, Arduino receives information from p5 and changes the brightness of the LED. Under void loop(), we used the map function to convert the values to PWM range and used analogWrite to set the LED brightness according to the value received from p5. 

ARDUINO CODE

int LEDpin = 3;  // Ensure this pin supports PWM
void setup() {
 Serial.begin(9600);
 pinMode(LED_BUILTIN, OUTPUT);
 pinMode(LEDpin, OUTPUT);


 // Initial blink to confirm working setup
 digitalWrite(LEDpin, HIGH);
 delay(200);
 digitalWrite(LEDpin, LOW);


 // Wait for initial data before proceeding
 while (Serial.available() <= 0) {
   digitalWrite(LED_BUILTIN, HIGH);  // Blink LED to indicate waiting for connection
   Serial.println("0,0");  // Send a starting message
   delay(300);
   digitalWrite(LED_BUILTIN, LOW);
   delay(50);
 }
}


void loop() {
 if (Serial.available() > 0) {
   digitalWrite(LED_BUILTIN, HIGH);  // LED on while receiving data
   int bright = Serial.parseInt();
   bright = map(bright, 0, 640, 0, 255);  // Adjust received value to PWM range


   if (Serial.read() == '\n') {
     analogWrite(LEDpin, bright);  // Set LED brightness
   }
   digitalWrite(LED_BUILTIN, LOW);  // Turn off status LED after handling data
   Serial.println(0);
 }
}

In p5, we used mouseX and its position on the canvas to control the brightness of the LED on Arduino. We initialized a variable LEDbright to 0 but then let it change according to the if statement. If mouseX <= width && mouseX >= 0 && mouseY <= height && mouseY >= 0 , then the variable LEDbright is mouseX and this data is then sent to Arduino which controls the brightness of the LED. However, if the condition is not satisfied, then the variable LEDbright remains 0. Simply put, the LED lights up brighter when the mouse is on the right side of the screen and dimmer when it is on the left side of the screen. 

P5.JS CODE

let LEDbright = 0;

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

function draw() {
  
  background(205);

  // the other value controls the text's transparency value
  fill(0)

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

  }

  // when clicked, digital LED will turn on,
  // other analog write LED will have brightness corresponding to the height of the mouse when it is press. can be pressed and dragged for controlling brightness
  if (mouseX <= width && mouseX >= 0 && mouseY <= height && mouseY >= 0) {
      LEDbright = mouseX;
  } else {
    LEDbright = 0;
  }
}

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

function readSerial(data) {
  ////////////////////////////////////
  //READ FROM ARDUINO HERE
  ////////////////////////////////////

    //////////////////////////////////
    //SEND TO ARDUINO HERE (handshake)
    //////////////////////////////////
    
    //send the posiiton of mouseY when clicked to control brightness
    let sendToArduino = LEDbright + "\n";
    writeSerial(sendToArduino);

}

EXERCISE 03: BI-DIRECTIONAL COMMUNICATION

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

To complete this assignment, we used a potentiometer as an input to control wind and an LED as an output controlled by the bouncing ball in p5.js.

P5.JS CODE

let velocity;
let gravity;
let position;
let acceleration;
let wind;
let drag = 0.99;
let mass = 50;
let light = 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);
  applyForce(wind);
  applyForce(gravity);
  velocity.add(acceleration);
  velocity.mult(drag);
  position.add(velocity);
  acceleration.mult(0);
  fill('black')
  
   if (!serialActive) {
    text("Press Space Bar to select Serial Port", 20, 30);
  } else {
    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;
    light=1
    
    }
    else{
      light=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();
  }
}


function readSerial(data) {
  ////////////////////////////////////
  //READ FROM ARDUINO HERE
  ////////////////////////////////////

  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
      
      // We take the string we get from Arduino and explicitly
      // convert it to a number by using int()
      // e.g. "103" becomes 103
      
      let sensorValue = int(fromArduino[0]);
      wind.x = map(sensorValue, 0, 1023, -1, 1);
    }
    }
    

    //////////////////////////////////
    //SEND TO ARDUINO HERE (handshake)
    //////////////////////////////////
    let sendToArduino = light + "\n";
    writeSerial(sendToArduino);
  }

ARDUINO CODE

int LEDpin = 2;
int wind = A0;

void setup() {
  // Start serial communication so we can send data
  // over the USB connection to our p5js sketch
  Serial.begin(9600);

  // We'll use the builtin LED as a status output.
  // We can't use the serial monitor since the serial connection is
  // used to communicate to p5js and only one application on the computer
  // can use a serial port at once.
  pinMode(LED_BUILTIN, OUTPUT);

  // Outputs on these pins
  pinMode(LEDpin, OUTPUT);
  pinMode(wind, 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
  }
}

void loop() {
  // wait for data from p5 before doing something
  while (Serial.available()) {
    digitalWrite(LED_BUILTIN, HIGH); // led on while receiving data

    int light = Serial.parseInt();
    if (Serial.read() == '\n') {
      digitalWrite(LEDpin, light);
      int sensor = analogRead(A0);
      delay(5);
      Serial.println(sensor);
    }
  }
  digitalWrite(LED_BUILTIN, LOW);
}

 

To briefly explain this code, every time the ball hits the ground, the variable ‘light’ is set to 1. If this is not the case, ‘light’ is set to 0.

if (!serialActive) {
    text("Press Space Bar to select Serial Port", 20, 30);
  } else {
    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;
    light=1
    
    }
    else{
      light=0
    }
  }
}

Then, p5.js sends the value of ‘light’ to the Arduino.

let sendToArduino = light + "\n";
    writeSerial(sendToArduino);

When the Arduino receives the light value from p5.js, it turns on if the value is 1 and turns off if the value equals 0.

int light = Serial.parseInt();
    if (Serial.read() == '\n') {
      digitalWrite(LEDpin, light);

To control the wind value, if the length of the data sensed by the Arduino is equal to 1, p5.js receives the data value of the potentiometer. We then use the map function to convert the analog input value from 0 to 1023 to a range of -1 to 1.

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
     
     // We take the string we get from Arduino and explicitly
     // convert it to a number by using int()
     // e.g. "103" becomes 103
     
     let sensorValue = int(fromArduino[0]);
     wind.x = map(sensorValue, 0, 1023, -1, 1);
   }
   }

Final Project Brief – “Interactive NYUAD Campus Explorer”

My goal is to create an interesting way to explore NYUAD. This project will combine physical interactivity with digital technology, providing a unique and engaging way to learn about our campus.

How It works

I am planning to create a tangible, interactive experience with a physical 3D model of the NYUAD campus, where each building is equipped with sensors. Additionally, I will use a small model of a person outfitted with a compatible sensor. When this person model is placed near or inside one of the buildings on the campus model, the sensors will detect its proximity or contact. The Arduino will then send a signal to a computer system, indicating which building the person model has been placed in. This signal will trigger a p5.js application to display specific information about that building on a screen. The displayed information can include textual descriptions, historical facts, photographs, and potentially other multimedia elements.

Purpose and Benefits

When I was accepted to NYUAD, I was curious about the campus buildings, but I could not find much information or photographs of our campus on the internet. Mainly, I wanted to create this project as a unique way for our students, faculty, and prospective students to learn about our campus. Also, this tool is invaluable for orientation programs, helping new students and staff familiarize themselves quickly and effectively with the campus.

Main Challenges

Currently, I am not sure which sensor to use in both the buildings and the miniature person.

Reading Reflection – Week 11

I have always imagined future technology, but the way the author describes the future was very eye-opening. I have always thought of a world with smart technology and screens but never considered that our hands could be essential tools for the future. I agree with the author that we perceive the world through touch. The hand is a tool used every day, helping us navigate our lives. However, today’s reading made me realize that the tactile experience is often overlooked when we use our everyday devices.

As children, we learned about different objects in this world through our tactile sense. This experience of learning through touching and using our hands and bodies has shaped who we are today. Thanks to these experiences, I know how to hold a cup, how to throw a ball, and I am familiar with the feelings of sand, rocks, and water. However, if the children of the future start learning things only through ‘pictures under glass,’ they will not be as well-rounded as we are now. They will miss out on knowing how wonderful the world is.

As the author emphasizes the importance of hands, I truly think that this overlooked issue should be addressed in the future with all possible technological advancements. I want to live in a world where my hands are useful. I want to live in a world where technology offers more than just ‘pictures under glass,’ and where I can truly feel the world.

Week 11 – “Playing Childhood song with Musical Instrument” by Hayeon Jeong and Hyein Kim

Concept

When we were young, we were taught to sing and play instruments to a song called “떴다 떴다 비행기”. This song is about airplanes and with the introduction to airplanes through this song, we learn more about airplanes and dream of riding it one day. Furthermore, when we played as elementary students in the playground, we always sang this song and looked up to the sky to find some airplanes. Now, as older students, playing this song on our instrument reminds us of our childhood in South Korea. 

Circuit

For digital, we used 3 buttons. Each button is connected to the Ground, a 330 ohm resistor and digital input (2, 3, 4). 

For analog, we used a potentiometer and a speaker. The speaker is connected to the Ground and analog input (~9). The potentiometer is connected to 5V, A0, and the Ground. 

Code

We have created a code so that when a button is pressed, the corresponding note is played with a frequency that can be altered up or down by the potentiometer. The constants BASE_NOTE_C4, BASE_NOTE_D4, and BASE_NOTE_E4 are defined at the top of the sketch. To simplify the code, we have used the INPUT_PULLUP function in the ‘setup’ function, which means that the button pin will read HIGH when unpressed and LOW when pressed. 

void setup() {
  for (int i = 0; i < 3; i++) {
    pinMode(buttonPins[i], INPUT_PULLUP); // Setup as pull-up to simplify wiring
  }
  pinMode(buzzerPin, OUTPUT);
}

In the main program loop, the potentiometer’s value is read from ‘potPin’ and mapped from its reading rand (0 to 1023) to a frequency adjustment range of -100 to +100 Hz. The loop checks each button in the buttonPins array to see if it’s pressed (reads LOW due to the pull-up resistor). If a button is pressed, the function playAdjustedTone() is called.

void loop() {
  int frequencyAdjustment = analogRead(potPin); // Read the potentiometer value
  frequencyAdjustment = map(frequencyAdjustment, 0, 1023, -100, 100); // Map the pot value to a frequency range adjustment

  for (int i = 0; i < 3; i++) {
    if (digitalRead(buttonPins[i]) == LOW) { // Check if button is pressed
      playAdjustedTone(i, frequencyAdjustment);
    }
  }
}

We wanted to use the potentiometer to adjust the tone. So we have written the playAdjustedTone() function. It calculates the adjusted frequency for the selected note by adding the frequency adjustment value from the potentiometer to the base frequency of the note. It then uses tone(buzzerPin, adjustedFrequency) to play the adjusted note for 100 milliseconds.

void playAdjustedTone(int noteIndex, int adjustment) {
  int baseFrequencies[] = {BASE_NOTE_C4, BASE_NOTE_D4, BASE_NOTE_E4}; // Base frequencies for C, D, E
  int adjustedFrequency = baseFrequencies[noteIndex] + adjustment; // Adjust the frequency based on potentiometer

  tone(buzzerPin, adjustedFrequency); // Play the adjusted note
  delay(100); // Duration of note
  noTone(buzzerPin); // Stop the tone
}

After playing the note, noTone(buzzerPin) stops the buzzer.

Here is the full version of our code:

// Define frequencies for musical notes C, D, E
#define BASE_NOTE_C4 261
#define BASE_NOTE_D4 294
#define BASE_NOTE_E4 329

// Define pin connections
const int buzzerPin = 9;
const int potPin = A0;
const int buttonPins[] = {2, 3, 4}; // Buttons for C, D, E notes

void setup() {
  for (int i = 0; i < 3; i++) {
    pinMode(buttonPins[i], INPUT_PULLUP); // Setup as pull-up to simplify wiring
  }
  pinMode(buzzerPin, OUTPUT);
}

void loop() {
  int frequencyAdjustment = analogRead(potPin); // Read the potentiometer value
  frequencyAdjustment = map(frequencyAdjustment, 0, 1023, -100, 100); // Map the pot value to a frequency range adjustment

  for (int i = 0; i < 3; i++) {
    if (digitalRead(buttonPins[i]) == LOW) { // Check if button is pressed
      playAdjustedTone(i, frequencyAdjustment);
    }
  }
}

void playAdjustedTone(int noteIndex, int adjustment) {
  int baseFrequencies[] = {BASE_NOTE_C4, BASE_NOTE_D4, BASE_NOTE_E4}; // Base frequencies for C, D, E
  int adjustedFrequency = baseFrequencies[noteIndex] + adjustment; // Adjust the frequency based on potentiometer

  tone(buzzerPin, adjustedFrequency); // Play the adjusted note
  delay(100); // Duration of note
  noTone(buzzerPin); // Stop the tone
}

Reflection

For improvement, we would like to add more buttons so that we can play more musical notes. In this way, the range of songs we can play on the instrument would widen and it would be more entertaining to play along on the instrument. Also, we tried to change the volume of the sound through the potentiometer but was unsuccessful at it. Therefore, for this assignment, we utilized the potentiometer to control the tone instead. In the future, however, we would like to learn and utilize volume control using the potentiometer. 

Week 10 – “Interactive Color Toy”

Concept

After completing my project, I began contemplating a creative concept for it. It occurred to me that if I had a child, I would use this project as a toy to help them quickly learn colors. Consequently, I decided to name this project the “Interactive Color Toy.” Children can use it as a toy, pressing a button to cycle through three colors: red, yellow, and green. Additionally, they can adjust the LED’s brightness using a potentiometer. By pressing the button and changing the brightness, children could easily learn colors through tactile experiences, especially if parents help by naming the colors that appear when the button is pressed.

Circuit

My circuit consists of the following elements:

– Arduino board (e.g., Arduino Uno)

– Potentiometer

– Push button switch

– LED

– Resistors

– Breadboard

– Jumper wires

In this circuit, a potentiometer is connected to an analog input pin of the Arduino, allowing it to read varying voltage levels. A push button is connected to a digital input pin, enabling the Arduino to detect button presses. Three digital output pins are connected to the red, green, and yellow pins of the LED, respectively. By adjusting the potentiometer, users control the brightness of the LED colors, while pressing the button cycles through the available colors.

Code

// Pins
const int POTENTIOMETER_PIN = A0; // Analog input pin for potentiometer
const int BUTTON_PIN = 2; // Digital input pin for push button
const int RED = 5;  // Digital output pin for RGB LED (red)
const int GREEN = 6;  // Digital output pin for RGB LED (green)
const int YELLOW = 9; // Digital output pin for RGB LED (yellow)

// Variables
int potentiometerValue = 0; // Potentiometer value
bool buttonState = false; // Button state
int colorIndex = 0; // Index of current color

void setup() {
  pinMode(POTENTIOMETER_PIN, INPUT);
  pinMode(BUTTON_PIN, INPUT_PULLUP);
  pinMode(RED, OUTPUT);
  pinMode(GREEN, OUTPUT);
  pinMode(YELLOW, OUTPUT);
}

void loop() {
  potentiometerValue = analogRead(POTENTIOMETER_PIN);
  
  // Map potentiometer value to LED brightness
  int brightness = map(potentiometerValue, 0, 1023, 0, 255);
  
  // Set the LED color based on the current color index
  switch (colorIndex) {
    case 0:  // Red
      analogWrite(RED, brightness);
      analogWrite(GREEN, 0);
      analogWrite(YELLOW, 0);
      break;
    case 1:  // Green
      analogWrite(RED, 0);
      analogWrite(GREEN, brightness);
      analogWrite(YELLOW, 0);
      break;
    case 2:  // Yellow
      analogWrite(RED, 0);
      analogWrite(GREEN, 0);
      analogWrite(YELLOW, brightness);
      break;
  }

  // Check button state
  if (digitalRead(BUTTON_PIN) == LOW) {
    if (!buttonState) {
      // Toggle color index
      colorIndex = (colorIndex + 1) % 3;
      buttonState = true;
      delay(200);
    }
  } else {
    buttonState = false;
  }
}

This is my code. The analogRead function reads the value from the potentiometer, which is then mapped to control the brightness of the LED colors. The switch statement selects the appropriate color based on the current color index, and the digitalWrite function sets the brightness of the corresponding LED pins accordingly. When the button is pressed, the color index is incremented to cycle through the available colors.

Improvements and Overview

Overall, I enjoyed this assignment, particularly the aspect of controlling outputs using different physical inputs. The most challenging part was figuring out how the current moved through the circuit. However, I was able to easily determine the correct way to connect all the components. As a further improvement, I considered expanding the color palette by using a full RGB LED instead of individual colors. This would allow for a wider range of colors and more creative possibilities.

Reading Reflection – Week 10

Physical Computing’s Greatest Hits (and Misses)

This reading was particularly informative, offering a wide array of projects within the field of physical computing. Previously, I had never imagined that such diverse and innovative projects were feasible when I first began my journey in this field. Particularly, I was fascinated by the idea of the theremin. This was a project I had wanted to work on when I was enrolled in another class last semester. However, due to my limited knowledge at the time, I couldn’t bring my ideas to reality. Now, equipped with the skills I’ve acquired from our recent classes, I feel confident and excited about the possibility of making this project a reality. The potential to combine electronic components with musical creativity truly captures the essence of what makes physical computing so exciting.

Making Interactive Art: Set the Stage, Then Shut Up and Listen

I really liked the directness and clarity in the title of the article. It reflects a fundamental truth about design: designers are communicators, not merely speakers. They show their thoughts through their creations. As the article discusses, Interactive Art goes beyond traditional boundaries by transforming viewers into active participants. This dynamic completes the artwork, creating a shared authorship between the creator and the audience. My experience last summer in a South Korean museum demonstrated this concept. There, I saw an interactive installation where visitors could draw animals and scan them to integrate their creations into the larger display with a pre-created background. This not only made the artwork dynamic but also personal, as each visitor’s contribution became central to the artistic narrative. It was a vivid demonstration of the profound connection that interactive art can forge, drawing beauty from the synergy between the artist’s vision and the audience’s involvement.

Week 9 Creative Switch – “Step”

Concept

There is a moment where imagination sparks innovation. For me, that moment took me back to the muddy adventures of my childhood. Picture this: a young kid, covered in mud, going back home. It is necessary to turn on the lights without adding to the crime scene. And from this muddy dilemma, an idea was born—a switch that doesn’t need a clean hand but just a simple step.

Progress

I made a simple circuit out of these components: 5V – jumper wire – resistor – jumper wire – LED – Ground. It was easy to make the circuit, however, the key was to create a gap in the circuit, hidden beneath the carpet. This gap was placed between the resistor and the jumper wires, completing the circuit only when pressure was applied. Stepping on the carpet would bridge this gap, lighting up the LED. However, this design came with limitations. The switch was only one-time usable. After activation, the gap in the circuit needed manual resetting for the next use.

Reflection

I enjoyed doing this assignment. Of course, the idea that I came up was very simple. However, I could learn from this assignment that creativity comes from everyday problems, and perhaps the solution could be very simple.