“The Story of a Butterfly” -Interaction Lab Final project | Bella and Yiru

INTRODUCTION

Link of the project: 
1.https://drive.google.com/file/d/19wAvjcShg_3bLxiIAJcliEN7BIqsdSc8/view?usp=sharing
2.https://drive.google.com/file/d/1PikyP3So-z7nOUsvadH-Hg8t8R5Z73MI/view?usp=drive_link

Title

“The Story of a Butterfly”

CONCEPTION AND DESIGN

The concept of this project is the life story of a butterfly. While seeking inspiration, I noticed many interactive Arduino bionic projects focused on the fluttering of butterfly wings. These projects are fascinating and beautiful. However, few pay attention to the butterfly’s early life stages. Initially, they are not the beautiful creatures we imagine, but green, unattractive caterpillars on branches, vulnerable to becoming bird prey. Only after hard work and a long wait do they emerge as stunning butterflies. My project aims to showcase this transformation, incorporating interactive elements during the caterpillar and cocoon stages, using a butterfly model with Arduino motors and Strips to emphasize the beauty and create a visual impact, prompting viewers to reflect and appreciate.

FABRICATION AND PRODUCTION

1. Scheduling:

First, we assessed the main tasks and established a schedule. Our steps mainly involve creating the computer screen background, decorating the backdrop, and crafting the mesmerizing butterfly. Next, we concealed a servo motor and white thread based on the butterfly’s size to ensure it initially remains hidden at the top of the device, then can fully emerge. Finally, we installed a pressure sensor at the bottom to achieve interactive effects.

Link of my draft: 
https://drive.google.com/file/d/1sUGcQgoMCoJPUhMnrOBxml9I2F8CDn5g/view?usp=drive_link
Link of the processing pictures: 
https://drive.google.com/file/d/18-88W59-mFLDvkPLe7vsN-vZfHNNUJ44/view?usp=drive_link
https://drive.google.com/file/d/1VMjgSnKu7uOO4JFOzqV2TBBBDoasMQVw/view?usp=drive_link
https://drive.google.com/file/d/1_ZylGRT61loMlJWMcSku0fRIA6LOlL2b/view?usp=drive_link
https://drive.google.com/file/d/1rkm3FR9I42JmVbSQSzag5j4F15lD3CXX/view?usp=drive_link
https://drive.google.com/file/d/1IxI07VHxLBixHot7hYbPz1hILNtxNPNV/view?usp=drive_link

2.Production Process:

The focal element in our project’s construction was the butterfly, crafted using 3D pencils to enhance the depth and beauty of the 3D experience. We integrated a motor sensor, selected for its ability to demonstrate controlled rotational movement, which activates when users press a button. Initially, a larger motor was considered, but its size and weight were impractical. Alongside this, a pressure sensor narrates the butterfly’s story. The coding process involved transferring data from Arduino to the processing unit, vital for both the butterfly’s story and its 3D representation.

Link of the pictures: 
https://drive.google.com/file/d/16haWb417j15rESp7WnOubLTcU5B66--A/view?usp=drive_link
https://drive.google.com/file/d/1wFF749tU8CId8YZDUUPm6SCJSZaqnBh4/view?usp=drive_link
https://drive.google.com/file/d/14cn1HcdtR9MQ7U2o_iGuMp9yjI1T6DNQ/view?usp=drive_link
https://drive.google.com/file/d/1CmPaDuXaU1NlnMPDiIbcRa_RvOHIR1ZA/view?usp=drive_link
https://drive.google.com/file/d/1tO5Z-YdX_rjt7_dVULTLGRM0bw_nKbfm/view?usp=drive_link
https://drive.google.com/file/d/17eu-kt5j3DCo1Z76WuVVEc2J-kfIsSPa/view?usp=drive_link

CONCLUSIONS:

To summarize the project’s conclusion from a different perspective: Our primary aim was to highlight the often-overlooked butterfly story. Reflecting on the project, I see room for improvement, especially in increasing interactive elements, as suggested by our audience. My understanding of interaction aligns well with the project’s design. Given more time, I’d enhance interactivity with additional sensors. This project taught us valuable lessons in time management, prioritizing, and the efficiency of collaborative work. Our teamwork was exemplary, and our combined ideas and learnings from the semester have the potential to make a significant impact.

My code of Arduino:

#define NUM_OF_VALUES_FROM_PROCESSING 1 /* CHANGE THIS ACCORDING TO YOUR PROJECT */

/* This array stores values from Processing */

int processing_values[NUM_OF_VALUES_FROM_PROCESSING];

#include <Adafruit_NeoPixel.h>

#ifdef __AVR__

#include<avr/power.h>// Required for 16 MHz Adafruit Trinket

#endif

#define PIN1 2 //灯带1引脚

#define NUMPIXELS1 16 // Popular NeoPixel ring size

#define PIN2 3 //灯带2引脚

#define NUMPIXELS2 16 // Popular NeoPixel ring size

Adafruit_NeoPixel pixels1(NUMPIXELS1, PIN1, NEO_GRB + NEO_KHZ800);

Adafruit_NeoPixel pixels2(NUMPIXELS2, PIN2, NEO_GRB + NEO_KHZ800);

int Val4=0;

#include <Servo.h>

Servo myservo;

void setup()

{

Serial.begin(9600);

myservo.attach(9);

myservo.write(90);

// These lines are specifically to support the Adafruit Trinket 5V 16 MHz.

// Any other board, you can remove this part (but no harm leaving it):

#ifdefined(__AVR_ATtiny85__) && (F_CPU == 16000000)

clock_prescale_set(clock_div_1);

#endif

// END of Trinket-specific code.







}

void loop()

{

getSerialData();

//压力传感器

int sensor0 = analogRead(A0);

int sensor1 = analogRead(A1);

int sensor2 = analogRead(A2);

String Send = (String)sensor0 + "," + (String)sensor1 + "," + (String)sensor2 + "," + (String)Val4;




if (processing_values[0] == 0)

{

RGB_Show1(0,0,0,0);

RGB_Show2(0,0,0,0);

Val4=0;

}

elseif (processing_values[0] == 1) //LED灯带点亮--绿色,亮度50

{ //FastLED.setBrightness(128);

RGB_Show1(255,255,224,255);

RGB_Show2(255,255,224,255);

Val4=0;

}

elseif (processing_values[0] == 2) // LED改变亮度与颜色--黄色,亮度150

{

//FastLED.setBrightness(128);

RGB_Show1(85,107,47,255);

RGB_Show2( 85,107,47,255);

Val4=0;

}

elseif (processing_values[0] == 3) // LED改变亮度与颜色--蓝色色,亮度250

{

//FastLED.setBrightness(128);

RGB_Show1(46,139,87,255);

RGB_Show2(46,139,87,255);

Val4=0;

}

elseif (processing_values[0] == 4)

{

RGB_Show1(46,139,87,255);

RGB_Show2(46,139,87,255);

Val4=0;

}

elseif (processing_values[0] == 5 && Val4==0) // LED变暗熄灭

{

for(int i=255;i>=0;i--)

{

RGB_Show1( 105,139,i,250);

RGB_Show2(139,69,19,250);

delay(15);

}

Val4=1; //发送信号给Processing,希望图片5灭

}

elseif (processing_values[0] == 6 && Val4==1) //图片5灭了之后出现图片六,Processing发送指令给Arduino

{ Val4=0;//change to here

myservo.write(90); //顺时针

for(int i=0;i<=300;i++) //控制颜色3秒全亮

{

RGB_Show1( 238,99,99,i);

RGB_Show2(030,144,255,i);

delay(10);

}

myservo.write(45); //逆时针

delay(10);




myservo.write(45); //顺时针

delay(10);

myservo.write(45); //逆时针

delay(10);

myservo.write(45); //顺时针

delay(10);

myservo.write(45); //逆时针

delay(10);

myservo.write(45); //顺时针

delay(10);

myservo.write(90); //逆时针

delay(3000);







}

Serial.println(Send);

delay(200);

// Serial.print(processing_values[0]);Serial.print("\t");

// Serial.print(processing_values[1]);Serial.print("\t");

// Serial.println(processing_values[2]);




}

/* Receive serial data from Processing */

/* You won't need to change this code */

void getSerialData() {

staticint tempValue = 0;

staticint valueIndex = 0;

while (Serial.available())

{

char c = Serial.read();

switch (c) {

case'0' ... '9':

tempValue = tempValue * 10 + c - '0';

break;




case',':

processing_values[valueIndex] = tempValue;

tempValue = 0;

valueIndex++;

break;




case'\n':

processing_values[valueIndex] = tempValue;

tempValue = 0;

valueIndex = 0;

break;

}

}

}

void RGB_Show1(int R,int G,int B,int brightness)

{

for(int i=0; i<NUMPIXELS1; i++)

{

pixels1.setPixelColor(i, pixels1.Color(R, G, B));

pixels1.setBrightness(brightness);

}

pixels1.show();

}

void RGB_Show2(int R,int G,int B,int brightness)

{

for(int i=0; i<NUMPIXELS2; i++)

{

pixels2.setPixelColor(i, pixels2.Color(R, G, B));

pixels2.setBrightness(brightness);

}

pixels2.show();

}
My code of processing:

///p to a
import processing.serial.*;

Serial serialPort;

int NUM_OF_VALUES_FROM_PROCESSING = 1; /* CHANGE THIS ACCORDING TO YOUR PROJECT */
/* This array stores values you might want to send to Arduino */
int processing_values[] = new int[NUM_OF_VALUES_FROM_PROCESSING];




int x1;
int y1;


int NUM_OF_VALUES_FROM_ARDUINO = 4; /* CHANGE THIS ACCORDING TO YOUR PROJECT */
/* This array stores values from Arduino */
int arduino_values[] = new int[NUM_OF_VALUES_FROM_ARDUINO];




boolean moveToTarget = false; // 控制img3是否移动
int shakeCount = 0; // 晃动计数器
int shakeDirection = 1; // 晃动方向


//light
int img5Brightness = 255; // 初始亮度设置为最大值 255


///images

PImage img1, img2, img3, img4, img5, img6;

float img3X = 300; // 初始 X 位置
float img3Y = 535; // 初始 Y 位置
float speed = 2; 
boolean canMoveImg3 = false; // 是否可以移动 img3

float targetX = 940; // 目标 X 坐标
float targetY = 330; // 目标 Y 坐标
float tolerance = 100; // 容忍度,例如 10
boolean draggingImg3 = false;





void setup() {

size(1300, 780);

///p to a
printArray(Serial.list());
// put the name of the serial port your Arduino is connected
// to in the line below - this should be the same as you're
// using in the "Port" menu in the Arduino IDE
serialPort = new Serial(this, "/dev/cu.usbmodem101", 9600);


///
img1 = loadImage("first page.jpg");
img2 = loadImage("background.jpg");
img3 = loadImage("O1.png");
img4 = loadImage("O2.pndg");
img5 = loadImage("second page.jpg");
img6 = loadImage("last page.jpg");
}

int currentImage = 1;

void draw() {

if (currentImage == 1) {
image(img1, 0, 0, width, height);
processing_values[0] = 1; ///0 is for strips

} else if (currentImage == 2) {
image(img2, 0,0, width, height);
processing_values[0] = 2;
//add text "welcome to the world 。。。"

} else if (currentImage == 3) {
image(img2, 0,0, width, height);
image(img3, 300, 535, 250, 200);
//add tsxt for introduction 
processing_values[0] = 3;

} else if (currentImage == 4) {

// 在映射的坐标上绘制图像


image(img2, 0,0, width, height);
image(img3, img3X, img3X, 250, 200); // 绘制 img3 在可移动的位置
image(img4, 0, 0, width, height);
processing_values[0] = 4;




// not sure part
if (arduino_values[0] > 400 && !moveToTarget) {
moveToTarget = true;
}

// img3移动到目标位置
if (moveToTarget && currentImage == 4) {
float dx = targetX - img3X;
float dy = targetY - img3Y;

// 根据速度和距离来更新图像位置
if (abs(dx) > 1) {
img3X += dx * speed / sqrt(sq(dx) + sq(dy));
}
if (abs(dy) > 1) {
img3Y += dy * speed / sqrt(sq(dx) + sq(dy));
}
}


if (abs(img3X - targetX) < tolerance && abs(img3Y - targetY) < tolerance) {
currentImage = 5; // 切换到 img5
moveToTarget = false;
}
}





if (currentImage == 5) {
if (arduino_values[0] == 1) {
img5Brightness = 0; // 当value4等于1时,将亮度设置为0
} else {
// 逐渐减少亮度,直到达到某个最小值
img5Brightness = max(img5Brightness - 1, 0); // 每次减少1,但不低于0
}

tint(255, img5Brightness); // 应用亮度调整
image(img5, 0, 0, width, height); // 显示图像
processing_values[0] = 5;

// 重置tint以影响其他图像
tint(255, 255);
delay(250); //let the screen be black for a while

} else if (currentImage == 6) {
image(img6, 0, 0, width, height);
processing_values[0] = 6;
}
// send the values to Arduino
sendSerialData();

}

void mousePressed() {
if (currentImage < 6) {
currentImage++;
} else {
currentImage = 1;
}
}


/// send to a
void sendSerialData() {
String data = "";
for (int i=0; i<processing_values.length; i++) {
data += processing_values[i];
// if i is less than the index number of the last element in the values array
if (i < processing_values.length-1) {
data += ","; // add splitter character "," between each values element
}
// if it is the last element in the values array
else {
data += "\n"; // add the end of data character linefeed "\n"
}
}
// write to Arduino
serialPort.write(data);
print("To Arduino: " + data); // this prints to the console the values going to arduino

while (serialPort.available() > 0) {
String in = serialPort.readStringUntil( 10 ); // 10 = '\n' Linefeed in ASCII
if (in != null) {
print("From Arduino: " + in);
String[] serialInArray = split(trim(in), ",");
if (serialInArray.length == NUM_OF_VALUES_FROM_ARDUINO) {
for (int i=0; i<serialInArray.length; i++) {
arduino_values[i] = int(serialInArray[i]);
}
}
}
}



}

Leave a Reply

Your email address will not be published. Required fields are marked *