Concept and Design Approach

From Sound to Movement explores the relationship between human interaction, environmental conditions, and adaptive architecture. The project proposes an interactive kinetic pavilion that responds to sound, temperature, and manual input through a series of movable shell panels.
Inspired by the folding mechanism of a fan, the pavilion consists of curved, overlapping panels arranged around a central axis. Their movement allows the structure to transform between different configurations, creating varying degrees of openness, enclosure, and shading.

Parametric Design Exploration
The architectural geometry was developed using Rhino and Grasshopper. Through parametric modelling, different shell configurations were explored by adjusting geometric parameters and studying their transformation.
This digital design process provided an opportunity to investigate how computational geometry could support kinetic movement. The architectural proposal was further developed through visualizations incorporating translucent materials, integrated seating, and lighting to enhance the spatial experience.

Physical Computing and Interactive Systems
The electronic prototype was developed using a Grove Beginner Kit for Arduino, integrated sensors, and two servo motors. The system was programmed to operate through three interaction modes.
Sound Mode: The sound sensor detects sudden changes in sound intensity, such as a finger snap, triggering the servo motors to alternate between two positions.
Automatic Mode: Temperature and humidity measurements influence the servo angles, demonstrating how environmental data can support responsive architectural systems.
Manual Mode: A rotary potentiometer allows users to directly control the servo positions and explore different movement configurations.
A push button enables switching between these modes, while an OLED display provides real-time information about the selected mode and environmental conditions.

Prototyping and Challenges
Testing demonstrated that the electronic system could successfully operate in all three modes, with two servo motors producing coordinated rotational movement.
However, translating this electronic response into a functional kinetic structure remains a key challenge. The limited rotation range of the servo motors and the mechanical connection between the motors and the shell panels require further investigation.
While the electronic prototype was tested physically, the architectural shell was developed as a digital design proposal.

Future Development
Future development will focus on refining the mechanical system, improving the connection between digital geometry and physical movement, and exploring alternative motor solutions. A stepper motor may offer a wider rotation range, although its suitability needs to be tested.
Ultimately, From Sound to Movement demonstrates the potential of combining parametric design and physical computing to create architectural environments that can adapt to users and changing environmental conditions.


Arduino Code
#include <Wire.h>
#include <DHT.h>
#include <Servo.h>
#include <U8x8lib.h>
// SENSORS
DHT dht(DHT20);
// SERVOS
Servo servo1;
Servo servo2;
// OLED – WORKING DRIVER
U8X8_SSD1306_128X64_NONAME_HW_I2C oled(U8X8_PIN_NONE);
// PINS
const int potPin = A0;
const int soundPin = A2;
const int buttonPin = 6;
const int servoPin1 = 7;
const int servoPin2 = 3;
// MODES
// 0 = AUTO
// 1 = MANUAL
// 2 = SOUND
int mode = 0;
// SERVO
int angle = 90;
bool isOpen = false;
// SOUND
const int threshold = 450;
unsigned long lastSnapTime = 0;
// BUTTON
int lastButtonState = LOW;
unsigned long lastPressTime = 0;
// TEMPERATURE AND HUMIDITY
float temperature = 0;
float humidity = 0;
bool sensorOK = false;
unsigned long lastSensorRead = 0;
// DISPLAY
unsigned long lastDisplayUpdate = 0;
void setup() {
Serial.begin(9600);
Wire.begin();
dht.begin();
// OLED SETUP – CORRECT DRIVER
oled.setBusClock(100000);
oled.begin();
oled.clear();
oled.setFlipMode(1); // 180 degrees
oled.clear();
oled.setFont(u8x8_font_chroma48medium8_r);
// BUTTON
pinMode(buttonPin, INPUT);
// SERVOS
servo1.attach(servoPin1);
servo2.attach(servoPin2);
servo1.write(angle);
servo2.write(180 – angle);
}
void loop() {
// 1. BUTTON – CHANGE MODE
int buttonState = digitalRead(buttonPin);
if (buttonState == HIGH &&
lastButtonState == LOW &&
millis() – lastPressTime > 250) {
mode = (mode + 1) % 3;
lastPressTime = millis();
if (mode == 2) {
isOpen = (angle > 90);
lastSnapTime = millis();
}
}
lastButtonState = buttonState;
// 2. READ TEMPERATURE AND HUMIDITY
if (lastSensorRead == 0 ||
millis() – lastSensorRead >= 2000) {
lastSensorRead = millis();
float t = dht.readTemperature();
float h = dht.readHumidity();
if (!isnan(t) && !isnan(h)) {
temperature = t;
humidity = h;
sensorOK = true;
}
}
// 3. AUTO MODE
if (mode == 0 && sensorOK) {
float autoAngle =
160 – (temperature – 24.0) * (140.0 / 6.0);
if (humidity > 60) {
autoAngle = autoAngle – 15;
}
angle = constrain((int)autoAngle, 20, 160);
}
// 4. MANUAL MODE
if (mode == 1) {
int potValue = analogRead(potPin);
angle = map(potValue, 0, 1023, 20, 160);
}
// 5. SOUND MODE
if (mode == 2) {
int soundMin = 1023;
int soundMax = 0;
unsigned long startTime = millis();
while (millis() – startTime < 30) {
int value = analogRead(soundPin);
if (value < soundMin) soundMin = value;
if (value > soundMax) soundMax = value;
}
int soundLevel = soundMax – soundMin;
if (soundLevel > threshold &&
millis() – lastSnapTime > 1200) {
isOpen = !isOpen;
if (isOpen) {
angle = 160;
} else {
angle = 20;
}
lastSnapTime = millis();
Serial.print(“SNAP! Sound: “);
Serial.println(soundLevel);
}
}
// 6. MOVE BOTH SERVOS
servo1.write(angle);
servo2.write(180 – angle);
// 7. OLED DISPLAY
if (millis() – lastDisplayUpdate >= 500) {
lastDisplayUpdate = millis();
oled.clearLine(0);
oled.setCursor(0, 0);
oled.print(“SHELL”);
oled.clearLine(2);
oled.setCursor(0, 2);
oled.print(“Mode: “);
if (mode == 0) oled.print(“AUTO”);
if (mode == 1) oled.print(“MANUAL”);
if (mode == 2) oled.print(“SOUND”);
oled.clearLine(4);
oled.setCursor(0, 4);
oled.print(“Temp: “);
if (sensorOK) {
oled.print(temperature, 1);
oled.print(” C”);
} else {
oled.print(“–“);
}
oled.clearLine(6);
oled.setCursor(0, 6);
oled.print(“Hum: “);
if (sensorOK) {
oled.print(humidity, 1);
oled.print(” %”);
} else {
oled.print(“–“);
}
// SERIAL MONITOR
Serial.print(“Mode: “);
if (mode == 0) Serial.print(“AUTO”);
if (mode == 1) Serial.print(“MANUAL”);
if (mode == 2) Serial.print(“SOUND”);
Serial.print(” Temp: “);
Serial.print(temperature);
Serial.print(” Hum: “);
Serial.print(humidity);
Serial.print(” Angle: “);
Serial.println(angle);
}
delay(10);