Week 14: Final Project Documentation — Time Trekker 3000

Concept

For my final project, I decided to make it Club Penguin themed. In the Club Penguin universe, once you join the Secret Agency (basically becoming a spy/secret agent), you get assigned missions from G (Gary the Gadget Guy).
So my project is that G assigned the user to a mission to test out his brand-new invention: The Time Trekker 3000. A time-traveling radio device that lets you tune into music and news from different time periods in history.

You twist the Time Selector (a potentiometer) to pick a decade, and then press one of the two radio stations, either Music or News, to hear what was happening back then. It’s basically a time machine, but make it a radio.
It’s inspired by the whole secret-mission vibe of Club Penguin!

How it Works

The user:
• Twists the potentiometer → chooses an era between the 1940s and the 2020s (with a 20 year difference between decades).
• Press a button → pick a station (Music or News).

The screen updates to show the decade you’re currently “in,” and plays the right audio from that time.

Here’s my P5 Sketch:
Here’s my code on Arduino: FullCode
Circuit Schematic


User Testing (from the IM Show):
Communication Between Arduino & p5.js

The potentiometer sends a stream of values from Arduino → p5.js (through serial communication of course). I map those values to different time periods/decades on the screen, so when you twist the knob, the interface changes and the music/news for that decade becomes available.

The two buttons send HIGH/LOW signals to let p5 know when the player presses “Music” or “News.” In p5, I check those button states and trigger the correct audio files depending on the decade selected.

The potentiometer values also control the LEDs: they light up to show which audio mode is active (Music or News), and the LEDs also change based on the decade.

So both systems talk to each other constantly.

Code Snippets

These are the parts I’m most proud of:

Audio Control

  // audio control between gameModes
if (gameMode === 1) { // We are on the Start Screen
    // 1. starts the start screen music
    if (!startMusic.isPlaying()) {
        startMusic.loop();
    }
    
    // 2. stops ALL main game audio if it's currently playing or exists
    if (currentMusic && currentMusic.isPlaying()) { 
        currentMusic.stop();
    }
    if (currentNews && currentNews.isPlaying()) { 
        currentNews.stop();
    }
} 

else if (gameMode === 2) { // on the main screen
    //stops the start screen mmusic
    if (startMusic.isPlaying()) {
        startMusic.stop();
    }
}

This one was for fixing overlapping music and my biggest headache.  This finally made sure only ONE audio layer plays at a time, which is so satisfying after days of chaos.

Button Switching Logic

// //music and news buttons logic (so they dont overlap and "else if" is important here!!)

 // 1. news button is pressed 
 if (nState === 1 && prevButtonNState === 0) {
   // activates news mode, deactivates music mode
   currentButtonNState = 1;
   currentButtonMState = 0;
 }

 // 2. music button is prressed (the 'else if' ensures that only ONE mode can be activated in a single frame!)
 else if (mState === 1 && prevButtonMState === 0) {
   // Activate Music Mode, Deactivate News Mode
   currentButtonNState = 0;
   currentButtonMState = 1;
 }

 // updates previous states of both buttons (very imp!)
 prevButtonNState = nState;
 prevButtonMState = mState;

Once I figured this part out, I was able to rest for a bit. So here I used each button’s value to check which one is pressed. I used else if here because if the first statement isn’t true, it’ll go through the second code block and make sure it works, and it did!

 Challenges I Faced

Honestly, the biggest challenge in this whole project was sound logic, making sure audio only plays when it’s supposed to. At first, everything was overlapping like crazy, start screen music + main game music + news + music… all at once, the program was going crazy. I had to really think through the logic of stopping whatever is already playing before starting anything new.

Another huge challenge was handling the two buttons and making sure only one “mode” (Music or News) could be active at a time. I solved that by tracking the previous state of each button and updating “current” active states using if statements. That part of the code took me some time to figure out, but I’m super proud of it now because it finally works perfectly. Once I fixed those, everything finally felt like a real interaction. The LEDs, audio, and screen all update correctly with the player’s choices!

I also had a hard time with soldering. I mean I didn’t practice much but it was honestly a disaster at first. But here we are and I’m glad my (current) buttons aren’t fried.

The sound files gave me a hard time as well, p5 would just not load. I had to trim and/or compress some files (even though they weren’t that long) for p5 to be able to handle them. I mean, I get it because I had a LOT of sound files for this project since it relies mainly on sound, but I’m glad I got it working without removing any of my sound files.

Resources Used
  • The Club Penguin UI is edited with self-made graphics for this project
  • All audio clips sourced from public YouTube news/music archives (then trimmed + converted by me)
  • Arduino + p5 Serial communication code is from class resources
How I Used AI Tools

I used AI for help with some parts of the logic that wasn’t working at first, like solving the overlapping audio issue, and creating working arrays for sound files. Everything else like the design, code structure, and media was done by me.

Week 13: Final Project User Testing

User Testing

For user testing, I let my sister test out my project. For this test, I didn’t give her many instructions beforehand, so I could observe how intuitive the system is.

User Testing Video:

 

Observations

My sister was confused at first because the mapping between the physical buttons and the actions on the screen wasn’t obvious.

I had to explain the concept of the project and how the buttons work, which shows I still need to make the controls more self-explanatory. Once explained, she understood the idea of selecting a year and choosing between music or news.

My sister suggested adding a sound effect when the selected decade changes so that the user is aware, she also suggested increasing the value range between the time periods because she felt that they were too close to each other (as seen in the video, she overturned the potentiometer and reached the last time period when she meant to only go to the second one).

She also criticized the play button (plays the music/news) and said that I didn’t really need it since the potentiometer changes the sounds anyway, so it would be redundant. Instead, she suggested having an activation button that “activates” the machine after the start screen.

Overall, it was clear where the experience worked and where it could be improved.

What’s Working Well
  • The music playback is smooth now, with no lag (that was a big issue until an hour ago).
  • The LEDs on the breadboard respond nicely to the potentiometer.
Areas to Improve
  • The “news” button currently requires a long press. I plan to fix this so that a single press triggers the news playback.
  • I want to add a clear response from P5, for example: the LED on the sketch lights up along with the LED on the board.
  • I also need to display the selected year on the P5 screen so that my sister could see what they’ve chosen without instructions.
  • The buttons need labels (“music” and “news”) so users immediately understand their function.
What Needed Explanation

The most confusing part for her was how the selection process works:

  • How the potentiometer selects the year
  • How the buttons choose music or news

To make this more intuitive, I plan to:

  • Clearly display the current year on the P5 sketch
  • Label the buttons on the breadboard
  • Possibly add visual feedback cues (lights, animations) so users know their input is registered
Next Steps
  • Improve the user interface on P5 to show selections clearly
  • Fix the news button to work with a single press
  • Add more intuitive labeling and feedback on the hardware
  • Look for more audio files to make the selection more vast

User testing was extremely helpful: it showed me what’s intuitive, what needs clarification, and how the experience can be improved for someone using it for the first time.

Week 12: Final Project Proposal (New Idea) and Progress

Concept

Soo I ended up not doing any of my initial ideas (oops) because I came up with a more exciting one today while talking to my sister. Basically, this project will be an interactive time machine (of some sort) that lets the user travel to different years using physical controls, and choose to either play real music or news from that selected time period/year. My project is inspired by the computer game Club Penguin, specifically the game feature where the player completes missions as a spy for the PSA (Penguin Secret Agency) and uses gadgets to solve tasks. Similarly, my concept is that the player/user is assigned a mission to test out a new prototype time machine. (I’m also making the main screen kind of look like the start screen of the minigame Aqua Grabber in Club Penguin.)

Arduino and P5 Communication

These are the components I’m going to use in my project:

  • 2 buttons, where one button selects the music, and the other selects the news broadcast.
  • A potentiometer, chooses the user’s preferred year/time period that shows up on the screen.
  • One more button, kind of acts like a start button, which will play the sounds of music of news after either one is selected by the user.
  • 5 Green LEDs, each LED lights up just like the ones on the screen will.

Just to be clear, the potentiometer is the time period/year selector, and the buttons select either music or news to be played.

The main interface of this project will look like the start screen of one of the minigames in Club Penguin called Aqua Grabber, which looks like this:

Arduino to P5 Communication

Every time the potentiometer’s value changes by 100, the sketch on P5 will change the green lights (as shown in the picture) to the next one. So the first light is initially lit up since the potentiometer’s value is 0, and once it reaches 100, it changes to the next one (goes from left to right).

P5 to Arduino Communication

The specific green LED that’s lit up on the sketch on P5 will also trigger the corresponding green LED on the breadboard to light up as well.

How it Works
  1. User turns the potentiometer and chooses a time period/year
  2. P5 lights up the corresponding green light on the sketch
  3. Arduino lights the matching green LED on the breadboard
  4. User presses either the “music” or “news” button
  5. User presses the “start” button
  6. P5 plays music/news from the selected year/time period
Project Progress So Far

I worked on the Arduino part of it first. I attached 5 green LEDs and a potentiometer. As I explained before, the LEDs light up when the potentiometer’s value is within that specific LED’s range.

Here’s the code I created on Arduino IDE: FullCode

Here’s a video of it:

Week 11: Preliminary Concept for Final Project

For my final project, I’m currently deciding between two game concepts. I’m still brainstorming and working on the overall ideas, so since I haven’t fully decided what to go with yet, I’m documenting both possible directions.

Concept 1 — Rhythm Game

This concept is based on rhythm games like Dance Dance Revolution, but turned into a tabletop physical controller. Instead of tapping keys on a keyboard, players interact with physical buttons connected to an Arduino that trigger actions in p5.js.

Interaction (How it Works)

On the p5.js screen, colored notes fall from the top to the bottom. The player has 4–6 physical push buttons arranged in a row, each one corresponding to a lane on the screen. When a falling note reaches the bottom marker, the player must press the matching physical button at the right moment.

The game gives immediate feedback, such as:

  • Perfect hits respond with a sound and/or visual flash
  • A miss is indicated with a red flash
  • The score updates in real time

Arduino Components

  • 4–6 push buttons
  • 1 potentiometer

The potentiometer will control the difficulty level by adjusting the speed of the falling notes (higher difficulty = faster notes).

I like this idea because I think people will naturally want to try it, and it’s generally easy to understand without needing much explanation.

 

Concept 2 — Wizard Duel (Mashing Game)

This concept is a 2-player competitive game inspired by Harry Potter wand duels and by games like “Wizard” on 1-2-Switch. Each player has a physical button, and the faster they mash their button, the more they push their spell beam toward the opponent.

Interaction (How it Works)

The p5.js screen shows two wizards on opposite sides. Player 1 has one button, Player 2 has another. When the game starts (using a separate start/reset button):

  • Both players mash their button as fast as possible
  • The faster player pushes the spell beam toward the opposite side
  • If the beam reaches Player 2’s side, Player 1 wins
  • If it reaches Player 1’s side, Player 2 wins

Arduino Components

  • 1 button to start/reset
  • 2 buttons (one for each player to mash)

I might also add LEDs for each player that flash with every mash (not 100% sure yet, I’ll see what works best). I’m also open to adding more components if it makes the game more interesting.

I like this idea because I love competitive games, especially mashing games. I used to play them all the time on game consoles with my sisters.

 

Conclusion

I still need to decide which concept I’ll fully commit to (and who knows, I might even change my entire idea by next week). Over the next few days, I’ll prototype small parts of each idea to see which one feels more engaging and fun for me to complete.

Reading Reflection — Week 11

After reading Design Meets Disability, I noticed how it sheds light on an ongoing issue with how society views disabilities. The author explains how when design and disability meet, the outcome is always the most intricate and interesting. It’s an opportunity for designers to test out their skills in both creativity and functionality.

I loved the section where he criticizes designers for making many assistive technology (AT) devices, like hearing aids and prosthetics, hidden. I also believe that disabilities should not be shamed, but embraced. By prioritizing the concealment of these devices, we are discouraging disabled individuals rather than empowering them, making them feel like outsiders instead of supporting them. By making AT more visible and beautifully designed, I believe designers can help change how people perceive disabilities.

The idea to bring engineers and designers together (‘solving’ and ‘exploring’) to create AT devices is brilliant because the result will be assistive technologies that are both useful and inspiring. I also think designers will be very useful in coming up with a comfortable device for users, since they’ll be wearing or using them all day (sometimes all night).

I absolutely agree with the enforcement of universal design, meaning designing products that are usable by as many people as possible, which of course also includes people with disabilities. The author mentions that rather than making a device for a very specific disability only, we could make devices with designs that are simple enough to be broadly adapted but smart enough to serve people with different needs. Overall, I believe this approach to design makes devices more accessible and more human.

Week 11: Serial Communication (Mariam and Mohammed)

Exercise 1: Arduino to P5 Communication

For this exercise, we used a potentiometer as the analog sensor. The potentiometer controls the ellipse’s position on the horizontal axis in the P5 sketch. When you turn it one way, the ellipse moves to the right, turning it the other way causes it to move left.

We added a little text at the top of the sketch that displays the sensor value. As the value increases, the ellipse moves to the right, and vice versa.

Link to code: Exercise1_FullCode

Schematic
 
Circuit Design

Demo Video

Exercise 2: P5 to Arduino Communication

Here, we used the keyboard arrow keys to change the LED brightness. Pressing the right arrow increases the brightness, and the left arrow decreases it.

Link to code: Exercise2_FullCode

Schematic

Demo Video

Exercise 3: Bi-directional Communication

For the Arduino to P5 communication, the potentiometer acts like the “wind” in the gravity/wind example. As you turn it, the ball gets pushed left or right depending on the mapped value.

For the P5 to Arduino communication, every time the ball hits the bottom and bounces, it triggers the LED to briefly turn on and then off, so the LED flashes in sync with each bounce.

Link to code: Exercise3_FullCode

Schematic

Demo Video

Reading Reflection – Week 10

Bret Victor’s rant on the future of technology had a very interesting take on technological design for the future, which made me realize the things we often ignore. He mentions how a glass screen completely misses the purpose of what our hands can do, which is to feel and manipulate, and how future interaction designs seem to neglect that entirely by reducing interaction to swiping fingers across a flat screen.

Honestly, I can’t help but agree with him on this, but I also find it difficult to come up with a clear solution to this problem. Designing future technology in the “Pictures Under Glass” way is probably the easiest way to do so, which is likely why it became the default design. If we did take the abilities of our hands into account, depending on the purpose of the device you’re using, the design would differ drastically from one to another, making it extremely complex. Although I do agree with Victor’s frustration, I also think his critique shows how difficult innovation can be once a certain design dominates the industry.

In his follow-up, Victor admits that he didn’t offer a solution because the purpose of his rant was to encourage research rather than provide answers. I actually respect his honesty, it made his rant look more like an invocation rather than a complaint. I’m on board with his criticism to limiting designs and to instead imagine new possibilities of greater ones. Even though we don’t yet know what a “dynamic tactile medium” will look like, I think Victor’s ideas push us as readers to think deeply about how our bodies and technology should work together.

Week 10: Musical Instrument (Ling and Mariam)

Concept

For this assignment, I worked together with Ling to create an instrument using the ultrasonic sensor. He came up with the idea to use the distance sensor, and the way we executed it reminded me of a theremin because there’s no physical contact needed to play the instrument. We also used a red button to turn the instrument on and off, as well as a green button that controls the tempo of the piezo buzzer (based on how many times you click on it in 5 seconds).

Schematic Diagram

 

Code

const int trigPin = 9;  
const int echoPin = 10; 
const int buzzerPin = 8; 
const int buttonPin = 4;  // system ON/OFF button
const int tempoButtonPin = 2;  // tempo setting button

//sensor variables
float duration, distance; 
bool systemOn = false; // system on or off state

// tempo variables
bool tempoSettingActive = false; 
int  tempoPressCount    = 0;   
unsigned long tempoStartTime = 0;
unsigned long tempoInterval  = 500; 

// for edge detection on tempo button (to count presses cleanly)
int lastTempoButtonState = HIGH;

// for edge detection on system button (cleaner)
int lastSystemButtonState = HIGH;


// for controlling when next beep happens
unsigned long lastBeatTime = 0;



void setup() {  
 pinMode(trigPin, OUTPUT);  
 pinMode(echoPin, INPUT);  
 pinMode(buzzerPin, OUTPUT);
 pinMode(buttonPin, INPUT_PULLUP); // system ON/OFF button 
 pinMode(tempoButtonPin, INPUT_PULLUP);  // tempo button 
 Serial.begin(9600);  
}  

void loop() {
  // system on/off state
  int systemButtonState = digitalRead(buttonPin);

  // detects a press: HIGH -> LOW 
  if (systemButtonState == LOW && lastSystemButtonState == HIGH) {
    systemOn = !systemOn;  // Toggle system state

    Serial.print("System is now ");
    Serial.println(systemOn ? "ON" : "OFF");

    delay(200); // basic debounce
  }
  lastSystemButtonState = systemButtonState;
  
  // if system is OFF: make sure buzzer is silent and skip rest
  if (!systemOn) {
    noTone(buzzerPin);
    delay(50);
    return;
  }

  // tempo button code
  int tempoButtonState = digitalRead(tempoButtonPin);

  // detects a press 
  if (tempoButtonState == LOW && lastTempoButtonState == HIGH) {
    if (!tempoSettingActive) {
      
      //first press (starts 5 second capture window)
      tempoSettingActive = true;
      tempoStartTime = millis();
      tempoPressCount = 1;  // Count this first press
      Serial.println("Tempo setting started: press multiple times within 5 seconds.");
    } else {
      // additional presses inside active window (5 secs)
      tempoPressCount++;
    }

    delay(40); // debounce for tempo button
  }
  lastTempoButtonState = tempoButtonState;

  // if we are in tempo mode, check whether 5 seconds passed
  if (tempoSettingActive && (millis() - tempoStartTime >= 5000)) {
    tempoSettingActive = false;

    if (tempoPressCount > 0) {
      // tempo interval = 1000 ms / (number of presses in 5 secs)
      tempoInterval = 1000UL / tempoPressCount;

      // avoids unrealistically fast intervals
      if (tempoInterval < 50) {
        tempoInterval = 50;
      }

      Serial.print("Tempo set: ");
      Serial.print(tempoPressCount);
      Serial.print(" presses in 5s -> interval ");
      Serial.print(tempoInterval);
      Serial.println(" ms between beeps.");
    } else {
      Serial.println("No tempo detected.");
    }
  }
 
  // ultrasonic sensor distance measurement
  digitalWrite(trigPin, LOW);
  delayMicroseconds(2);

  digitalWrite(trigPin, HIGH);
  delayMicroseconds(10);
  digitalWrite(trigPin, LOW);

  duration = pulseIn(echoPin, HIGH);
  distance = (duration * 0.0343) / 2.0;  // in cm

  Serial.print("Distance: ");
  Serial.println(distance);

  
  //buzzer pitch and tempo
  // checks if distance is valid and in a usable range
  if (distance > 0 && distance < 200) {
    float d = distance;

    // limit distances for stable mapping
    if (d < 5)  d = 5;
    if (d > 50) d = 50;

    // maps distance to frequency (closer = higher pitch)
    int frequency = map((int)d, 5, 50, 2000, 200);

    // uses tempoInterval to define how often we "tick" the sound (creates short beeps at each interval using current frequency)
    unsigned long now = millis();

    if (now - lastBeatTime >= tempoInterval) {
      lastBeatTime = now;

      // plays a short beep (half of the interval duration)
      unsigned long beepDuration = tempoInterval / 2;
if (beepDuration < 20) {
beepDuration = 20;  // minimum hearable blip
 }

tone(buzzerPin, frequency, beepDuration);
}

 } else {
    // if bad/no reading, silence the buzzer between ticks
    noTone(buzzerPin);
  }
  delay(50); //delay to reduce noise

}
Favorite Code
//buzzer pitch and tempo
// checks if distance is valid and in a usable range
if (distance > 0 && distance < 200) {
  float d = distance;

  // limit distances for stable mapping
  if (d < 5)  d = 5;
  if (d > 50) d = 50;

  // maps distance to frequency (closer = higher pitch)
  int frequency = map((int)d, 5, 50, 2000, 200);

This is a pretty simple part of the code, but I loved how the beeping sounds turned out. It’s so satisfying to see how my hand movements directly control the sound, and it made me realize how significant even a small part of the code could be.

The code was completed with assistance from ChatGPT.

Video Demo

Reflection and Future Improvements

Mapping the distance to control the sound was pretty simple. The challenging part was controlling the tempo, we had to figure out the values to divide in order for it to have a clear change in the sound of the piezo buzzer after clicking the green button. Overall, this was a really cool project and I hope to continue to improve and expand my knowledge in physical computing!

Week 9: Analog and Digital Sensors

Concept

For this week’s assignment, my overall concept is pretty similar to the one I did last week because it also has something to do with sleep. This time, I created a light system: for the first one, I used a button to turn on a single LED manually, and for the second one, the yellow LED turns on when the lights are turned off, just like a night light! I got inspiration for this idea from my little sister when we were kids, because she always used to sleep with a night light on.

Code
int buttonPin = 8;
int greenLED = 7;  // pin for green LED
int lightSensorPin = A2;
int yellowLED = 6;  // pin for yellow LED

void setup() {
  Serial.begin(9600);
  pinMode(buttonPin, INPUT_PULLUP);  
  pinMode(greenLED, OUTPUT);
  pinMode(yellowLED, OUTPUT);
}

void loop() {
  int sensorValue = analogRead(lightSensorPin);
  Serial.println(sensorValue);  // prints sensor value from light sensor

  if (digitalRead(buttonPin) == LOW) {  // button pressed
    digitalWrite(greenLED, HIGH);
  } else {
    digitalWrite(greenLED, LOW);
  }

  if (sensorValue < 175) {
    digitalWrite(yellowLED, HIGH);
  } else {
    digitalWrite(yellowLED, LOW);
  }
}

So basically, I used conditional statements for when I wanted each LED to turn on. The green LED was connected to the digital pins, so I used a button to turn it on and off: when the button is pressed, the LED lights up, and when it’s not pressed, the LED turns off. For the yellow LED, it checks the light sensor’s value, and when that value goes below 175, the LED turns on (so when the lights are off, the yellow LED acts as a night light!).

Hand-Drawn Schematic
Schematic diagram and Photo:
Video Demo
Reflection and Future Improvements

Honestly, it was pretty hard to come up with a concept for this project, but when I did, I’m satisfied with how it turned out. Another thing was that I underestimated how much time this would take, it took me way too long to figure everything out and fix the issues on the circuit. In the future, I plan on practicing wiring more often and getting a better understanding of circuit logic.

Reading Reflection – Week 9

Physical Computing’s Greatest Hits (and misses)

I agree with Igoe’s idea of recurring “hits and misses,” but I don’t think a project has to be deeply meaningful to count as a hit. Sometimes, a piece can still be successful if it’s creative, interesting, or just fun to interact with. I also think context plays a role in making something feel meaningful, especially through how users receive feedback. For example, the Monsters Inc. scream canisters in Disneyland Paris come to mind. As a kid, I loved screaming into them and watching the energy bar go up to the top, it’s a perfect example of feedback making the interaction more memorable.

I used to get hesitant about working on projects that weren’t completely original, feeling like I needed to come up with something new. But Igoe’s words reminded me that even if an idea’s been done before, I can still make it mine by adding my own personal touch.

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

I found Igoe’s idea of “setting the stage and shutting up” really interesting because it shows just how much power interpretation has in interactive art. When artists or designers immediately tell their audience what something means, it limits how people can experience it. I think there’s this sort of psychological effect that once you’re told what something is, it’s hard to see it in any other way. So I think it’s more effective to let users come to their own conclusions, even if it means they interpret the project differently from what was intended.

While making my own projects, I understand how my project works but users might not. By actually watching and hearing how they interact with it, I can figure out what’s confusing or what needs improvement. Feedback like that helps me refine my designs to make them more intuitive and engaging.