final
Date:15 December 2024 | Course: Interaction Lab
documentation
final
Date:15 December 2024 | Course: Interaction Lab
documentation
|A. Happy New Year!|
Created by Xianxian (Tina) Yang & Leying (Alice) Guo
Instructed by Andy Garcia
B. VIDEO DOCUMENTATION
C.CONCEPTION AND DESIGN
This project is an interactive installation that simulates the process of lighting fireworks for the New Year. Users can use a real lighter to ignite the bombs on the firework box, and the neopixels will simulate the real fuse burning gradually until triggering the electronic fireworks. In this project, we have set up four types of fireworks: heart fireworks, star fireworks, sparks fireworks, and happy 2025 fireworks. They represent the messages “Star your new year with love”,“Best wishes for the best year”, “Kindle your passion”, and “Happy New Year” respectively. These four messages are also displayed in the form of blessing tags on the firework box, symbolizing best wishes for the new year. When we selected the topic for the entire project, we found in our research that Shanghai has strictly prohibited the setting off of fireworks and firecrackers in the city area in recent years, leading to a sense of missing New Year atmosphere among the people. This project aims to reshape the New Year ambiance in an environmentally friendly manner: by igniting non-polluting electronic fireworks, people can still experience the excitement of lighting the fuse with a lighter and the anticipation of the fireworks igniting. In other words, this project hopes to restore the essence of New Year through innovative means.
However, the final outcome of this project actually underwent numerous adjustments, with the most impactful stage being user testing. In the initial concept, we had set up four types of sensors: button, light sensor, temperature sensor, and sound sensor, each corresponding to a different interactive method, which in turn triggered a different firework display. For example, if a user were to say “happy new year” into the microphone, it would trigger the “happy new year” firework. During user testing, we found that users were confused about how to interact with the device. Each sensor had a different triggering mechanism, requiring users to learn a new way to interact at each stage, which was overly complex. Additionally, users did not understand the connection between the four sensors and the fireworks. Therefore, after user testing, we replaced the four different sensors with a single temperature sensor and unified the four different interactive methods into igniting a bomb. During the final presentation, we clearly felt that users' confusion about how to interact with the device had significantly decreased. The firework box and the bomb made them naturally want to ignite it. After igniting the first firework, users were also filled with anticipation for what other fireworks would follow. After undergoing these adjustments, the theme of the entire project became clearer, more realistically depicting the process of igniting fireworks, and the method of triggering the device became more innovative.
The initial conception
The process diagram for the final project
D. FABRICATION AND PRODUCTION
The three major parts of our project are neopixel controlling, firework video playing and fabrication, which I and Alice completed jointly. We started with the electronics part, aiming to achieve the effect where the Neopixel would simulate a fuse being triggered by a sensor. Before user testing, we encountered issues where the button, light sensor, temperature sensor, and sound sensor could not be reliably triggered independently. For instance, during the user testing process, setting the threshold for the sound sensor was very challenging. If the sensor became too sensitive, the device would be triggered constantly, and if it became less sensitive, even loud sounds from the user wouldn't trigger the device. After user testing, in addition to the reasons mentioned in the conception and design phase, we also unified the four sensors into a temperature sensor due to technical reasons. At this stage, we faced the issue where individual temperature sensors could control their corresponding Neopixels, but when they were all connected to one board, the Neopixels would not function properly. Later, we discovered that this was a power supply issue.
In terms of Processing, initially, we set up Arduino to send a signal '11' to the serial monitor when a sensor was triggered, and Processing would play the corresponding video upon receiving '11'. However, when the device had four temperature sensors, this code would continuously play a single video. Therefore, we modified the Processing code to directly receive the sensor values. When the value exceeded a certain limit, the corresponding video would play. This adjustment deepened my understanding of how serial communication operates. After the modification, each time a sensor was triggered, the video would play only once. Finally, we focused on digital fabrication, using laser cutting to create the firework box and 3D printing to make the bomb. During this stage, we gave a lot of thought to how to conceal the temperature sensor, as exposing the sensors directly to users for ignition would diminish the authenticity. Ultimately, we opted for the bomb because it would hint to users that they needed to ignite it to trigger the device. In this phase, we found a template for the bomb and customized it by adding a hole to allow wires and sensors to pass through. During the final presentation, users also praised the design of the bomb, finding it simple and easy to understand."
void draw() {
getSerialData();
buttonPressed = arduino_values[0] == 11; // Check if the button is pressed (receiving "11" from Arduino)
// If the button is pressed and video is not playing yet
if (buttonPressed && !videoPlaying) {
myMovie.jump(0); // Reset the video to the beginning
myMovie.play(); // Start playing the video from the beginning
videoPlaying = true; // Set the video state to playing
}
// Check if the video has finished playing
if (videoPlaying && !myMovie.isPlaying()) {
videoPlaying = false; // Update the state to reflect that the video has finished
}
Processing code before revision
void draw() {
getSerialData(); // Get data from Arduino
// Assign the temperature sensor values to individual variables
temperature1 = arduino_values[0];
temperature2 = arduino_values[1];
temperature3 = arduino_values[2];
temperature4 = arduino_values[3];
// Check and play the corresponding video based on the sensor readings
if (temperature1 > 56 && !videoPlaying) {
videoFile = "111.mp4"; // Set the video file to "111.mp4"
startVideo();
} else if (temperature2 > 56 && !videoPlaying) {
videoFile = "222.mp4"; // Set the video file to "222.mp4"
startVideo();
} else if (temperature3 > 56 && !videoPlaying) {
videoFile = "333.mp4"; // Set the video file to "333.mp4"
startVideo();
} else if (temperature4 > 56 && !videoPlaying) {
videoFile = "444.mp4"; // Set the video file to "444.mp4"
startVideo();
}
Processing code after revision
Customized template for 3D printing
E. CONCLUSIONS
Our project aims to create electronic fireworks in an innovative way, recreating the New Year atmosphere while protecting the environment. Our final outcome achieved this goal. During the showcase, users can ignite the device using a real lighter, triggering four different types of fireworks. The fun of interaction between users and the device comes from the action of igniting the fireworks, which simulates reality, while the ignition of the electronic wires and fireworks departs from reality. I believe one of the most successful aspects of our project lies in our interactive approach, which goes beyond common methods like keyboards and buttons in modern society, maximizing the surprise and excitement of igniting fireworks. The process of creating this project was not smooth sailing; we faced many more challenges than what is presented in this blog. However, it was in solving these problems that I deeply understood the meaning of 'creation is not a linear process.' After user testing, we overturned a significant portion of the design, which ultimately became the key to elevating our project. Given more time, we might change the design of the neopixels to make their illumination transition from fully lit to dark, to more realistically simulate the process of a wire being burned short. Additionally, we might incorporate firecracker designs to better evoke the 'festive flavor' of China. I hope you enjoy this project that we put our hearts into, filled with childlike wonder. Even more, I hope it evokes memories of your childhood, igniting a cluster of fireworks during the New Year in your hometown—a seemingly trivial yet precious moment.
F. DISASSEMBLY
F. APPENDIX
Full Arduino Code:
#include <FastLED.h>
#define NUM_LEDS 60 // 每个灯带的 LED 数量
#define TEMP_SENSOR_PIN_A0 A0 // 第一个温度传感器 (A0)
#define TEMP_SENSOR_PIN_A1 A1 // 第二个温度传感器 (A1)
#define TEMP_SENSOR_PIN_A2 A2 // 第三个温度传感器 (A2)
#define TEMP_SENSOR_PIN_A3 A3 // 第四个温度传感器 (A3)
#define TEMP_THRESHOLD 56 // 温度阈值,超过该温度时触发 LED 效果
#define DATA_PIN_1 3 // 第一个 LED 灯带的控制引脚
#define DATA_PIN_2 5 // 第二个 LED 灯带的控制引脚
#define DATA_PIN_3 6 // 第三个 LED 灯带的控制引脚
#define DATA_PIN_4 9 // 第四个 LED 灯带的控制引脚
CRGB leds1[NUM_LEDS]; // 第一个 LED 灯带
CRGB leds2[NUM_LEDS]; // 第二个 LED 灯带
CRGB leds3[NUM_LEDS]; // 第三个 LED 灯带
CRGB leds4[NUM_LEDS]; // 第四个 LED 灯带
int next_led = 0; // 跟踪下一个需要点亮的 LED
float lastTemperature = 0; // 存储上一个温度值
unsigned long lastTime = 0; // 上次读取温度的时间
bool temperatureExceededA0 = false; // 第一个传感器超过阈值的标志
bool temperatureExceededA1 = false; // 第二个传感器超过阈值的标志
bool temperatureExceededA2 = false; // 第三个传感器超过阈值的标志
bool temperatureExceededA3 = false; // 第四个传感器超过阈值的标志
void setup() {
Serial.begin(9600);
// 初始化每个灯带
FastLED.addLeds<NEOPIXEL, DATA_PIN_1>(leds1, NUM_LEDS); // 第一个灯带
FastLED.setBrightness(50); // 设置亮度
FastLED.addLeds<NEOPIXEL, DATA_PIN_2>(leds2, NUM_LEDS); // 第二个灯带
FastLED.setBrightness(50); // 设置亮度
FastLED.addLeds<NEOPIXEL, DATA_PIN_3>(leds3, NUM_LEDS); // 第三个灯带
FastLED.setBrightness(50); // 设置亮度
FastLED.addLeds<NEOPIXEL, DATA_PIN_4>(leds4, NUM_LEDS); // 第四个灯带
FastLED.setBrightness(50); // 设置亮度
// 初始化所有灯带为关闭状态
turnOffAllLEDs();
delay(3000); // 初始延迟
}
void loop() {
unsigned long currentTime = millis();
// 每隔 10 毫秒检查一次温度传感器
if (currentTime - lastTime >= 10) {
lastTime = currentTime;
// 读取所有温度传感器的值
int sensorValueA0 = analogRead(TEMP_SENSOR_PIN_A0); // 读取温度传感器 A0
int sensorValueA1 = analogRead(TEMP_SENSOR_PIN_A1); // 读取温度传感器 A1
int sensorValueA2 = analogRead(TEMP_SENSOR_PIN_A2); // 读取温度传感器 A2
int sensorValueA3 = analogRead(TEMP_SENSOR_PIN_A3); // 读取温度传感器 A3
// 将温度传感器的值发送到串口监视器
Serial.print(sensorValueA0);
Serial.print(",");
Serial.print(sensorValueA1);
Serial.print(",");
Serial.print(sensorValueA2);
Serial.print(",");
Serial.print(sensorValueA3);
Serial.println();
// 检查每个温度传感器是否超过阈值
if (sensorValueA0 > TEMP_THRESHOLD && !temperatureExceededA0) {
Serial.println("Trigger LED effect on A0");
lightUpLEDs(leds1); // 激活第一个 LED 灯带
temperatureExceededA0 = true;
}
if (sensorValueA1 > TEMP_THRESHOLD && !temperatureExceededA1) {
Serial.println("Trigger LED effect on A1");
lightUpLEDs(leds2); // 激活第二个 LED 灯带
temperatureExceededA1 = true;
}
if (sensorValueA2 > TEMP_THRESHOLD && !temperatureExceededA2) {
Serial.println("Trigger LED effect on A2");
lightUpLEDs(leds3); // 激活第三个 LED 灯带
temperatureExceededA2 = true;
}
if (sensorValueA3 > TEMP_THRESHOLD && !temperatureExceededA3) {
Serial.println("Trigger LED effect on A3");
lightUpLEDs(leds4); // 激活第四个 LED 灯带
temperatureExceededA3 = true;
}
// 如果温度低于 50,重置标志,允许下次触发
if (sensorValueA0 < 50 && temperatureExceededA0) {
temperatureExceededA0 = false;
}
if (sensorValueA1 < 50 && temperatureExceededA1) {
temperatureExceededA1 = false;
}
if (sensorValueA2 < 50 && temperatureExceededA2) {
temperatureExceededA2 = false;
}
if (sensorValueA3 < 50 && temperatureExceededA3) {
temperatureExceededA3 = false;
}
}
}
void lightUpLEDs(CRGB* leds) {
// 逐个点亮 LED 灯带的 LED,颜色为巧克力色
for (next_led = 0; next_led < NUM_LEDS; next_led++) {
leds[next_led] = CRGB(139, 69, 19); // 设置当前 LED 为巧克力色
FastLED.show(); // 更新 LED 灯带
delay(20); // 延时,模拟逐个点亮的效果
}
// 等最后一个 LED 点亮后,关闭所有 LED
delay(1000);
for (int i = 0; i < NUM_LEDS; i++) {
leds[i] = CRGB::Black; // 关闭所有 LED
}
FastLED.show();
next_led = 0;
}
void turnOffAllLEDs() {
// 关闭所有灯带的 LED
for (int i = 0; i < NUM_LEDS; i++) {
leds1[i] = CRGB::Black;
leds2[i] = CRGB::Black;
leds3[i] = CRGB::Black;
leds4[i] = CRGB::Black;
}
FastLED.show();
}
Full Processing Code:
import processing.serial.*;
import processing.video.*;
Serial serialPort;
int NUM_OF_VALUES_FROM_ARDUINO = 4; // We are receiving 4 values, one for each temperature sensor
int arduino_values[] = new int[NUM_OF_VALUES_FROM_ARDUINO];
Movie myMovie;
boolean videoPlaying = false; // Variable to track video play state
int temperature1, temperature2, temperature3, temperature4;
String videoFile = "444.mp4"; // Default video to play
void setup() {
size(1920, 1080);
background(0);
// Initialize the movie, but don't start it yet
myMovie = new Movie(this, videoFile);
// List available serial ports for debugging
printArray(Serial.list());
// Initialize the serial port, choose the correct port (update with your actual port)
serialPort = new Serial(this, "/dev/cu.usbmodem1101", 9600);
}
void draw() {
getSerialData(); // Get data from Arduino
// Assign the temperature sensor values to individual variables
temperature1 = arduino_values[0];
temperature2 = arduino_values[1];
temperature3 = arduino_values[2];
temperature4 = arduino_values[3];
// Check and play the corresponding video based on the sensor readings
if (temperature1 > 56 && !videoPlaying) {
videoFile = "111.mp4"; // Set the video file to "111.mp4"
startVideo();
} else if (temperature2 > 56 && !videoPlaying) {
videoFile = "222.mp4"; // Set the video file to "222.mp4"
startVideo();
} else if (temperature3 > 56 && !videoPlaying) {
videoFile = "333.mp4"; // Set the video file to "333.mp4"
startVideo();
} else if (temperature4 > 56 && !videoPlaying) {
videoFile = "444.mp4"; // Set the video file to "444.mp4"
startVideo();
}
// Check if the video has finished playing
if (videoPlaying && !myMovie.isPlaying()) {
videoPlaying = false; // Update the state to reflect that the video has finished
}
// Display the current video frame, if available
if (myMovie.available()) {
myMovie.read(); // Read the next frame from the video
}
// Draw the video frame on the screen
image(myMovie, 0, 0, width, height);
}
// Function to start playing a new video
void startVideo() {
myMovie = new Movie(this, videoFile); // Load the new video
myMovie.jump(0); // Reset the video to the beginning
myMovie.play(); // Start playing the video
videoPlaying = true; // Set the video state to playing
}
// Function to read data from the serial port (Arduino)
void getSerialData() {
while (serialPort.available() > 0) {
String in = serialPort.readStringUntil(10); // Read data until newline
if (in != null) {
print("From Arduino: " + in); // Print data from Arduino to Serial Monitor
String[] serialInArray = split(trim(in), ","); // Split the data into an array
if (serialInArray.length == NUM_OF_VALUES_FROM_ARDUINO) { // Ensure we get the right number of values
for (int i = 0; i < serialInArray.length; i++) {
arduino_values[i] = int(serialInArray[i]); // Convert string values to integers
}
}
}
}
}
Citation:
Star firework video:
Sparks firework video:
Happy 2025 firework video:
Bomb template:
Wiring Diagram:
Other photos and videos: