Recitation 8: Serial Communication by Qianyue Fan

Exercise 1: Make a Processing Etch A Sketch

Building this circuit requires the knowledge of using code to send values from Arduino to Processing. I started from the examples we learned in class and added the code according to the comments in the example code. I forgot how to connect the potentiometer, so I referred to previous recitations. The use of println() was quite important in Arduino for it would affect the form of the data sent to processing.

The user interacts with the project by turning the potentiometers with different angles to move the dot and create images, and adjust the speed and direction of drawing when seeing the feedback on the screen.

schematic:

picture:

video:

Arduino code:

Processing code:

Exercise 2: Make a musical instrument with Arduino

I attempted to design a relatively complicated interface and it took me some time to decide the parameters of rectangles as keys for the notes. After finishing the code, the buzzer still made no tunes, so I asked for help and realized that I should use the PWM pin as the output. Also, there was a part of the code which turned the signals into 1 and 0 that I forgot to delete. With all these problems solved, the circuit worked well.

The user interacts with the project by clicking different parts of the screen or typing on the keyboard to make tunes.

schematic:

picture:

video:

Arduino code:

Processing code:

  

Preparatory Research and Analysis by Qianyue Fan

During the group project, I defined interaction as an activity where two actors are involved and both of them have effects on each other by a cycle of listening, processing and responding. During the process of interaction, the action of at least one actor should be made intentionally or purposefully, and the outcome should be entertaining or utilitarian.

After working on my midterm project and learning about Processing, I realize the limitation of including “two actors” in the definition. Our midterm project supports competition among players, which involves two people and one device. Therefore, the number of actors should be expanded to multiple instead of two. Besides, when learning basic Processing, we write programs that generate random outcomes without much entertainment or utility. However, we tried to explore the various functions by changing the parameters and testing the results, which can also be seen as a way of interaction. So the explorative purpose should be included as well.

One project that lines up with my definition is the Roskilde Festival playground. It uses gigantic projectors and a huge button as the physical interface in the zone, creating changing mazes of light and color. People can enjoy the combination of music and visual art or interact with the button to see how many possibilities the project has, which is an interesting exploration.

Based on it, I’d like to make a game as the final project that entertains people visually and aurally with some intellectual challenge.

On the contrary, the “Cindermedusae”, a generative book, does not align with my definition. It is a compilation of animation of virtual jellyfish generated from random parameters. Although the creatures are fascinating and vivid, they do not take external inputs and the audience are in the passive position. It is more like the artist’s exploration of artistic expressions instead of an interactive project.

Given all these new experiences and projects, I’d like to define interaction as the activity between at least two actors who affect others in a cycle of receiving input, processing and giving output, and it arouses people’s emotional or mental reactions. When interacting with machines, people should be in the active position and have at least partial control over the machine to figure out what may happen and what they are supposed to do even when they have no knowledge about it in the beginning.

Recitation 7: Processing Animation by Qianyue Fan

interactive animation:

I made a new project for this recitation. It looks like the incomplete version of the game Brick Breaker, for there are no bricks but only a paddle and a bouncing ball.  In the beginning, the ball stays still on the screen and the paddle moves with the mouse. To start the game, press the key ‘r’. The player can move the paddle anywhere within the screen with the mouse to hit the bouncing ball, and the ball changes direction when hitting the paddle or the edges of the canvas. The ball can be sped up by pressing ‘w’ once and slowed down by pressing ‘s’ once.

Video:

code:

Additional Homework:

Step 1:

Step 2:

Step 3:

Step 4 (With canvas edges as borders. The circle gets stuck when moving) :

code:

 

Reflection:

When writing codes, it is useful to read examples and other open-source codes, especially on the Processing Forum, to learn about the structure and functions to realize the required features. It is also important to read the instruction of functions in Reference carefully, which solves most of the problems I encountered. There are times when different functions overlap and hinder each other, and it needs patience and clear logic in mind to sort them out one by one, and make greater adjustments when necessary. 

The most interesting functions I used include ‘key’ and ‘keyPressed’, the difference between which is vital. When using ‘key’ in the format of if (key == sth){}, the input will always be kept in memory until replaced when another key is pressed. However, when if (keyPressed){} is added into the code, the key needs to be kept pressed to make the function work. This difference needs to be paid attention to especially when making game-related designs.

For the use of arrow keys, I learned to apply key == CODED and keyCode == UP (or other directions).

Another interesting structure, though not a function, is the “sentinel value” (I borrowed the term from Python). To be specific, in my own project in this recitation, after pressing a key to start the game, I wanted the ball to change speed when pressing other keys. However, as I mentioned in the previous paragraph, the program only stores one value. So I added a new variable that changes with the pressing of a certain key and it then would remain unchanged. Therefore the problem of storage is solved. This can be especially useful when multiple keys are used in the program.

Midterm project: Light Maze – Qianyue Fan – Eric

CONTEXT AND SIGNIFICANCE:

 In the previous research, we defined interaction as an activity that involves two actors and they affect each other by a cycle of listening, processing and responding. The outcome should be entertaining or utilitarian. From the perspective of being entertaining, I drew inspiration from the Speed Game in recitation. The high level of involvement of players and real-time feedback make game one of the most interactively entertaining activities. Based on that project, I came up with the idea of turning abstract count of button clicks into visible flash of LED lights, and small buttons into handy joysticks which give users a feeling of gamepads. The final version of our project is a game where players move their position with joysticks from the start to the end point, with various obstacles in their way. The LED lights indicate the current position, and the time they use will be recorded and displayed. The outcome is shown by both a signal light and a buzzer. The project is intended for everyone to have fun and challenge themselves either on their own or compete with friends, and it may also provoke nostalgia for arcade games in the past.

CONCEPTION AND DESIGN:

In order to create a relatively small device as the carrier of the game, we chose wooden box to put all the circuits in it. Transparent plastic might have been more modern, but the box would then look messy and puzzling. We designed the upper surface of the box as the main panel, for LED lights could steadily stay in the position and the lights can be seen more clearly. To make it easier for players to use joysticks as they like, we chose not to fix them on the box. Later we added reset buttons on breadboards to restart the game without uploading the code again, but the design proved to be oversized and cumbersome. However, we did not change them into built-in style due to the time limit. As for the coding, we include the position of players with the help of the professor and added different tunes of buzzers for success and failure. We also used millis() function to make a ranking list on the serial monitor.

FABRICATION AND PRODUCTION:

In the beginning, we made a box with laser cut and marked each piece of board in case we forgot their correct positions. But the box turned out too small and could not be put together due to a mistake in the original design.

marked boards

In the user test, we had to make do with the problem and just put the upper piece loosely on the top. People were interested in the game and competition, but the game supported only single player so they could not compete simultaneously. game supported only single player so they could not compete simultaneously.

first version

Also, the joysticks could be put in the wrong direction and there were no relevant signs for them. In fact, there was no instruction for the game and we needed to explain every time. Besides, the time counted in millisecond was complicated, the reset button was not handy, and the flash of signal light and buzzer made users believe that they failed while they actually reached the end point. In the there was no lose or win but only delay in the user testing version, and it was only a matter of time to reach the destination. Having received all these feedbacks, we first made a new box double size as the original one to support two players. The box was made more user-friendly with concise instructions on the front, and millisecond was changed into second. We stuck pieces of wooden arrows to the joysticks to show the right direction and used reset pins on Arduino boards to connect external buttons to them. We also improved the codes so that players would have the risk to fail when going the wrong way. Accordingly, we used separate light colors and sounds for failure and success. In that way, our project became more challenging and visually satisfying.

new version

CONCLUSIONS:

The goal of our project is to create an interactive and competitive game for users to enjoy themselves. As a game it fulfilled most of our requirements, but there are still defects that negatively affect the interaction. Users are quick to be proficient in the game. While it gives them the chance to improve skills, the game soon becomes unchallenging and is reduced to both players going the same path as fast as possible. If we had more time, we would provide more paths to increase difficulty and cancel the limit of moving right and down only, making it more like a maze game instead of one-way race.

In the whole process, we did well in time management and cooperation. Every step was precisely scheduled and we were quick to react to incidents in time. What we learned was something about the art of design. Despite the countless wires and LEDs we used, the game itself was not very entertaining compared to some other carefully designed projects. Interaction is the combination of art and logical designs, with proper appearance and creative thoughts. Complexity does not necessarily bring surprise and appreciation, creativity does. Interactive art is not aimed at imitating existing entertainment forms but making new forms, and only that makes the interaction meaningful.

Code:

(main 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();
}
}

(“pitch”)

#define NOTE_B0 31
#define NOTE_C1 33
#define NOTE_CS1 35
#define NOTE_D1 37
#define NOTE_DS1 39
#define NOTE_E1 41
#define NOTE_F1 44
#define NOTE_FS1 46
#define NOTE_G1 49
#define NOTE_GS1 52
#define NOTE_A1 55
#define NOTE_AS1 58
#define NOTE_B1 62
#define NOTE_C2 65
#define NOTE_CS2 69
#define NOTE_D2 73
#define NOTE_DS2 78
#define NOTE_E2 82
#define NOTE_F2 87
#define NOTE_FS2 93
#define NOTE_G2 98
#define NOTE_GS2 104
#define NOTE_A2 110
#define NOTE_AS2 117
#define NOTE_B2 123
#define NOTE_C3 131
#define NOTE_CS3 139
#define NOTE_D3 147
#define NOTE_DS3 156
#define NOTE_E3 165
#define NOTE_F3 175
#define NOTE_FS3 185
#define NOTE_G3 196
#define NOTE_GS3 208
#define NOTE_A3 220
#define NOTE_AS3 233
#define NOTE_B3 247
#define NOTE_C4 262
#define NOTE_CS4 277
#define NOTE_D4 294
#define NOTE_DS4 311
#define NOTE_E4 330
#define NOTE_F4 349
#define NOTE_FS4 370
#define NOTE_G4 392
#define NOTE_GS4 415
#define NOTE_A4 440
#define NOTE_AS4 466
#define NOTE_B4 494
#define NOTE_C5 523
#define NOTE_CS5 554
#define NOTE_D5 587
#define NOTE_DS5 622
#define NOTE_E5 659
#define NOTE_F5 698
#define NOTE_FS5 740
#define NOTE_G5 784
#define NOTE_GS5 831
#define NOTE_A5 880
#define NOTE_AS5 932
#define NOTE_B5 988
#define NOTE_C6 1047
#define NOTE_CS6 1109
#define NOTE_D6 1175
#define NOTE_DS6 1245
#define NOTE_E6 1319
#define NOTE_F6 1397
#define NOTE_FS6 1480
#define NOTE_G6 1568
#define NOTE_GS6 1661
#define NOTE_A6 1760
#define NOTE_AS6 1865
#define NOTE_B6 1976
#define NOTE_C7 2093
#define NOTE_CS7 2217
#define NOTE_D7 2349
#define NOTE_DS7 2489
#define NOTE_E7 2637
#define NOTE_F7 2794
#define NOTE_FS7 2960
#define NOTE_G7 3136
#define NOTE_GS7 3322
#define NOTE_A7 3520
#define NOTE_AS7 3729
#define NOTE_B7 3951
#define NOTE_C8 4186
#define NOTE_CS8 4435
#define NOTE_D8 4699
#define NOTE_DS8 4978

Recitation 6: Processing Basics by Qianyue Fan

Concealing by Josef Albers

I chose  Concealing by Josef Albers (https://www.guggenheim.org/artwork/147) as a motif. The use of abstract shapes and the artful choice of color make this piece of work a good inspiration. It took me some time to get used to the special coordinate system in Processing, and it was a little demanding to estimate the numerical values based on the relative positions of the shape. 

It was not difficult to copy the composition and color, but the overlying layers of polygons reminded me of the room in Stephen King’s novel “1408”. I use alternate color systems of different saturation for each part to give it a sense of constriction. To add something different from the original work, I used a BĂ©zier curve. Processing may not be the best choice for designing, for it requires a lot of calculation work by heart, lacks effects of materials and paintbrushes, and does not reflect our thought in real-time. It works better for dynamic and interactive 2-D artworks. 

Code:

size(600,600);

fill(201,159,53);//brown 129,79,29
noStroke();
rect(0,0,600,600);

fill(90,90,69);//purple 110,29,129
noStroke();
rect(100,60,400,540);

fill(2527,220,11);//red 211,23,80
stroke(255);
quad(180,60,450,120,450,480,180,480);

fill(12,12,12);//white 255
noStroke();
quad(240,280,350,300,350,460,240,470);

fill(191,166,23);// green 1 34,155,125
stroke(255);
quad(0,510,180,480,180,600,0,600);

fill(191,166,23);// green 2
stroke(100);
quad(180,600,180,510,600,465,600,600);

line(100,160,500,115); // line above
stroke(255);

noFill();
stroke(240,129,10);
for (int i = 0; i < 200; i += 10) {
bezier(i, 40+i, 410, 20, 440, 300, 300-(i/16.0), 300+(i/8.0));
}

Final sketch: