BubbleChair- Yanny- Andy Garcia
CONTEXT AND SIGNIFICANCE
My research on interactive design, particularly inspired by Don Norman’s The Design of Everyday Things, forms the foundation of my midterm project, ChairSurprise. Norman’s principles highlight that great design should be intuitive and user-friendly, inviting people to engage effortlessly with the experience. He emphasizes the power of simplicity and familiar forms to create positive, memorable interactions. With this in mind, I envisioned a project that goes beyond utility, aiming to evoke joy and surprise.
ChairSurprise transforms the ordinary act of sitting into a delightful experience. Upon sitting, the music “Dynamite” plays, and as users spin, they’re surrounded by colorful bubbles, adding an unexpected twist. This simple, familiar interaction carries a hidden surprise, washing away fatigue and bringing moments of lightheartedness.
The bubble element in ChairSurprise draws from BubbleTime, a project where bubbles entertain kids through a pressure sensor in a pillow, triggered by hugs. Inspired by Peter Pan, I wanted to evoke the playful, nostalgic joy that bubbles bring, especially for adults seeking relief from daily routines. ChairSurprise aims to provide both relaxation and a return to childlike wonder, making it uniquely valuable for anyone needing a refreshing break.
CONCEPTION AND DESIGN
sketch for the initial idea
Refinement of Idea
Understanding user interaction with ChairSurprise guided key design decisions. Initially, we envisioned a “surprise corner” with multiple interaction points; however, based on instructor Andy’s advice to focus our design, we chose to concentrate on enhancing the interactive experience of a single chair. This focus allowed us to refine each interaction and ensure that the surprise elements were more impactful.
Material list
swivel chair*1
pressure sensor*1
DFPlayerMini*1
Rotary Encoder*1
Rubber wheel*1
servo*2
Bubble gun*2
Arduino*1
Breadboard*1
M/M & M/F cables
cardboards, paperboards, strings
Design Elaboration
The design of ChairSurprise unfolds in two stages. In the first stage, a pressure sensor is positioned on the chair to detect when a user sits down, triggering the DFPlayerMini to start playing music. The music stops when the user leaves, creating an intuitive, responsive interaction. Initially, we considered using a touch sensor; however, instructor Andy advised us that touch sensors require direct skin contact, which would not work effectively with a chair. Instead, Andy recommended a pressure sensor, which proved to be a more suitable and reliable choice for detecting seated presence.
⬅️ initial plan with DC sensor
⬆️change with Rotary encoder and wheel
The second stage—detecting chair rotation—presented a unique challenge. With Andy’s guidance, we incorporated a rotary encoder into a wheel attached to the chair’s spine and apply the hot glue on the edge of the wide spine, preventing the string from out-slipping to ensure stability of the wheel ( but not presented in this picture yet). As the chair spins, the wheel rotates, allowing the rotary encoder to detect movement. This rotation data signals the servos to activate, pressing the bubble gun triggers at specific intervals. When each servo reaches the designated angle, it presses the trigger, releasing bubbles; when it turns back, the bubbles stop.
In an earlier attempt, we used a DC motor as a rotation sensor, but it proved overly sensitive, causing inconsistent signals that disrupted the servos’ functionality. The rotary encoder provided a more stable and precise alternative, ensuring a smoother, more reliable interaction.
This focused two-stage design and choice of materials emphasize the simplicity, responsiveness, and surprise elements central to ChairSurprise, making it engaging and delightful for users.
FABRICATION AND PRODUCTION
Work Division
My primary responsibility in this project was coding and fabrication, while Tina focused on decoration and assembly/disassembly, also assisting with certain technical tasks. Together, we brainstormed and developed the proposal, then worked on our individual parts based on our schedules. We maintained real-time updates via WeChat, which enabled us to seamlessly build on each other’s work without compromising progress. We reconvened for final adjustments and testing before the user test and presentation. Our collaboration was highly effective, allowing us to stay aligned and continue each other's work fluidly.
Yanny is working, 17th Oct.
Tina is working, 17th, Oct.
Challenges Overview
The primary challenges emerged around integrating the pressure sensor and ensuring smooth operation of the servo motor for bubble release, especially in detecting chair rotation. During the initial user test, our use of a DC motor as a rotation sensor and vulnerable code caused the servo to malfunction, resulting in continuous ticking that disrupted bubble release.
In contrast, the pressure sensor for music control performed better but still required refinements. At first, the DFPlayerMini played music inconsistently: it sometimes continued playing after the user left the chair, or restarted repeatedly. With Fellow Kevin's suggestion, I connected the DFPlayerMini's busy pin to the Arduino, allowing it to check the music state. This change allowed us to control the music more effectively, solving the main issue before user testing. But the sensitivity of the pressure sensor remained a problem where the sensor occasionally failed to detect lighter users, or it would stop the music abruptly if users shifted slightly.
Refinement after the User Test
Receiving feedback from the User Test, we worked on refining our project. To address the issue of the pressure- music stage, I adjusted the sensor’s sensitivity by lowering the sensorVal threshold from 100 to 20, and repositioned it to the underside of the left thigh area for more consistent pressure detection. I also modified the code, switching from play() and stop() commands to start() and pause() so that music could resume where it left off, ensuring a seamless listening experience.
if (sensorVal1 > 20 && digitalRead(9) == HIGH) { // Only play if music is not busy (HIGH = not playing) myDFPlayer.start(); // Resume music} else if (sensorVal1 <= 20 && digitalRead(9) == LOW) { // Only stop if music is busy (LOW = playing) myDFPlayer.pause(); // Pause music}
The rotation detection required a major revision. Besides replacing the DC sensor with a rotation encoder I have explained before, I rewrote the code's logic: Initially, our code used a basic logic that checked if the chair was either "spinning" or "not spinning" to control the servo motor that triggered the bubble gun. When the code detected "spinning," the servo would activate and press the bubble gun’s trigger. When it detected "not spinning," the servo would deactivate, releasing the trigger. However, this simple on/off logic caused the servo to behave erratically, frequently switching between states even when the chair rotated slightly or momentarily paused. This led to the servo constantly "ticking" on and off, which caused the bubble gun to spray bubbles inconsistently.
To solve this, I added a 2-second timer to the code. Here’s how it worked:
Extended Action: When the code detected "spinning," it would activate the servo and initiate a timer that kept it engaged for 2 seconds.
Smooth Reset: The servo would hold the bubble gun’s trigger for the full 2 seconds, regardless of minor pauses or slight changes in the chair’s rotation. After the timer expired, the servo would automatically return to its original position, releasing the trigger.
This change made the servo's movements more predictable and ensured that bubbles were released in a smooth, continuous flow. The 2-second delay helped prevent the servo from reacting too sensitively to every small motion, creating a more stable and enjoyable interaction for users.
if (startTime != -1 && millis() - startTime > 2000) { // Returns servos to their original position myservo1.write(30); myservo2.write(30); startTime = -1; // Resets timer once action is complete}
Physically, I made several adjustments to the electronics setup. Initially, we taped components like the Arduino, breadboard, and speaker under the seat, which proved difficult to manage. I created a cardboard platform under the seat to organize and secure each component, making it easy to access and modify connections as needed. Additionally, I added a second bubble gun to the setup, enhancing the visual effect and reinforcing the element of surprise. Tina contributed by adding decoration, making the chair visually appealing and engaging.
User testing provided essential insights that significantly influenced our production choices. Feedback helped us find the ideal placement and sensitivity for the pressure sensor and identify the underlying issues in the rotation-detection system. Many users also provided practical suggestions that led to additional refinements and improvements in our project.
By addressing these challenges and integrating user feedback, we created a well-functioning, entertaining, and surprising experience with ChairSurprise that aligns with our project goals of interaction, joy, and novelty. The iterative improvements we implemented throughout production were crucial to achieving a polished and enjoyable final product.
Final version of the Code
#include "DFRobotDFPlayerMini.h"
#include <SoftwareSerial.h>
#include <Servo.h>
// DFPlayer setup
SoftwareSerial softSerial(10, 11); // RX, TX for DFPlayer
DFRobotDFPlayerMini myDFPlayer;
int sensorVal1; // Sensor for music trigger
int volume = 0;
//Rotary Encoder
*This was adapted from the tutorial found here
*https://github.com/ima-nyush/Interaction-Lab/tree/main/Tutorials/Rotary%20Encoder
int clkPin = 7;
int dtPin = 6;
int swPin = 8;
long startTime = -1; // stopped by default
int pollRate = 25000; //in uS
// Servo setup
Servo myservo1; // Servo motor on the right
Servo myservo2;// Servo motor on the left
void setup() {
Serial.begin(9600);
//RE intialization
pinMode(clkPin, INPUT);
pinMode(dtPin, INPUT);
pinMode(swPin, INPUT);
// DFPlayer initialization
softSerial.begin(9600);
pinMode(9, INPUT); // Attach DFPlayer to pin9 to check whether it is busy
if (!myDFPlayer.begin(softSerial, /*isACK = */ false, /*doReset = */ false)) {
Serial.println("Error starting DFplayer");
while (true)
; // Stop the program if DFPlayer is not detected
}
myDFPlayer.volume(5); // Set volume value (0 to 30)
// Servo initialization
myservo1.attach(3); // servo1
myservo2.attach(5);//servo2
}
void loop() {
//pressure sensor & DFPlayer
sensorVal1 = analogRead(A0); //the value of pressure sensor
Serial.print("pressure:");
Serial.println(sensorVal1);
if (sensorVal1 > 20 && digitalRead(9) == HIGH) { // Only play if music is not busy (HIGH = not playing)
myDFPlayer.start(); // Resume music
} else if (sensorVal1 <= 20 && digitalRead(9) == LOW) { // Only stop if music is busy (LOW = playing)
myDFPlayer.pause(); // Pause music
}
//RE & servo
unsigned long timeStarted = micros();
int clkStateOld = digitalRead(clkPin);
//give window of time(default 25ms) to register pulse
while (micros() <= timeStarted + pollRate) {
int clkState = digitalRead(clkPin);
int dtState = digitalRead(dtPin);
if (clkState == HIGH && clkState != clkStateOld) { //rising
Serial.println("spinning");
startTime = millis();
}
clkStateOld = clkState;//update the state
}
if (startTime != -1 && millis()-startTime < 2000) {
// servo action
myservo1.write(60);
myservo2.write(60);
}
if (startTime != -1 && millis()-startTime > 2000) {
//servo return original position
myservo1.write(30);
myservo2.write(30);
startTime = -1; // when we’re done, set this back to stopped
}
delay(50); //a slight delay to Stabilize sensor readings for both sensors
}
Conclusion
Results and Feedback
Our project aimed to amuse and delight users, and I was thrilled to see genuine happiness reflected in their reactions. One user even commented, "It does make people happy," confirming that we achieved our primary goal. Additionally, everyone intuitively understood how to interact with the project, which validated our design principles of Discoverability and Understanding (Don Norman2013) . Hopefully this simple yet engaging interaction creates an enjoyable "dialogue" between the users and our project.
Future Improvement
However, if we had more time, we would address some interaction issues. Andy suggested integrating the servo control with the pressure sensor, as the current setup has a two-second delay before the servo resets. This sometimes causes the bubble release to continue even when users have left the chair, leading to confusion. Especially if the chair was just rotated by someone passes by, but the bubbles spray out. By using the pressure sensor as the main switch, bubbles would release only when a user is seated, which would make the interaction more logical and consistent. With additional time, we could also add more stages to the interaction or even create an immersive "surprise corner", to achieve our primitive ambition.
Takeaway
From this project, I learned valuable lessons in scientific debugging. When issues arose, I used sample code to isolate each part of the circuit, pinpointing the problems accurately. This process made me more comfortable with Arduino components, including troubleshooting common issues like a stuck servo. I also realized the importance of seeking guidance, consulting instructors and fellows helped streamline our process and enhance our learning.
Finally, I learned that courage to start over is crucial. Mistakes were inevitable, and we had to rework both our code logic and physical design—especially for the rotary encoder. Each iteration demanded patience and resilience, essential qualities that helped us achieve a successful outcome.