Final production

Final Piece

Physical Computing / Pieces

My work is all about space, and I wanted the installation to be on the floor. I glued my stepping pieces onto a single piece of wood, with each stepping piece made of cardboard and a hidden FSR beneath each cardboard tile. I painted the wood black, and also painted the cardboard stepping pieces and the boxes that held the button and potentiometer in black to keep a consistent aesthetic. I used the laser cutter in the IM lab and drilled a small hole for cable management.

For the visuals, I added images on the “stones” to enhance the aesthetics. Each image represented the function of its corresponding stepping piece, for example, adding a planet, meteor, or stars. To keep the images stylistically consistent, I used Google Gemini (Nano Banana) for image generation. I laminated the images since people would be stepping on them, and I wanted to make sure they wouldn’t get damaged.

I also had to weld the wires together to extend them and have them stick to the potentiometer and button.

Arduino setup and code

The rails came in really handy since I had five resistors for my five FSRs, so I could just connect all the resistors to the ground rail. I also used the 5V rail for my potentiometer. Some of the wires weren’t long enough, so I had to either solder them together or use jumper wires.

I needed to read the values of course, and for the button, I used input_pullup because I already had a lot of wiring so I wanted to keep the board cleaner.

Code

The main problem was that the FSR would occasionally send a 0 value, causing the whole screen to be spammed with meteors, stars, and planets, which resulted in significant lag, so I needed to change the code to implement proper debouncing, smoothing/averaging, and state confirmation to filter out false triggers. The solution includes a rolling average of three samples to smooth out noise, a 50 ms debounce time to ensure the state is stable before triggering, a minimum press time of 30 ms to confirm a press event, confirmed state tracking to prevent false positives, and hold detection that activates only after the button is verified as pressed.

I used Claude AI here to help come up with the solution because I had no idea what to do about the incorrect readings.

Code is in arduino.html in p5.js

Difficulties

There were mainly two difficulties. The first was more time-consuming than it was technically challenging: having several wires for seven different controls made organiscing and writing everything quite difficult. The second issue, which I mentioned earlier, was that the FSR values would randomly drop to 0 every few seconds even when there was no pressure applied, so I had to find a way to work around that.

User testing

Final code – https://editor.p5js.org/kk4827/full/ThmIIRv_-

Sounds from Pixabay

Images from Gemini Nano Banana

User Testing

IMG_2996 Updates

After doing more research, I realised I can only have five stepping pieces. This is because the Arduino only has six analog pins, and I need to reserve one for the potentiometer. So I changed the layout to: three pins for the three star regions, one for planets, and one for meteors.

User Testing

During my initial testing, the first problem I encountered was that several sensors didn’t work at all. I had to find new ones, solder them to the wires so they stayed attached, and replace the old ones. This also meant I had to rip the stones off the board, which made me realise I should have tested the sensors thoroughly before sticking them onto the wood.
I used a simple Arduino program that printed the FSR values to make sure each sensor worked properly.

Another thing I realised was that, since I wanted the installation to be activated by foot pressure, I needed a way for users to know what each foot pad represents. So I generated images with Gemini AI, printed them, and mounted them on cardboard. Then I realised I should laminate them, because they were starting to crinkle and tear.

I also thought about how the user would see on the screen what they are pressing, especially if they’re holding it down. I decided it would be ideal to show small circles representing each stone on the screen with a ring animation that fills up when the stone is held, similar to the ring on the Apple Watch when you hold down a button for three seconds.

With the FSR, I noticed that sometimes the pressure would fluctuate between 0–10 even when a foot was on the sensor, so I set the threshold to 10.
Finally, I placed my stepping stones on pieces of black wood to create a more defined “space” feel.

 

Final Idea

I want to create an immersive experience with space. I want users to come to an empty canvas and use pressure sensors to add planets, meteors and stars. These stars can be added and let’s say we have a minimum of 5 stars, a star constellation will be created and can grow if the user adds more stars. These will be floating around or soaring by (meteors) and so it feels like you’re in space. I want to have a projector to project the P5 screen so users can really feel the grandeur of it.

The Interaction

I will have 8 stepping stones on the floor that when the user steps on them they do different things:

Star Makers (Stones 1, 4, 6):

  • Quick tap: Adds one small white star to that stone’s constellation
  • Each stone creates its own independent star collection
  • When 5 stars are placed, they automatically connect with glowing lines to form a constellation
  • Can expand up to 9 stars, making the constellation more intricate and complex
  • Three unique constellations can exist simultaneously in different regions of the sky

Planet Makers (Stones 2, 5, 7):

  • Hold for 3+ seconds: Materializes a planet in space
  • Random planet type appears: gas giants, ringed planets, rocky worlds, ice planets, or mysterious alien worlds
  • Planets drift randomly through space, floating past your constellations
  • Creates a living, breathing solar system

Meteor Makers (Stones 3, 8):

  • Quick tap: Shoots one meteor across the sky in a random direction
  • Hold for 3+ seconds: Triggers a meteor shower with 5 meteors streaking across space
  • Adds dynamic movement and excitement to the scene

Atmosphere Control (Potentiometer dial):

  • Physical dial near the stepping area
  • Controls both the visual intensity and audio volume
  • Low: Clear, minimal space with silence
  • High: Rich nebula clouds, cosmic dust, and immersive ambient soundscape
  • Gives users creative control over the mood of their universe

The Experience

Users approach a darkened floor projection showing empty space. As they explore the stepping stones, they discover they can build their own universe, star by star, constellation by constellation. The moment when 5 stars connect into a glowing constellation creates a magical sense of achievement. Planets drift through the creations, meteors streak across the sky, and the atmosphere can be dialed from stark and minimal to rich and dramatic.

Lily pad

For this project, I wanted to recreate a peaceful scene of a frog sitting on a lily pad in a pond. Since I hadn’t worked much with sensors yet, I thought this would be the opportunity to incorporate one. I decided to use a distance sensor to control the ripples in the water, the closer your hand gets to the sensor, the more frequently the frog hops and creates ripples.

The Arduino codesimply measures how far away your hand is from the sensor and sends that data to the p5.js code. The Arduino code measures distance by sending an ultrasonic pulse and calculating how long it takes to bounce back, then converts that time into cms using the speed of sound (0.034 cm/microsecond) divided by 2 since the sound travels to the object and back.

The p5.j code then uses that distance data to dictate how often the ripples should occur. In the p5 code, I also hosted the visuals/art element of the project.

Next time, I think it would be fun to use a pressure sensor and have users actually jump up and down at different strengths and show that on p5.js.

// ARDUINO CODE
const int trigPin = 9;
const int echoPin = 10;

void setup() {
  Serial.begin(9600);
  pinMode(trigPin, OUTPUT);
  pinMode(echoPin, INPUT);
}

void loop() {
  // measure distance
  digitalWrite(trigPin, LOW);
  delayMicroseconds(2);
  digitalWrite(trigPin, HIGH);
  delayMicroseconds(10);
  digitalWrite(trigPin, LOW);
  
  long duration = pulseIn(echoPin, HIGH);
  int distance = duration * 0.034 / 2;
  
  // send distance to p5.js
  Serial.println(distance);
  
  delay(50);
}

IMG_2539

Week 11 reading response

This text suffers from a fundamental contradiction that undermines its own arguments: while championing simplicity and challenging universal design, it romanticises elite consumer products that are themselves inaccessible to many disabled users. The iPod worship is weird, celebrating a device with no tactile feedback beyond a smooth wheel and minimal physical controls as some paragon of inclusive thinking. The author gestures at Peter and Steve’s differing preferences but never interrogates why someone like Tyler would need to feel “self-confident” using a phone in public, treating internalised ableism as personal taste rather than a design failure. The golden prosthetic hand and Aimee Mullins’s carved wooden legs are presented as liberating alternatives to discretion, yet these bespoke art objects are available only to those with money, barely a decent vision of disability design.

The tension between “fashion meets discretion” reveals the author’s shallow engagement with power dynamics in disability. Dismissing pink plastic hearing aids as shameful while celebrating expensive designer eyewear ignores that frames cost hundreds of pounds, discretion through flesh-coloured plastic may be the only affordable option for many users. The suggestion that “fashion designers should be involved as a matter of course” treats aesthetics as a universal good without acknowledging that high design often increases cost and decreases repairability.

The “flying submarine” metaphor encapsulates the text’s elitism, better to have multiple specialised and beautifully designed products than one versatile compromise. This definitely works if you can afford a wardrobe of prosthetics or a collection of single purpose devices, but it’s design thinking for the wealthy masquerading as liberation. The text never acknowledges that universal design emerged precisely because disabled people couldn’t access or afford specialised alternatives.

Week 10 – musical instrument

Concept

For this week’s assignment, Shahram and I made a small musical instrument using an Arduino. We decided to create a pressure-sensitive drum pad that lets you play different drum sounds depending on how hard you press it.

The main part of the project is a force-sensitive resistor (FSR) that acts as the drum pad. When you press on it, the Arduino reads how much pressure you applied and plays a sound through a small buzzer. The harder you hit it, the longer the sound lasts, kind of like playing a real drum.

We also added a button that lets you switch between three drum sounds: a kick, a snare, and a hi-hat. So pressing the pad feels interactive, and you can change the type of drum as you play. It’s a really simple setup, but it was fun to experiment with.

Schematic

 

Video Demo

IMG_0808

const int FSR_PIN = A0;        
const int BUTTON_PIN = 2;     
const int PIEZO_PIN = 8;     

// Drum sounds 
int kickDrum = 80;             // low drum
int snareDrum = 200;           // mid drum
int hiHat = 1000;              // high drum

int currentDrum = 0;         
int lastButtonState = HIGH;    

void setup() {
  pinMode(BUTTON_PIN, INPUT);  
  pinMode(PIEZO_PIN, OUTPUT);
  Serial.begin(9600); 
}

void loop() {
  int pressure = analogRead(FSR_PIN);
  if (pressure > 20) {
    int duration = map(pressure, 10, 1023, 10, 200);
    // Play the drum sound
    if (currentDrum == 0) {
      tone(PIEZO_PIN, kickDrum, duration);
    } else if (currentDrum == 1) {
      tone(PIEZO_PIN, snareDrum, duration);
    } else {
      tone(PIEZO_PIN, hiHat, duration);
    }
    delay(50);  
  }
  int buttonState = digitalRead(BUTTON_PIN);
  //if button was just pressed, we need to change drum sound
  if (buttonState == LOW && lastButtonState == HIGH) {
    currentDrum = currentDrum + 1;
    if (currentDrum > 2) {
      currentDrum = 0;
    }
    delay(200); 
  }
  lastButtonState = buttonState;  // Store utton state 
}

Future Improvements

For future improvements, we’d like to add a potentiometer to control the sound more precisely, allowing the player to adjust tone or volume in real time while drumming. We could also include LEDs that light up based on which drum sound is active and how hard the pad is hit. These additions would make the drum pad feel more dynamic,  and visually engaging.

 

Week 10 – reading

A Brief Rant on the Future of Interaction Design – initial article

The part of the reading that I found most interesting was the idea that we should stop limiting human interaction to just the tips of our fingers. It made me question why so many interactive designs and technologies focus almost entirely on finger-based gestures. Why not explore other parts of the body as tools for interaction?

I think part of the reason is that we, as humans, feel we have the most control over our fingers – they’re precise, sensitive, and easy to coordinate. But that doesn’t mean interaction should stop there? How could we design experiences that involve other body parts, ones that are still easy to control, but that go beyond what’s been unimaginatively repeated in current design?

The article emphasises how much of our natural ability to sense and manipulate the world through touch has been lost in “Pictures Under Glass”, flat screens that give us no tactile feedback. That really stood out to me, because it highlights how technology, despite its innovation, can sometimes strip away what makes interaction human.

Overall, the reading made me realise how limited our current designs are compared to the potential of the human body. I think it helped me to challenge myself and image more creative ways to interactive with my projects.

Responses

I appreciate his point on the iPad being revolutionary but if it acts the same in 20 years, it won’t be as there has been no big enough change to stay revolutionary. But what are those next steps? Mind control, hand and arms altogether with holograms? It is difficult to come up with answers or suggestions to the rants that were mentioned but I also see the finger being a cap to how we interact with daily tech objects.

Week 9 assignment

For this assignment, I decided to use the potentiometer and the button. I wanted the potentiometer to control how bright the RGB light is and use the switch button for 2 purposes, to change the general colour of the RGB but to also start and stop the blinking of the red alarm LED I used.

I had the code use 4 different colours but have this also a factor on how many blinks occur with the LED light.

I had the switch button be used as a way to have the red LED on or off.

To be honest, I used the Claude Sonnet 4..5 model to give me ideas on how I can make the whole system more interesting / creative. That is how the idea of having the number of pings be dependent on the colour came from.

this is the code I used

// PIN location
const int POT_PIN = A0;           // Potentiometer
const int BUTTON_PIN = 2;         // Push button 
const int RGB_RED_PIN = 9;        
const int RGB_GREEN_PIN = 10;     
const int RGB_BLUE_PIN = 11;      
const int MODE_LED_PIN = 13;      // Ree LED 

int potValue = 0;                 
int brightness = 0;               
bool buttonState = false;         
bool lastButtonState = false;     
int colorMode = 0;               
unsigned long previousMillis = 0; //  non-blocking blink timing
const long blinkInterval = 150;   // blink interval for mode indicator
bool modeLedState = false;        

const char* modeNames[] = {"White", "Red", "Green", "Blue"};

void setup() {
  Serial.begin(9600);
  
  // set pins
  pinMode(POT_PIN, INPUT);
  pinMode(BUTTON_PIN, INPUT);
  pinMode(RGB_RED_PIN, OUTPUT);
  pinMode(RGB_GREEN_PIN, OUTPUT);
  pinMode(RGB_BLUE_PIN, OUTPUT);
  pinMode(MODE_LED_PIN, OUTPUT);
  
  // initialise LEDs as off
  analogWrite(RGB_RED_PIN, 0);
  analogWrite(RGB_GREEN_PIN, 0);
  analogWrite(RGB_BLUE_PIN, 0);
  digitalWrite(MODE_LED_PIN, LOW);
}

void loop() {
  // potentiometer read
  potValue = analogRead(POT_PIN);
  
  // map the values of the potentiometer to a brightness value
  brightness = map(potValue, 0, 1023, 0, 255);
  
  // button read
  buttonState = digitalRead(BUTTON_PIN);
  
  // when button is pressed, change the colour
  if (buttonState == HIGH && lastButtonState == LOW) {
    colorMode = (colorMode + 1) % 4;  //cycle through 0-3
    Serial.println(modeNames[colorMode]);
    delay(50);  
  }
  
  lastButtonState = buttonState;
  
  // change RGB LED based on selected colour
  switch(colorMode) {
    case 0:  //  white
      analogWrite(RGB_RED_PIN, brightness);
      analogWrite(RGB_GREEN_PIN, brightness * 0.8); 
      analogWrite(RGB_BLUE_PIN, brightness * 0.6);  
      break;
      
    case 1:  // red 
      analogWrite(RGB_RED_PIN, brightness);
      analogWrite(RGB_GREEN_PIN, 0);
      analogWrite(RGB_BLUE_PIN, 0);
      break;
      
    case 2:  // green 
      analogWrite(RGB_RED_PIN, 0);
      analogWrite(RGB_GREEN_PIN, brightness);
      analogWrite(RGB_BLUE_PIN, 0);
      break;
      
    case 3:  // blue 
      analogWrite(RGB_RED_PIN, 0);
      analogWrite(RGB_GREEN_PIN, 0);
      analogWrite(RGB_BLUE_PIN, brightness);
      break;
  }
  
  // Mode 0 = no blinks (off)
  // Mode 1 = 1 blink
  // Mode 2 = 2 blinks 
  // Mode 3 = 3 blinks
  handleModeIndicator();
  delay(10);  // Small delay for stability
}

//function to handle the 
void handleModeIndicator() {
  unsigned long currentMillis = millis();
  static int blinkCount = 0;
  static unsigned long patternStartTime = 0;
  static bool isBlinking = false;
  
  // when white, keep LED off
  if (colorMode == 0) {
    digitalWrite(MODE_LED_PIN, LOW);
    blinkCount = 0;
    isBlinking = false;
    return;
  }
  
  // new blink pattern every 2 seconds
  if (!isBlinking && (currentMillis - patternStartTime >= 2000)) {
    isBlinking = true;
    blinkCount = 0;
    patternStartTime = currentMillis;
  }
  
  // perform blinks equal to color mode number
  if (isBlinking) {
    unsigned long timeInPattern = currentMillis - patternStartTime;
    int currentBlink = timeInPattern / (blinkInterval * 2);  // *2 for on+off
    
    if (currentBlink < colorMode) {
      // still within the blink count for this mode
      unsigned long timeInBlink = timeInPattern % (blinkInterval * 2);
      
      if (timeInBlink < blinkInterval) {
        digitalWrite(MODE_LED_PIN, HIGH);  // LED on
      } else {
        digitalWrite(MODE_LED_PIN, LOW);   // LED off
      }
    } else {
      digitalWrite(MODE_LED_PIN, LOW);
      isBlinking = false;
    }
  }
}

 

IMG_2228

 

Week 9 reading

Physical Computing’s Greatest Hits (and misses)

The article highlights that originality doesn’t always mean creating something entirely new from scratch. Many people shy away from existing physical computing ideas because they think someone else has already done them, but that’s not the point. What matters is how we, as artists and engineers, can bring our own perspective, creativity, and purpose to these ideas. The author emphasises that real creativity lies in reimagining how people interact with technology in expressive and human centred ways.

weird switch

For my project, I was inspired from the gym leg adductor machine where you have to close your legs against weight to work on your inner thigh muscle. I created the circuit just like in class but I added the 2 strips of copper tape on my inner thigh so that they when the legs were closed, the electricity would flow through. I also added crocodile clips just to extend the length of the circuit.

IMG_2157

I drew a rough schematic on how I wanted the system to work.