Week 13 – Working on Final Project

Are they able to figure it out? Where do they get confused and why?
My friends were a bit confused what to do in first place. So, I included instructions on top left corner, that by doing a fist they could transition between different 3D models and by using index finger and thumb they could manipulate the sketch.

Do they understand the mapping between the controls and what happens in the experience?
They do understand it. Controls how to use it is already given in the top left corner as instructions, so no problem with that.

What parts of the experience are working well? What areas could be improved?
I’m still working on adding new 3D models and adding explanation to each one and how it is specifically tied to Kazakh culture. I want people to learn about Kazakh culture and feel the items, observe them, and etc. I want to do a menu screen, and another instructions screen. Add 3 more Kazakh Cultural elements. Also, more features that would allow to do something interesting with the sketch line draw lines and oscillations and something interactive like this on the background of 3D model. In addition, I will working heavily on Arduino side from now on, adding arcade buttons for transitions between different 3D models. and building an engraved casing using probably ply wood.

What parts of your project did you feel the need to explain? How could you make these areas more clear to someone that is experiencing your project for the first time?
I’m expecting that engraved casing for the project with arcade buttons would make more sense on how to transition between different aspects of Kazakh culture rather than making a fist. But, I think using a fist pretty cool idea, and I get to explore hand gestures more. I will try to make instructions constant on the page, in case user forgot, they will always be there. Also, in main menu I will try to explain a bit about the project itself.

The project teaches people about Kazakh culture through interactive 3D objects. The user moves their hand in front of the webcam and controls a 3D asyq and a 3D yurt in real time. Hand rotation and hand openness change rotation, scale, and animation of the models. The goal is to make cultural objects feel alive and playful.

Handpose in p5.js finds key points on the user hand. The code maps these points to rotation and size values. The 3D asyq and yurt models load from external OBJ files. The models update their rotation and scale on every frame based on hand movement. The interaction is simple so anyone can explore the cultural objects.

The user brings their hand into the camera. Turning the index finger rotates the asyq.  Bigger pinch between thumb and index distance makes the yurt grow. I want to implement moving the hand forward or backward changes the distance of the models. The idea is to mix physical movement with digital cultural storytelling.

The Arduino is optional but adds a second layer of interaction. A sensor like a potentiometer or flex sensor sends values to p5.js. The value can change things like background color or cultural patterns. But, currently, I’m thinking of using arcade buttons to change between different 3D models.

The Arduino sends sensor values through serial. p5.js reads the values using the Web Serial API. The values change simple visual settings. This lets the user control the cultural objects both by hand and by sensor.

I am proud that the project takes Kazakh cultural objects and makes them interactive. I like that people can learn culture through movement. I am happy that the 3D models work smoothly with hand tracking.

I created the asyq and yurt models with 3D tools. I used p5.js for graphics and Handpose for tracking. I used Arduino for extra input. I used generative AI to help fix errors, structure the code, and write the description. All cultural objects are based on real Kazakh designs. I found 3D models online on Sketchlab, and I will reference them.

I want to add more gestures for cultural actions like throwing the asyq. I want to add more objects like dombyra or shanyrak. I want to add sound from Kazakh music. I also want to create a cleaner guide so visitors can learn the meaning of each cultural object.

Final Project Concept

Project Concept

For my final project, I’m creating a gesture-based vocabulary learning system (more like a game, basically). The idea came from noticing how flashcard apps never really stick for me because they’re so passive, and I wanted to create something where your body is actually involved in the learning process. Hover your left hand to see just a hard definition, challenging you to guess the word. When curiosity gets the better of you, hover your right hand to reveal the answer. A quick swipe over both sensors is like saying “got it” and moves to the next word, while holding both hands still gives you an example sentence to see the word in context. The interface tracks which words trip you up and brings them back more often, while words you nail consistently take a break. It’s spaced repetition, but you’re physically interacting with it rather than just clicking buttons.

 GRE prep, LSAT terms, fancy academic writing words, or a custom list of interesting words you’ve encountered and want to remember, the system visualizes your progress over time so you can actually see your vocabulary growing.

Arduino Design

Both photoresistors constantly feed readings to the Arduino, which compares them against threshold values to detect when your hands are hovering. The key is making the gesture detection smooth rather than jumpy, so I’m building in some debouncing logic that prevents flickering when your hand is at the edge of the sensor range. The timing matters too because the Arduino needs to distinguish between a quick swipe that says “next word” and deliberately holding both hands there to request an example sentence. I’m planning to add more to this but this is it for now.

P5.js Program Design

Large, readable text dominates the screen. When you hover your hand over a sensor, there’s subtle visual feedback confirming the system detected you, so you’re never wondering if it’s working. The progress dashboard lives off to the side, quietly showing you how many words you’ve learned today and your overall mastery percentage. The “Word of the Day” feature adds a nice ritual to opening the system. The system saves your progress using local storage, so your learning history persists between sessions. Over time, you build up this visualization of your vocabulary growth that’s genuinely satisfying to watch. You can see which word sets you’ve conquered, which ones still need work, and how consistent you’ve been with your practice. It’s the kind of feedback that makes you want to keep going.

Implementation Progress

I’m starting with getting the Arduino sensors working reliably because everything else depends on that foundation. First step is just wiring up the photoresistors and watching the raw values in the Serial Monitor to understand what I’m working with. Once I know what “hand hovering” actually looks like in terms of sensor readings, I can write the gesture detection code with appropriate thresholds. After the gestures feel solid and responsive when I test them by hand, I’ll set up the serial connection to P5 and make sure the commands are flowing through correctly.  Then it’s on to building the P5 interface, starting simple with a hard-coded list of maybe ten words that cycle through in response to Arduino commands. Once that basic interaction loop works, I’ll layer in the vocabulary database, spaced repetition algorithm, and progress tracking features. The final polish phase is where I’ll add the Word of the Day, multiple vocabulary sets, and any visual refinements that make it feel complete. The goal is to have something functional quickly, then make it delightful.

Week 12- Final Project Proposal

Finalised Concept for the Project

Plant Care Station is an interactive, game-like system that combines physical sensors through Arduino with a browser-based visual interface through p5.js.
The project teaches users about plant care (light, water, soil, and touch) through playful interactions, animations, glowing suns, and confetti celebrations.

My project uses sensor data from the Arduino : including four light sensors,  capacitive touch sensors using foil, and a soil moisture sensor — which are visualized in p5.js as a growing, living plant environment. As the user helps the plant receive enough light, fertilizer and moisture, the interface responds through movement, glowing suns, page transitions, and celebratory effects.

Arduino to P5:

  • 4 Light Sensors: Once the light has hit the sensors at a specific threshold, we use the p5 interface to show the user which sensors need more light. Once the light threshold is met, then confetti is thrown and the user can move to the next page.
  • Capacitative Touch sensors: I used aluminium foil to act as a capacitative touch sensor. This foil will be stuck to the scissors so that everytime the reading goes from NO-CONTACT to CONTACT: I count that as one leaf cut.
  • Capacitative Touch sensors/Pressure sensors: Once the fertilizer is paced in the soil we confirm that on the p5 screen and allow the user to move to the next page
  • Soil Moisture Sensor: Once the plant is watered to a specific threshold we notify the user on the p5 screen

 P5 to Arduino:

  • Once all the Steps are complete, p5 will send a signal to Arduino and the colourful LEDs will start flashing- to celebrate the completion.

 

Reading Response Week 11

I’ve always been fascinated by the ways design can alter our everyday experiences, but this reading made me realize how deeply it can also impact dignity and independence. Design Meets Disability argues that assistive technologies aren’t just medical tools; they’re cultural objects that can express identity and empower people. That idea immediately reminded me of when I first discovered the Be My Eyes app.

The app enables people with visual impairments to call volunteers, open their phone camera, and request assistance with tasks such as locating items in the fridge or reading labels. I’ll never forget one call I had: the person asked me to help identify items in their kitchen, and while we were talking, he told me a story about how he once cooked an entire meal for his family using the app to double-check ingredients and instructions. I was amazed, not just by his resourcefulness but by how technology became a bridge for independence and creativity.

Reflecting on that experience alongside the reading, I realized how much design can influence confidence and joy. When assistive tools are thoughtfully designed, they don’t just solve problems; they open doors to new possibilities. Be My Eyes is a perfect example of inclusive design, empowering people by turning what might seem like a barrier into an opportunity for connection and creativity. My takeaway is that disability should never be viewed as a deficit in design, but rather as an opportunity to rethink and expand what technology can do for everyone.

Production Week 11

For this assignment, I worked with Bigo to connect p5.js with an Arduino. We completed three exercises to practice sending data back and forth between the physical and digital worlds.

Part 1: One Sensor to p5.js

In the first exercise, we used a potentiometer connected to the Arduino. This sensor controlled the horizontal position of a circle on the computer screen. The Arduino read the potentiometer value and sent it to p5.js, which then moved the circle left or right based on that input.

Schematic

Arduino Code

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

void loop() {
  // Read analog value and send it as a line of text
  int sensorValue = analogRead(A0);
  Serial.println(sensorValue);
  delay(20); 
}

p5.js Code

let port;
let connectBtn;
let ballX = 0;
let sensorVal = 0;

function setup() {
  createCanvas(600, 400);
  background(50);

  port = createSerial();

  // Open the port automatically if used before
  let usedPorts = usedSerialPorts();
  if (usedPorts.length > 0) {
    port.open(usedPorts[0], 9600);
  }

  connectBtn = createButton('Connect to Arduino');
  connectBtn.position(10, 10);
  connectBtn.mousePressed(connectBtnClick);
}

function draw() {
  // Check if port is open
  if (port.available() > 0) {
    let data = port.readUntil("\n");
    
    if (data.length > 0) {
      // Update value
      sensorVal = Number(data.trim()); 
    }
  }

  background(256);
  
  // Map sensor val to canvas width
  ballX = map(sensorVal, 0, 1023, 25, width - 25);
  
  // Draw ball
  fill(0, 255, 100);
  noStroke();
  ellipse(ballX, height / 2, 50, 50);
}

function connectBtnClick() {
  if (!port.opened()) {
    port.open('Arduino', 9600);
  } else {
    port.close();
  }
}

Part 2: p5.js to LED Brightness

For the second part, we reversed the direction of the data. Instead of sending information from the Arduino to p5.js, we sent it from p5.js back to the Arduino. The ball on the screen acted like a virtual light bulb; dragging it upward made the physical LED brighten, while dragging it downward caused the LED to dim.

Arduino Code

C++

void setup() {
  Serial.begin(9600);
  pinMode(9, OUTPUT); //pmw pin
}

void loop() {
  if (Serial.available() > 0) {
    String input = Serial.readStringUntil('\n');
    int brightness = input.toInt();    // convert str to int
    brightness = constrain(brightness, 0, 255);    // just in case data is weird
    analogWrite(9, brightness);
  }
}

p5.js Code

JavaScript

let port;
let connectBtn;

// Ball variables
let ballX = 300;
let ballY = 200;
let ballSize = 50;
let isDragging = false; 

// Data variables
let brightness = 0;
let lastSent = -1; 

function setup() {
  createCanvas(600, 400);
  
  port = createSerial();
  
  let usedPorts = usedSerialPorts();
  if (usedPorts.length > 0) {
    port.open(usedPorts[0], 9600);
  }

  connectBtn = createButton('Connect to Arduino');
  connectBtn.position(10, 10);
  connectBtn.mousePressed(connectBtnClick);
}

function draw() {
  background(50);

  // ball logic
  if (isDragging) {
    ballX = mouseX;
    ballY = mouseY;
    
    // Keep ball inside canvas
    ballY = constrain(ballY, 0, height);
    ballX = constrain(ballX, 0, width);
  }

  // map brightness to y pos
  brightness = floor(map(ballY, 0, height, 255, 0));

  // send data
  if (port.opened() && brightness !== lastSent) {
    port.write(String(brightness) + "\n");
    lastSent = brightness;
  }
  //draw ball
  noStroke();
  fill(brightness, brightness, 0); 
  ellipse(ballX, ballY, ballSize);
  stroke(255);
  line(ballX, 0, ballX, ballY);

}

// --- MOUSE INTERACTION FUNCTIONS ---
function mousePressed() {
  // check if mouse is inside the ball
  let d = dist(mouseX, mouseY, ballX, ballY);
  if (d < ballSize / 2) {
    isDragging = true;
  }
}

function mouseReleased() {
  // stop dragging when mouse is let go
  isDragging = false;
}

function connectBtnClick() {
  if (!port.opened()) {
    port.open('Arduino', 9600);
  } else {
    port.close();
  }
}

Part 3: Gravity Wind and Bi-directional Communication

For the final exercise, we brought all the concepts together using the gravity-and-wind example. We modified the code to add two new features.

First, a potentiometer was used to control the wind speed in real-time. Second, we programmed the Arduino so that whenever the ball hit the ground, an LED would turn on.

This part took some troubleshooting. I had to filter out very small bounces because the LED kept flickering while the ball rolled along the floor. Once that was fixed, I also added a visual arrow on the screen to show the current wind direction and intensity.

Arduino Code

void setup() {
  Serial.begin(9600);
  pinMode(9, OUTPUT); // LED on Pin 9
}

void loop() {
  // read & send pot value
  int potValue = analogRead(A0);
  Serial.println(potValue);


  if (Serial.available() > 0) {
    char inChar = Serial.read();
    
    // check for blink command
    if (inChar == 'B') {
      digitalWrite(9, HIGH);
      delay(50); 
      digitalWrite(9, LOW);
    }
  }
  
  delay(15);
}

p5.js Code

let port;
let connectBtn;

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

function setup() {
  createCanvas(640, 360);
  noFill();
  
  // Physics Setup
  position = createVector(width/2, 0);
  velocity = createVector(0,0);
  acceleration = createVector(0,0);
  gravity = createVector(0, 0.5*mass);
  wind = createVector(0,0);

  // Serial Setup
  port = createSerial();
  let usedPorts = usedSerialPorts();
  if (usedPorts.length > 0) {
    port.open(usedPorts[0], 9600);
  }
  
  connectBtn = createButton('Connect to Arduino');
  connectBtn.position(10, 10);
  connectBtn.mousePressed(connectBtnClick);
}

function draw() {
  background(255);
  
  // read for wind
  if (port.available() > 0) {
    let data = port.readUntil("\n");
    if (data.length > 0) {
      sensorVal = Number(data.trim());
    }
  }
  
  // map wind
  let windX = map(sensorVal, 0, 1023, -0.8, 0.8);
  wind.set(windX, 0);

  // apply physics
  applyForce(wind);
  applyForce(gravity);
  velocity.add(acceleration);
  velocity.mult(drag);
  position.add(velocity);
  acceleration.mult(0);
  
  // draw
  fill(0);
  ellipse(position.x, position.y, mass, mass);
  drawWindIndicator(windX);

  // detect bounce
  if (position.y > height - mass/2) {
      velocity.y *= -0.9; 
      position.y = height - mass/2;
      
      // send blink command
      if (abs(velocity.y) > 1 && port.opened()) {
        port.write('B');
      }
  }
  
  // collision detection
  if (position.x > width - mass/2) {
    position.x = width - mass/2;
    velocity.x *= -0.9;
  } else if (position.x < mass/2) {
    position.x = mass/2;
    velocity.x *= -0.9;
  }
}

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

function connectBtnClick() {
  if (!port.opened()) {
    port.open('Arduino', 9600);
  } else {
    port.close();
  }
}

// helper to visualize the wind
function drawWindIndicator(w) {
  push();
  translate(width/2, 50);
  fill(150);
  noStroke();
  text("Wind Force", -30, -20);
  stroke(0);
  strokeWeight(3);
  line(0, 0, w * 100, 0); 
  fill(255, 0, 0);
  noStroke();
  if (w > 0.05) triangle(w*100, 0, w*100-10, -5, w*100-10, 5); // Right Arrow
  if (w < -0.05) triangle(w*100, 0, w*100+10, -5, w*100+10, 5); // Left Arrow
  pop();
}

function keyPressed(){
  // reset ball
  if (key==' '){
    mass=random(15,80);
    position.y=-mass;
    position.x = width/2;
    velocity.mult(0);
  }
}

Video Demonstration

Reading Response Week 10

I still remember the first time I used VR. I was so amazed by the experience that I didn’t touch my phone for the whole day. It felt completely different from the usual screen interactions I was used to; suddenly, I was moving, reaching, and using my body in ways that made the technology feel alive. Reading A Brief Rant on the Future of Interaction Design reminded me of that moment, because the author argues that our visions of the future are too focused on “Pictures Under Glass,” flat screens that limit the richness of human interaction.

The rant makes a strong case that our hands and bodies are capable of far more expressive actions than just tapping and swiping. The follow-up responses clarify that the point wasn’t to offer a neat solution, but to spark research into dynamic, tactile interfaces that embrace our physicality. I completely agree with this perspective, as VR demonstrates the power of technology when it engages the entire body. It’s entertaining, immersive, and feels closer to what interaction design should be.

At the same time, I know it would be hard to design everything this way. Not every task needs full-body interaction, and sometimes the simplicity of a phone screen is enough. But I do think it’s doable to push more technologies in that direction, blending practicality with embodied experiences. My main takeaway is that the future of interaction design shouldn’t settle for prettier screens; it should aim for interfaces that make us feel connected to our bodies and the environments around us. VR proves that this is possible, and even if it’s challenging to apply everywhere, it’s a direction worth pursuing.

Production Week 10

Project: The Arduino DJ Console

Assignment Description

For this assignment, we were tasked with designing and building a musical instrument using Arduino. The requirements were simple: the project had to include at least one digital sensor (such as a switch) and one analog sensor.

What We Built

Working with Bigo, we created a DJ-style sound console powered by an Arduino. This instrument enables users to experiment with sound by adjusting pitch and speed, providing a substantial amount of room for creativity.

Our setup included:

  • Two Potentiometers (Analog Sensors):
    One knob changes the pitch of the note, and the other controls the duration (speed).

  • One Button (Digital Sensor):
    This serves as a mute button, instantly silencing the sound.

  • Piezo Buzzer:
    The component responsible for producing the tones.

Schematic

The circuit uses analog pins A0 and A5 for the two knobs and digital pin 13 for the pushbutton.
The buzzer is connected to pin 9.

Video Demonstration

Code

We wrote code to read the sensors and play notes from a C Major scale. Here is the source code for the project:

C++

// Control a buzzer with two knobs and a button

// Define hardware pins
const int piezoPin = 9;
const int pitchPotPin = A0;
const int durationPotPin = A5;
const int buttonPin = 13;

// List of frequencies for C Major scale
int notes[] = {262, 294, 330, 349, 392, 440, 494, 523};

void setup() {
  // Start data connection to computer
  Serial.begin(9600);
  Serial.println("Instrument Ready! Note Stepping Enabled.");

  // Set pin modes
  pinMode(piezoPin, OUTPUT);
  pinMode(buttonPin, INPUT_PULLUP);
}

void loop() {
  // Check if the button is pressed
  int buttonState = digitalRead(buttonPin);

  // Mute sound if button is held down
  if (buttonState == LOW) {
    noTone(piezoPin);
  } else {
    // Read values from both knobs
    int pitchValue = analogRead(pitchPotPin);
    int durationValue = analogRead(durationPotPin);

    // Convert pitch knob value to a note index from 0 to 7
    int noteIndex = map(pitchValue, 0, 1023, 0, 7);

    // Select the frequency from the list
    int frequency = notes[noteIndex];

    // Convert duration knob value to time in milliseconds
    int noteDuration = map(durationValue, 0, 1023, 50, 500);

    // Play the sound
    tone(piezoPin, frequency, noteDuration);

    // Show information on the screen
    Serial.print("Note Index: ");
    Serial.print(noteIndex);
    Serial.print(" | Frequency: ");
    Serial.print(frequency);
    Serial.print(" Hz | Duration: ");
    Serial.print(noteDuration);
    Serial.println(" ms");

    // Wait for the note to finish
    delay(noteDuration + 50);
  }
}

Reading Response Week 9

What really stood out to me across these two readings was how much creativity in physical computing and interactive art depends on participation. In Physical Computing’s Greatest Hits (and Misses), I was struck by how many projects keep reappearing: theremin-like instruments, drum gloves, video mirrors, and interactive paintings. At first, it almost feels repetitive, but the point is that each version can still surprise us. The same theme can be reinvented in ways that feel fresh, because the interaction itself is what makes it unique. It’s less about inventing something completely new every time, and more about how the design invites people to play, explore, and discover.

That idea connected with my own love of music. I’ve always been fascinated by how instruments themselves are designed to invite interaction. Even something as simple as a guitar feels like it’s guiding you, its strings and frets practically tell you how to play, and once you start experimenting, you realize how much freedom you have to create your own sound. Reading about theremin-like instruments and drum gloves reminded me of that same feeling: the design doesn’t just produce music, it encourages you to participate, to experiment, and to find joy in the process.

Then, in Making Interactive Art: Set the Stage, Then Shut Up and Listen, the focus shifts to the artist’s role. Instead of dictating meaning, the artist’s job is to create an environment where the audience can respond and interpret for themselves. I liked the idea that interactive art is more like a performance than a finished statement; the audience completes the work through their actions. That perspective really changes how I think about design. It’s not about control, but about setting up the right conditions for discovery.

Taken together, both readings made me realize that physical computing and interactive art thrive on openness. Whether it’s a recurring project idea or a carefully staged environment, the real magic happens when people bring their own curiosity and interpretation to the table. Good design doesn’t just show us something, it gives us space to participate, and that’s what makes the experience meaningful.

Production Week 9

I designed a simple interactive game using LEDs, a potentiometer, and a digital switch. The setup has two rows of LED pairs, each pair matching in color. The potentiometer controls the start point. When I rotate it, the highlighted position shifts across the pairs and cycles through them.

When I press the digital switch, one of the two lit LEDs starts moving quickly along its row. Pressing the button again stops it. If the moving LED stops exactly on the matching position of the other fixed LED, a green verdict LED turns on to show success. If not, a red verdict LED lights up, and the game resets to the start point.

It’s a fun, simple matching game that combines timing, control, and basic electronics.

Code:

// — Pin Definitions —
// LED Rows (G, Y, R, B)
const int fixedRowPins[] = {2, 4, 6, 8};
const int cyclingRowPins[] = {3, 5, 7, 9};

// RGB Feedback LED Pins
const int RGB_RED_PIN = 11;
const int RGB_GREEN_PIN = 12;
const int RGB_BLUE_PIN = 13;

// Input Pins
const int POT_PIN = A1;
const int BUTTON_PIN = 10;

// — Game Logic Variables —
// Game State: false = waiting/potentiometer mode, true = cycling/active mode
bool gameIsActive = false;

// Stores the color index (0-3) when the game starts
int targetColorIndex = 0;

// Stores the current color index (0-3) of the cycling light
int currentCyclingIndex = 0;

// — Timing Variables for Non-Blocking Cycling —
unsigned long previousCycleMillis = 0;
const int CYCLE_SPEED_MS = 80; // How fast the light cycles (lower is faster)
const int VERDICT_DISPLAY_MS = 2000; // How long to show Red/Green verdict

void setup() {
Serial.begin(9600); // For debugging

// Set all 8 game LED pins to OUTPUT
for (int i = 0; i < 4; i++) {
pinMode(fixedRowPins[i], OUTPUT);
pinMode(cyclingRowPins[i], OUTPUT);
}

// Set RGB LED pins to OUTPUT
pinMode(RGB_RED_PIN, OUTPUT);
pinMode(RGB_GREEN_PIN, OUTPUT);
pinMode(RGB_BLUE_PIN, OUTPUT);

// Set button pin with an internal pull-up resistor
// The pin will be HIGH when not pressed and LOW when pressed
pinMode(BUTTON_PIN, INPUT_PULLUP);
}

void loop() {
// Read the button state
bool buttonPressed = (digitalRead(BUTTON_PIN) == LOW);

// — Main Game Logic: Two States —

// STATE 1: Game is NOT active. Control LEDs with the potentiometer.
if (!gameIsActive) {
handlePotentiometer(); // Light up LED pair based on pot

// Check if the button is pressed to START the game
if (buttonPressed) {
Serial.println(“Button pressed! Starting game…”);
// Lock in the current color from the potentiometer
targetColorIndex = getPotIndex();

gameIsActive = true; // Switch to the active game state
turnRgbOff(); // Ensure verdict light is off

// Wait for the button to be released to avoid misfires
while(digitalRead(BUTTON_PIN) == LOW);
delay(50); // Simple debounce
}
}
// STATE 2: Game IS active. Cycle the lights and wait for the player’s timing.
else {
cycleLights(); // Handle the light cycling logic

// Check if the button is pressed to STOP the cycle and check the verdict
if (buttonPressed) {
Serial.println(“Timing button pressed!”);
// The currentCyclingIndex is the player’s selection
checkVerdict();

gameIsActive = false; // Game is over, switch back to potentiometer mode

// Wait for button release
while(digitalRead(BUTTON_PIN) == LOW);
delay(50); // Simple debounce
}
}
}

// — Helper Functions —

// Reads potentiometer and lights up the corresponding LED pair
void handlePotentiometer() {
int potIndex = getPotIndex();
lightLedPair(potIndex);
}

// Reads the potentiometer and maps its value to an index from 0 to 3
int getPotIndex() {
int potValue = analogRead(POT_PIN); // Reads value from 0-1023
// Map the 0-1023 range to four sub-ranges (0, 1, 2, 3)
int index = map(potValue, 0, 1023, 0, 3);
return index;
}

// Lights one pair of LEDs based on an index (0-3)
void lightLedPair(int index) {
turnAllGameLedsOff();
digitalWrite(fixedRowPins[index], HIGH);
digitalWrite(cyclingRowPins[index], HIGH);
}

// Manages the fast, non-blocking cycling of the second row of LEDs
void cycleLights() {
// This uses millis() to avoid delay() so we can still read the button
unsigned long currentMillis = millis();

if (currentMillis – previousCycleMillis >= CYCLE_SPEED_MS) {
previousCycleMillis = currentMillis; // Reset the timer

// Move to the next LED in the cycle
currentCyclingIndex++;
if (currentCyclingIndex > 3) {
currentCyclingIndex = 0; // Loop back to the start
}

// Update the lights
turnAllGameLedsOff();
digitalWrite(fixedRowPins[targetColorIndex], HIGH); // Keep fixed LED on
digitalWrite(cyclingRowPins[currentCyclingIndex], HIGH); // Light the current cycling LED
}
}

// Checks if the player’s timing was correct and shows the verdict
void checkVerdict() {
if (currentCyclingIndex == targetColorIndex) {
Serial.println(“Verdict: CORRECT!”);
showVerdict(true); // Show green light
} else {
Serial.println(“Verdict: WRONG!”);
showVerdict(false); // Show red light
}
}

// Lights up the RGB LED Green for correct, Red for incorrect
void showVerdict(bool isCorrect) {
turnAllGameLedsOff(); // Turn off game lights to focus on verdict
if (isCorrect) {
// Light RGB GREEN
digitalWrite(RGB_RED_PIN, LOW);
digitalWrite(RGB_GREEN_PIN, HIGH);
digitalWrite(RGB_BLUE_PIN, LOW);
} else {
// Light RGB RED
digitalWrite(RGB_RED_PIN, HIGH);
digitalWrite(RGB_GREEN_PIN, LOW);
digitalWrite(RGB_BLUE_PIN, LOW);
}
delay(VERDICT_DISPLAY_MS); // Hold the verdict light
turnRgbOff(); // Turn off the verdict light before returning to the game
}

// — Utility Functions —

// Turns off all 8 game LEDs
void turnAllGameLedsOff() {
for (int i = 0; i < 4; i++) {
digitalWrite(fixedRowPins[i], LOW);
digitalWrite(cyclingRowPins[i], LOW);
}
}

// Turns off the RGB LED
void turnRgbOff() {
digitalWrite(RGB_RED_PIN, LOW);
digitalWrite(RGB_GREEN_PIN, LOW);
digitalWrite(RGB_BLUE_PIN, LOW);
}

Reading Response Week 8

Honestly, the biggest takeaway for me from these documentaries was realizing how much design and persistence shape not just how we use things, but also how we feel about using them. With Attractive Things Work Better, it hit me especially hard because of my situation at TikTok. I had never actually used the app before starting, and at first, I felt entirely out of place, as if I was missing some secret language that everyone else already spoke. But the more I explored, the more I noticed how the design itself was pulling me in. The smooth scrolling, the way videos fill the screen, and the clean interface all made me curious, rather than frustrated. Even though I didn’t know what I was doing, the app felt welcoming. That’s precisely what the documentary was talking about: attractive things don’t just look good, they change the way we experience them.

On the other hand, Her Code Got Humans on the Moon made me think about resilience and diving into challenges without a clear roadmap. It reminded me of when I joined the Hack My Robot cybersecurity competition. I had zero prior knowledge about network security, but I was so excited to participate that I didn’t even care about the results. I ended up bingeing on crash courses and tutorials, trying to absorb as much information as possible in a short amount of time. It was one of the most intensive learning experiences I’ve ever had, but also one of the most enjoyable. And in the end, our team actually placed second, which felt surreal given how unprepared I had been at the start.

By combining these two ideas, I’ve come to realize that good design and passionate persistence both have the power to transform intimidating experiences into something playful and rewarding. Attractive design makes me more patient and curious, while resilience in the face of uncertainty makes me more confident and adaptable. Whether it’s learning TikTok from scratch or throwing myself into a competition I wasn’t ready for, both experiences showed me that the way we feel while engaging with something can be just as important as the technical details.