The user would like to see their impact on the project real time, knowing what they are doing–Therefore, we used color detect to detect the motion of the user’s waving the wand, and show the trace on the screen real time. Moreover, the trace would disappear gradually, ensuring that the screen isn’t too messy.
We want the user to do certain gesture to be like performing a magic trick. How the user is to be informed is to indicate the desired gesture on the screen for them to follow–We add a text “follow me” that keeps circling on the screen. The user would naturally follow the circle with their wand. The speed of the text an adjusted to make it comfortable and easy to both for the user to follow and for the computer to detect.
The magic wand and a piece of music from Harry Potter are used. When the user has done the right trick, a parchment with the sentence “Time for magic!” would appear, and a music clip indicating that the user has triggered a magical phenomenon would be played. We want to create a magical atmosphere, especially related to Harry Potter. I am a big fan of Harry Potter, so are many millennials. They would relate to this experience deeply.
The final part of the project is that a robot would move and draw a pattern related to Harry Potter on sand using magnetic balls. However, due to the time limit, we weren’t able to figure it out. Choosing this robot is because the magnetic ball drawing on the sand without seeing a robot driving it (actually it is running underneath the sand table) is a magical scene. It connects to the topic of magic well.
- FABRICATION AND PRODUCTION:
The most significant step is to track the motion of the user well. It occurs that the lighting, the background, the area being tracked and the color itself are all factors that influence the successfulness of color tracking. We at first used a simple method of loading pixels and comparing the color code to spotify the desired color that appears in certain pixels. Then, we find out that it isn’t precise enough during the User test. Therefore, we switch to another method using the OpenCV library.
In the User test, we find out that if the strokes are kept on the screen, the interface would be messy and the user would feel lost of what they are doing. Therefore we make the stroke to vanish after a certain time. In addition, the “follow me” text used to be a green circle that goes slower. It was not tempting for the user to follow. Therefore, we change the circle into the text and adjust the speed. The adaptations worked well later on.
We at first wanted the user to perform a much more complicated magic gesture than drawing a circle. However, we found out that restricting the area to detect and count the pixels is hard. Therefore, it only becomes drawing a circle, which still serves as performing a magic trick. Moreover, we at first wanted to map the user’s drawing in the air onto the drawing on the sand. However, the procedure is too complicated for us, thus we switched to drawing a square that is pre-coded, which still serves as drawing a pattern on the sand with a magnetic ball that creates a magical sense.
The part of the user’s drawing certain gesture that triggers the robot to move gives the user a feeling that they are interacting with the computer. They input the gesture and receive the feedback of both the computer showing “Time for magic” with a sound effect and the car starting suddenly. The whole interaction helps the user to realize an impossible dream that they may know magic. Although it doesn’t include much profundity, arousing the user to think hard, it includes fun, which already fulfills the meaning of interaction.
The audience interacted with my audience in an expected way to perform the magic trick. They learn the scene to be about Harry Potter because of the wand, music, and parchment. Nevertheless, they expect more to happen other than the moving of a robot that seems to be unrelated to Harry Potter.
If we have more time, we will first add a spell for the user to speak out when they are doing the trick with their wand. It would be more like a magic trick when adding this “nonsense”. For the robot drawing on the sand part, I would choose another way to realize the goal of “doing magic”. I would replace the robot with probably a fog machine, a carpet that flows, or Quidditch (Those are elements mentioned in the class review). Those are options that take fewer efforts and the concept of Harry Potter could be emphasized more.
Our biggest problem with this project is that we didn’t expect the workload well and picked on a harder goal that wouldn’t be accomplished within such a short period of time. We should have been more aware of our ability and time limit to make sure the completion of the project. Meanwhile, I’m still proud of what we have accomplished: the mastery of OpenCV, if statement and pixel manipulation.
To create a magical world where happiness is all around, we should work hard to make people believe that they have the magic to make the world a better place.
Processing:
Arduino:
/* Encoder Library – TwoKnobs Example
http://www.pjrc.com/teensy/td_libs_Encoder.html
This example code is in the public domain.
*/
#include <Encoder.h>
int state = 0;
// Change these pin numbers to the pins connected to your encoder.
// Best Performance: both pins have interrupt capability
// Good Performance: only the first pin has interrupt capability
// Low Performance: neither pin has interrupt capability
Encoder knobLeft(2, 11);
Encoder knobRight(3, 12);
// avoid using pins with LEDs attached
const int motor_l_E = 9;
const int motor_l_A = 8;
const int motor_l_B = 7;
const int motor_r_E = 5; //flipped this pin because it has PWM
const int motor_r_A = 6;
const int motor_r_B = 4;
void setup() {
Serial.begin(9600);
Serial.println(” Encoder Test:”);
pinMode(motor_l_E, OUTPUT);
pinMode(motor_l_A, OUTPUT);
pinMode(motor_l_B, OUTPUT);
pinMode(motor_r_E, OUTPUT);
pinMode(motor_r_A, OUTPUT);
pinMode(motor_r_B, OUTPUT);
motorStop();
pinMode(13, OUTPUT);
}
void loop() {
if (Serial.available() > 0) { // Checks whether data is comming from the serial port
state = Serial.read(); // Reads the data from the serial port
}
// if (newLeft != positionLeft || newRight != positionRight) {
// Serial.print(“Left = “);
// Serial.print(newLeft);
// Serial.print(“, Right = “);
// Serial.print(newRight);
// Serial.println();
// positionLeft = newLeft;
// positionRight = newRight;
// }
// // if a character is sent from the serial monitor,
// // reset both back to zero.
// if (Serial.available()) {
// Serial.read();
// Serial.println(“Reset both knobs to zero”);
// knobLeft.write(0);
// knobRight.write(0);
// }
if (state == ‘1’) {
// goStraight();
Serial.println(“go!”);
digitalWrite(13, HIGH);
forward( 1000) ;
rotate(300);
forward( 1000) ;
rotate(180);
forward( 1000) ;
rotate(180);
forward( 1000) ;
// forward( 1000) ;
// forward( 1000) ;
// forward( 1000) ;
motorStop();
delay(20000000);
state=0;
}else{
Serial.println(“stop!”);
motorStop();
digitalWrite(13, LOW);
}
}
void forward( int steps) {
digitalWrite(motor_l_A, HIGH);
digitalWrite(motor_l_B, LOW);
digitalWrite(motor_r_B, LOW);
digitalWrite(motor_r_A, HIGH);
long newLeft, newRight;
knobLeft.write(0);
knobRight.write(0);
int spd = 150;
while ( abs(knobLeft.read()) < steps ) {
newLeft = knobLeft.read();
newRight = -knobRight.read();
int dif = (newLeft – newRight) /2;
Serial.print(“Left = “);
Serial.print(newLeft);
Serial.print(“, Right = “);
Serial.print(newRight);
Serial.print(“, dif = “);
Serial.print(dif);
Serial.println();
Serial.println();
analogWrite(motor_l_E, spd + dif);
analogWrite(motor_r_E, spd – dif);
}
motorStop();
}
void back( int steps) {
digitalWrite(motor_l_A, LOW);
digitalWrite(motor_l_B, HIGH);
digitalWrite(motor_r_B, HIGH);
digitalWrite(motor_r_A, LOW);
long newLeft, newRight;
knobLeft.write(0);
knobRight.write(0);
int spd = 150;
while ( abs(knobLeft.read()) < steps ) {
newLeft = knobLeft.read();
newRight = -knobRight.read();
int dif = -(newLeft – newRight) /2;
Serial.print(“Left = “);
Serial.print(newLeft);
Serial.print(“, Right = “);
Serial.print(newRight);
Serial.print(“, dif = “);
Serial.print(dif);
Serial.println();
Serial.println();
analogWrite(motor_l_E, spd + dif);
analogWrite(motor_r_E, spd – dif);
}
motorStop();
}
void motorStop() {
digitalWrite(motor_l_A, LOW);
digitalWrite(motor_l_B, LOW);
digitalWrite(motor_r_B, LOW);
digitalWrite(motor_r_A, LOW);
analogWrite(motor_l_E, 0);
analogWrite(motor_r_E, 0);
}
void rotate( int steps) {
digitalWrite(motor_l_A, HIGH);
digitalWrite(motor_l_B, LOW);
digitalWrite(motor_r_A, LOW);
digitalWrite(motor_r_B, HIGH);
long newLeft, newRight;
knobLeft.write(0);
knobRight.write(0);
int spd = 150;
while ( abs(knobLeft.read()) < steps ) {
newLeft = knobLeft.read();
newRight = -knobRight.read();
int dif = (newLeft – newRight) /2;
Serial.print(“Left = “);
Serial.print(newLeft);
Serial.print(“, Right = “);
Serial.print(newRight);
Serial.print(“, dif = “);
Serial.print(dif);
Serial.println();
Serial.println();
analogWrite(motor_l_E, spd + dif);
analogWrite(motor_r_E, spd – dif);
}
motorStop();
}