Recitation 8: Serial Communication — Shuyang Cai

Exercise 1:

Photos & Video:

Schematic:

Code:

For the first exercise, we are asked to create a sort of a painting brush that shows its trail on the screen. To realize this, we need to transfer two values from Arduino to processing because the ellipse should be set small and the fill of the background doesn’t need to be 0. Also, the x and y of the ellipse should reflect the change of the two potentiometers, so that the ellipse can serve as a brush and we can control which direction it goes by turning the potentiometers.

Exercise 2:

Photos & Video:

Schematic:

Code:

For the second exercise, we need to change the sound of the buzzer by changing its frequency and duration. Also, the frequency and duration should reflect the position of mouseX and mouseY. To realize this, we need to transfer two values from processing to Arduino, so as to change the tone of the buzzer according to the mouse position.

Preparatory Research and Analysis — Shuyang Cai

During the group research project, I attach great importance on the communication between people and machine, for I think that is the essence of interactivity. I believe that makes communication between people and machine complete, there should be three processes, including input, process, and output (Crowford, 5). According to my recognition of interactivity, I designed my midterm project is a way that involves high interactivity between the player and the lights. However, based on my midterm project, I realized my definition of interactivity should also include communication between players. As my midterm project allows two people to play the game at the same time, they should also interact and communicate with each other in terms of interactivity. Also, I realized that to improve the level of interactivity, it is necessary to make the machine or project changeable or even “complicated” to some extent, so that it is more entertaining and people would be more attracted.

During my research, I came across two interesting projects that are very inspirational. The first one is a project called “Melting Memories”, which is “a series of digital artworks that explore the materiality of remembering by offering new insights into the representational possibilities of EEG data collection” (https://www.creativeapplications.net/vvvv/melting-memories-drawing-neural-mechanisms-of-cognitive-control/ ).

Basically, this artwork projects people’s artwork on a huge screen. Although this project does not totally line up with my definition of interaction, as the interactivity seems to be simple and does not need to be explored, this project successfully turns abstract things such as cognitive activity into concrete things like shapes moving on the screen. I think it would be very interesting if my final project could also present an invisible mechanism or process through a certain kind of art.

The second educational project I found is called “Face Trade”, which is an excellent example of the interaction between people and the machine. (https://www.creativeapplications.net/c/face-trade-art-vending-machine-that-trades-mugshots-for-free-portraits/ ). This project enables people to get a unique picture of their face, as long as they stand before the machine and have their photo saved in the system of this machine. To some extent, they trade their face to get a printed picture and I think this is an interesting way to realize a higher level of interaction. And I think it would be interesting if my project could enable people to experience a sort of trade with it.

From my perspective, my “new” definition of interaction would be efficient communications between not only people and machine but also among people and users of the machine. Such communication must involve a certain level of entertainment, and within the reasonable range, the interaction should be interesting, entertaining, to some extent difficult, so that people can enjoy the fun of exploring them and figuring out how it works. It is also in accordance with what Igoe, an interactive artist, says. He argues that artists should not speak too much when people are exploring their work. People should help themselves find out the functions and funs of artists’ work. Therefore, in my final project, I would like to create something that enables users to have more choices and fun. Also, if it is multiuser at the same time, it is important to find out a way to create a certain level of connection between them as well.

Recitation 7: Processing Animation — by Shuyang Cai

In recitation 7, I started from the stick man and create an animated effect. I intend to create a waving person who seems to be looking at the direction of the mouse. During the recitation, I learned how to use pushMatrix and popMatrix, as well as translate and rotate so as to create a waving arm. This recitation also makes me have a better understanding of the if syntax and for loop.

list of interesting functions:

pushMatrix(); // saves the current coordinate system to the stack

popMatrix(); // restores the prior coordinate system.

translate(); // specifies an amount to displace objects within the display window

rotate(radians(angle)); //rotates the amount specified by the angle parameter

random(number); // randomly choose a number within the given range

ellipse(); // create ellipses

int angle = 0;
int x = 145;
int y = 320;
int eyePosition = 0;
void setup(){
size(400, 500);
}

void draw(){
background(0, 0, 0);
fill(48, 172, 209);
triangle(200, 182.5, 235, 280, 165, 280);
fill(255, 255, 255);
ellipse(200, 175, 50, 65);
fill(34, 102, 188);
rect(182, 280, 15, 50);
rect(202, 280, 15, 50);
fill(0,0,0);
ellipse(eyePosition, 167, 10, 10);

fill(34, 102, 188);
pushMatrix();
translate(200, 250);

rotate(radians(angle));
if( angle <= 15 && angle >= -65){
angle = angle + 1;
} else {
angle = -65;
}

//rect(30, -10, 15, 45);
rect(0, -5, 45, 15);

popMatrix();

if (mouseX >= 225){
eyePosition = 210;
}

if (mouseX < 225 && mouseX > 175){
eyePosition = 210;
fill(0,0,0);
ellipse(190, 167, 10, 10);
}

if (mouseX <= 175){
eyePosition = 190 ;
}
fill(random(100, 200),random(0, 100),random(200, 255));
ellipse(mouseX, mouseY, 30, 30);
fill(255, 255, 255);
ellipse(mouseX, mouseY, 20, 20);

}

Additional Recitation Homework:

Step 1:

Step 2:

Step 3:

Midterm project documentation: Light Maze – Shuyang Cai (Eric)

CONTEXT & SIGNIFICANCE:

During my previous research, I believe that it must involve effective communication and a certain level of exploration for a machine to be defined as interactive. Referring back to all the interactive projects I have come across, I found that they mainly fall into two categories: the functional ones (the eye-movement tracking machine for paralyzed people) and the entertaining ones (the R2D2 model shown on the class). Therefore, my partner and I decided to come up with a proposal that not only includes the two crucial characteristics of interactivity but also serves a particular function or entertains people. Basically, the main idea of our project came from one of the tasks during Recitation 3, in which joystick is used to control LEDs. By creating a 3*3 square matrix consisted of LEDs with different colors, we intend to create an entertaining maze game that requires people to reach the endpoint as fast as possible. The use of joystick actually guarantees the effectiveness of the communication between humans and the devices, for the joystick is better at sensing human movements and changing the resistance immediately and accordingly. Also, in order to promote its interactivity and entertaining ability, we designed two sets of mazes, so that two people can play the game at the same time and compete with each other. The significance of this project lies in that, as an entertaining game, everyone is able to play it, compete with their friends and enjoy themselves by doing so.

CONCEPTION AND DESIGN:

Initially, we added an instruction light and a buzzer to promote the interaction between users and our project. Once people successfully reached the endpoint, the instruction light in front of the maze will light up and the buzzer installed in the box will go off. Also, once people move through a LED and light it up, it won’t turn off even after they make the next move, so as to record the paths that users have taken. To make the exterior of the project nice and neat, we designed a box to hide the main body of the circuit, and we decided that the material of the box would be wood, for plastic material is transparent but we don’t want people to see the circuit. It also seems to us that the texture of wood materials is a better fit of the maze than plastic materials. The only tricky thing is that we don’t know how big our box is going to be at the first place, so we actually cut a rather small box and later when we finished building the circuit, we found that there is no way we can put the circuit in the box. Therefore, we had to cut another larger box. We also had to make sure that the holes are of the exact size that the legs of LEDs can go through them, while the bulb has to be stuck on the surface of the board.

Previous version

Final version

Apart from laser cutting the wooden box, another challenge is to write the code. We defined the users’ movement by giving xvalue and yvalue a certain range, and we also used two conditions in an if structure to define which LED lights up once a move is made. However, this way of coding only works with green LEDs, which are designed to be the normal path. When we try to apply the same code to the yellow LEDs, which provide chances of either speed up or slow down, it doesn’t work anymore. However, we eventually fixed this problem with the help of our professor. It turns out that to take every possibility of each move into consideration, it is not enough to just define what the movement is. It is also required to define the current position from which the move is made. Before the users’ test, we had one set of the game done but without any red light, meaning that there is no way a player can die. Everyone can successfully reach the endpoint, it is just a matter of time.

Code:

#include “pitch.h”
int currentPosition = 2;
int melody[] = {
NOTE_C4, NOTE_G3, NOTE_G3, NOTE_A3, NOTE_G3, 0, NOTE_B3, NOTE_C4
};

// note durations: 4 = quarter note, 8 = eighth note, etc.:
int noteDurations[] = {
4, 8, 8, 4, 4, 4, 4, 4
};

void setup() {
// put your setup code here, to run once:
pinMode(2, OUTPUT);
pinMode(3, OUTPUT);
pinMode(4, OUTPUT);
pinMode(5, OUTPUT);
pinMode(6, OUTPUT);
pinMode(7, OUTPUT);
pinMode(8, OUTPUT);
pinMode(9, OUTPUT);
pinMode(10,OUTPUT);
pinMode(11, OUTPUT);
pinMode(12,OUTPUT);
pinMode(13,OUTPUT);
pinMode(A0, INPUT);
pinMode(A1, INPUT);

digitalWrite(2, HIGH);
digitalWrite(10, HIGH);
digitalWrite(12, HIGH);
Serial.begin(9600);

}

void loop() {

int xvalue = analogRead(A1);
int yvalue = analogRead(A0);

boolean moveRight = false;
boolean moveLeft = false;
boolean moveUp = false;
boolean moveDown = false;

if (xvalue < 270) {
moveRight = true;
} else if ( xvalue > 750) {
moveLeft = true;
} else if (yvalue < 270) {
moveUp = true;
} else if (yvalue > 750) {
moveDown = true;
}

// Position 2
if (currentPosition == 2) {
if (moveRight == true) {
currentPosition = 3;
digitalWrite(3, HIGH);
delay(500);
}
if (moveDown == true) {
currentPosition = 8;
digitalWrite(8, HIGH);
delay(random(0, 1000));
}
} else if (currentPosition == 3) {
if (moveDown == true) {
currentPosition = 4;
digitalWrite(4, HIGH);
delay(500);
}
if (moveRight == true) {
digitalWrite(13,HIGH);
Serial.println(“You fail!”);
tone(9,1000,500);
digitalWrite(9,LOW);
delay(700);
digitalWrite(9,HIGH);
tone(9,1000,500);
Serial.end();
}
} else if (currentPosition == 8) {
if (moveRight == true) {
currentPosition = 4;
digitalWrite(4, HIGH);
delay(500);
}
if (moveDown == true) {
digitalWrite(13,HIGH);
Serial.println(“You fail!”);
tone(9,1000,500);
digitalWrite(9,LOW);
delay(700);
digitalWrite(9,HIGH);
tone(9,1000,500);
Serial.end();
}
} else if (currentPosition == 4) {
if (moveRight == true) {
currentPosition = 5;
digitalWrite(5, HIGH);
delay(500);
}
if (moveDown == true) {
currentPosition = 7;
digitalWrite(7, HIGH);
delay(random(0, 1000));
}
} else if (currentPosition == 5) {
if (moveDown == true) {
currentPosition = 6;
digitalWrite(6, HIGH);
if (currentPosition = 6) {
digitalWrite(11, HIGH);
Serial.println(“You win! Let’s check the time!”);

for (int thisNote = 0; thisNote < 8; thisNote++) {
int noteDuration = 1000 / noteDurations[thisNote];
tone(9, melody[thisNote], noteDuration);
int pauseBetweenNotes = noteDuration * 1.30;
delay(pauseBetweenNotes);
noTone(9);
}
}
}
} else if (currentPosition == 7) {
if (moveRight == true) {
currentPosition = 6;
digitalWrite(6, HIGH);
if (currentPosition = 6) {
digitalWrite(11, HIGH);
Serial.println(“You win! Let’s check the time!”);

for (int thisNote = 0; thisNote < 8; thisNote++) {
int noteDuration = 1000 / noteDurations[thisNote];
tone(9, melody[thisNote], noteDuration);
int pauseBetweenNotes = noteDuration * 1.30;
delay(pauseBetweenNotes);
noTone(9);
}
}
}

}
float millisecond = millis();
float second = millisecond/1000;
if (digitalRead(6) == HIGH) {
Serial.println(“You used ” + String(second) + ” seconds”);

Serial.end();
}
}

// delay(1500);

// float second = millis();
//
// /*y = A0
// x = A1
// xvalue < 270 && yvalue < 510 right
// yvalue > 750 && xvalue > 500 down
// */
//
// digitalWrite(2, HIGH);
// delay(150);
//
// if (xvalue < 270 && yvalue < 510 && digitalRead(2) == HIGH) {
// digitalWrite(3,HIGH);
// delay(150);
// }
//
// if (yvalue > 750 && xvalue > 500 && digitalRead(2) == HIGH) {
// digitalWrite(8, HIGH);
// delay(1500);
// }
//
// if (digitalRead(3) == HIGH && yvalue > 750 && xvalue > 500){
// digitalWrite(4, HIGH);
// delay(150);
// }
//
// if (digitalRead(4) == HIGH && yvalue < 510 && xvalue < 270){
// digitalWrite(5, HIGH);
// delay(150);
// }
//
// if(digitalRead(5) == HIGH && yvalue > 750 && xvalue > 500){
// digitalWrite(6,HIGH);
// delay(150);
// }
//
// if(digitalRead(6) == HIGH){
// Serial.print(“You used” + String(second) + “milliseconds”);
// Serial.end();
// }

FABRICATION AND PRODUCTION:

During the users’ test, however, we received some very useful feedback that can help us to improve the user experience of our project. One of the biggest problems seems to be that people have no idea how to hold the joystick. To fix this problem, we first think of making a hole on the upper surface of the box and fix the joystick through the hole, but later we found it is actually impossible due to the irregular shape of the joystick. So we eventually decided that we will attach a little stick to the joystick to instruct the correct direction of using it. Another commonly reported problem is that if the instruction light is red, people are likely to think they lose the game even if it actually means they have succeeded in reaching the end point. So we decided to use the full color led and use blue light to indicate players’ success and red light to the failure. It is also mentioned several times that whether there way for plays to die in this game during users’ test. At first, we think it would be more user-friendly if they can reach the end point anyway, it is just a matter of time.  But later we think it would be more exciting and competitive if there is a possibility of not being able to reach the endpoint. It is also mentioned during the users’ test that there should be clearer instructions about the functions of LEDs in different colors, so we added some specific instructions on the front surface of the box. We also added the sentence: “time is ticking”, so as to remind players that the less time they use to get to the end point, the better. However, one limitation of this game is that players cannot move back once they have made their move. The main reason is that since it is a speed competition game and the chance to die is so small, going back is gonna be a waste of time. Also, if people are allowed to move backward, the coding would be even harder.

Producing:

Before User testing

After User testing 

CONCLUSIONS:

All in all, the goal of our project is to create an entertaining game that is highly interactive and enable people to compete with each other. The instruction light, as well as people using joysticks to control the LEDs,  are both communications with the project. Meanwhile, this project can be entertaining, as there is competition and people can always choose whether to take the risk. I think the significance of this project is to get two people together and compete for speed, reaction and luck with each other while having fun at the same time. Nevertheless, there are certain aspects that this project does not align with my definition of interactivity. For example, the maze is far too simple, which makes it more like a speed competition game than a true maze. It would be much more entertaining if there can be more LEDs, more paths or the color of LEDs can change from time to time. Another main problem is that since we used two separate Arduinos to control the two sets of lights, we also needed two reset buttons. As a result, the two players need to press the reset button respectively if they need to restart, which is very difficult to happen at the exact same moment and decreases the level of interactivity of this project. If we had more time, we would add more LEDs to it more difficult to reach the endpoint, we would also make the color of the LEDs changeable to make the task more challenging and engaging. As the maze is more difficult, we would also enable our players to move backward so that they can have more choices and better enjoy the game.

Generally speaking, a broad lesson I took from the failures and setbacks I came across during this project is to always think carefully, double check everything and start doing things early. Sometimes it is hard for one person to realize the mistake in circuit building or laser-cutting file preparing, but by asking the teammate to check for a second time is of great help. Also, as many problems cannot be foreseen before we actually face them, it is better for us to start early and leave enough time to deal with unexpected challenges and problems. One thing I take away from my accomplishment, on the other hand, is that when doing an interactive project, always leave people as many choices and possibilities. The more choices there are, the more entertaining the project is and the more interactivity can be generated by the desire of exploration and curiosity.

Recitation 6: Processing Basics by Shuyang Cai

The motif:

My final sketch:

I picked Sol LeWitt’s “Wall Drawing 552D” (http://myartguides.com/exhibitions/sol-lewitt-wall-drawing-552d/) as the motif of my drawing. As a green hand at programming, I chose this image as the motif because it does not contain a lot of difficult shapes and is rather practical even for me. Although the shapes are not difficult, the position and size still needed to be estimated and tested, hence the process of trying to reproduce this image can be educational and exploratory. It also requires basic color dealing skills.

In Processing, I first wanted to reproduce the basic shapes in the motif. There are a triangle and two quadrilaterals. They all share one edge with one another, so the coordinate of which shape need to be paid attention to. However, in the motif, the background is a single color, which looks a little bit dull. Therefore, I decided to use different colors as the background in my processing. The basic color is red, but varies from hue and saturation, so as make the background color more dynamic and energetic. The main shapes in my final creation are basically the same as in the motif, but the background is very different, as I use different colors to make the image look more complicated. I believe that drawing in Processing was a good mean of realizing the designs, for it helps me have a better understand the sizes, structures, and positions of the components that consist of the image.

Code:

  1. size(600, 600);
  2. fill(227, 91, 57, 220);
  3. stroke(255, 255, 255);
  4. strokeWeight(0);
  5. rect(140, 0, 360, 360);
  6. stroke(0);
  7. fill(52, 175, 198, 210);
  8. triangle(180, 0,350, 80, 450, 0);
  9. stroke(10);
  10. fill(227, 217, 32, 210);
  11. beginShape();
  12. vertex(180, 0);
  13. vertex(350, 80);
  14. vertex(350, 360);
  15. vertex(140, 250);
  16. endShape(CLOSE);
  17. stroke(10);
  18. fill(209, 208, 198, 235);
  19. beginShape();
  20. vertex(350, 80);
  21. vertex(450, 0);
  22. vertex(500, 250);
  23. vertex(350, 360);
  24. endShape(CLOSE);
  25. stroke(255, 255, 255);
  26. strokeWeight(0);
  27. fill(160, 42, 24, 255);
  28. rect(0, 0, 20, 600);
  29. stroke(250, 255, 255);
  30. strokeWeight(0);
  31. fill(185, 52, 32, 250);
  32. rect(20, 0, 20, 600);
  33. stroke(255, 255, 255);
  34. strokeWeight(0);
  35. fill(214, 60, 37, 255);
  36. rect(40, 0, 20, 600);
  37. stroke(250, 255, 255);
  38. strokeWeight(0);
  39. fill(224, 105, 61, 255);
  40. rect(60, 0, 20, 600);
  41. stroke(250, 255, 255);
  42. strokeWeight(0);
  43. fill(242, 68, 42, 215);
  44. rect(80, 0, 20, 600);
  45. stroke(250, 255, 255);
  46. strokeWeight(0);
  47. fill(240, 83, 10, 230);
  48. rect(100, 0, 20, 600);
  49. stroke(250, 255, 255);
  50. strokeWeight(0);
  51. fill(227, 91, 57, 255);
  52. rect(120, 0, 20, 600);
  53. stroke(250, 255, 255);
  54. strokeWeight(0);
  55. fill(160, 42, 24, 255);
  56. rect(140, 360, 460, 20);
  57. stroke(250, 255, 255);
  58. strokeWeight(0);
  59. fill(185, 52, 32, 250);
  60. rect(140, 380, 460, 20);
  61. stroke(250, 255, 255);
  62. strokeWeight(0);
  63. fill(214, 60, 37, 255);
  64. rect(140, 400, 460, 20);
  65. stroke(250, 255, 255);
  66. strokeWeight(0);
  67. fill(224, 105, 61, 255);
  68. rect(140, 420, 460, 20);
  69. stroke(250, 255, 255);
  70. strokeWeight(0);
  71. fill(240, 83, 10, 230);
  72. rect(140, 440, 460, 30);
  73. stroke(0);
  74. strokeWeight(0);
  75. fill(227, 91, 57, 255);
  76. rect(140, 470, 460, 30);
  77. stroke(250, 255, 255);
  78. strokeWeight(0);
  79. fill(160, 42, 24, 255);
  80. rect(140, 500, 460, 20);
  81. stroke(250, 255, 255);
  82. strokeWeight(0);
  83. fill(185, 52, 32, 250);
  84. rect(140, 520, 460, 20);
  85. stroke(250, 255, 255);
  86. strokeWeight(0);
  87. fill(214, 60, 37, 255);
  88. rect(140, 540, 460, 20);
  89. stroke(250, 255, 255);
  90. strokeWeight(0);
  91. fill(224, 105, 61, 255);
  92. rect(140, 560, 460, 20);
  93. stroke(250, 255, 255);
  94. strokeWeight(0);
  95. fill(242, 68, 42, 215);
  96. rect(140, 580, 460, 20);
  97. stroke(250, 255, 255);
  98. strokeWeight(0);
  99. fill(240, 83, 10, 230);
  100. rect(500, 0, 20, 360);
  101. stroke(250, 255, 255);
  102. strokeWeight(0);
  103. fill(227, 91, 57, 255);
  104. rect(500, 0, 20, 360);
  105. stroke(250, 255, 255);
  106. strokeWeight(0);
  107. fill(160, 42, 24, 255);
  108. rect(520, 0, 20, 360);
  109. stroke(250, 255, 255);
  110. strokeWeight(0);
  111. fill(185, 52, 32, 250);
  112. rect(540, 0, 20, 360);
  113. stroke(250, 255, 255);
  114. strokeWeight(0);
  115. fill(214, 60, 37, 255);
  116. rect(560, 0, 20, 360);
  117. stroke(250, 255, 255);
  118. strokeWeight(0);
  119. fill(224, 105, 61, 255);
  120. rect(580, 0, 20, 360);