Self-Portrait :)

For this project, I decided to practice my (beginner) Illustrator skills by tracing a selfie of mine in Illustrator and then using those coordinates in Processing. Of course, because coordinates are straight lines, the endeavor did not turn out exactly beautifully, but I still like it (also – I did draw a nose, even though it is hard to see):

 

 

 

 

 

Here is what tracing in Illustrator looked like (at different stages):

To get the coordinates for the tracings, I exported the Illustrator file as an SVG (Scalable Vector Graphics), which was a file that contained code including the coordinates. I copied and pasted the coordinates into my Processing file.

Besides simply drawing my self-portrait, I added a few extra effects (changing hair colors, blinking, and a tongue that sticks out). You can see these in the video below, or watch it on youtube:

There were four parts of this project:

(1) Drawing my self-portrait using the coordinates from Illustrator.

To draw myself, I copied and pasted the coordinates from Illustrator, formatted them into a string, split them, and then used a for loop and the begin/end shape function to iterate through all the coordinates of each shape (eyes, nose, hair, etc.).

(2) Making the hair colors change.

To make the hair colors change, I simply have a variable that keeps track of the frames, and every 30 frames I fill the “hair” shape randomly with one of five different colors. The only special thing is that to avoid having the same hair color twice in a row, I check whether the newly generated hair color is the same as the old one, and if it is I keep generating new random colors until I get one that is different than the old one.

(3) Making my eyes blink periodically.

To make my eyes blink, I count each frame, and after 190 frames I fill the eye with the lid color (to make the eye look closed), and the eye stays like this (stays “closed”) for ten frames; then, I reset the counter.

(4) Making my tongue stick out on hover.

To make my tongue stick out on hover, I used illustrator to trace a rectangle around my mouth, and then (just like we did in class) I test whether MouseX and MouseY are in the specified area (that rectangle), and if they are I draw the tongue.

The code involved is way too long to post here, so if you are interested please click here to view the code.

Casey Reas: Art, Order, and Chaos

There were so many things I enjoyed about Casey Reas’ lecture – as well as quite a few things I did not. I loved his inclusion of so many works of art; I am now aware that the field of algorithm-based art is huge and worth exploring further on my own. I also love the idea of juxtaposing chaos and order, and using the beauty in each to make something even more beautiful. I really liked that he showed the viewers, using simple Processing code, how to create these “chaotic ordered art pieces / patterns” – doing so added a very practical touch to the talk, and made me feel like experimenting myself.

However, like Zbynek, I did not particularly think that his critique of completely ordered art was fair. While art that does have an element of chaos is, technically, more similar to imperfect humanity, I do not see the logic of why that means that such art is automatically superior to ordered art. (He did not say this in these words, but it was clear he felt very strongly that there is something unworthy in ordered art.) People paint pictures of heavens and gods and mythical creatures, none of which very closely resemble humanity; yet just like people are fascinated with the idea of a perfect place – a heaven, a nirvana – people are also intrigued and motivated by the notion of perfect art – a perfect circle, a perfect grid. To me, there is clearly value and beauty in both types of art, and I could not help but think that Reas need not be so derogatory about ordered art.

Lastly, I am a bit skeptical about the artwork that Reas and a collaborator made for the building in Miami (shown above). He described the artistic process this way: they took photos over a year of the surrounding art district and construction of the building. Then, they narrowed down hundreds of photos to just the ones they liked (in simple terms) best. Next, they used algorithms to play with the photos, creating interesting “ordered chaotic patterns.” Lastly, they did some tedious work to put together the final product (365 art pieces). The strange parts about this for me was the last part: Reas implied that at the end, even after letting the algorithm and random properties do their work, he and his collaborator tweaked the results to make them more ideal. While I know art has no rules, it seems a odd that an artist who believes so much in the beauty of chaos would tweak the results, making them no longer random/chaotic.

(I am including another of Reas’ pieces below to show that despite the fact that my post was mainly critical I really do like his artwork; it is just that it is generally more interesting to discuss things you do not like than to go on and on praising something.)

 

 

Her Code: Margaret Hamilton, a.k.a Software Goddess

There are few things as inspirational as someone who, despite facing obstacles of all kinds, not only overcomes those obstacles, but completely annihilates them and accomplishes something mind-blowing and iconic. In “Her Code Got Humans to the Moon – And Invented Software Itself,” we learned about such a person: Margaret Hamilton. Despite beginning her MIT programming job in the 1960s, an era in which women were expected to be housewives, not participants in the tech field, she wrote code that was absolutely crucial to the successful flight of Apollo. Not only did she help humanity get to the moon, but she also helped found the field of software engineering, and started several software companies including Hamilton Technologies.

What shocked me the most about the article was the fact that Hamilton specifically wanted to write code to prevent a major issue (having an astronaut press P01 mid-flight), but her higher ups disagreed. It seems incredibly strange that her superiors and NASA would not want to do everything they could to prevent human error. Considering that an astronaut aboard Apollo did make this error, there is a lesson to be learned: software engineers should not just aim to prevent bugs and errors within software itself, but should also try to predict human/user errors, and code in such a way that ensures that the technology will be able to overcome them and function well regardless.

Overall, I loved this article and now feel motivated to learn more about the beginnings of the software field, and especially about the contributions of women; considering that women are still disadvantaged in the tech field in 2017, the fact that women in the 1960s were able to contribute so much to the field is utterly remarkable.

Ballerina :)

My first idea when brainstorming about using a motor to create a human-like motion was of belly dancing: I really wanted to make a bellydancing girl who would move in a way that made it appear that her hips were detached from her upper body (which is how I have always thought about it in real life). The funny part about this whole project is this: I started making a belly dancing girl, and half-way through began to think that the 360 degree twirling of the motor seemed to fit a ballerina more, and thus started over and began to create a ballerina instead, and then, in the end, the dancing effect actually looks more like belly dancing. So, I now have a ballerina who is a wanna-be belly dancer.

Here is a photo of her:

The project works like this: there is a button that controls the speed of the ballerina’s twirls, and also changes the song (technically just three repeating notes). There are three options that correspond with button presses: the first is three “lower” notes repeating, which corresponds with a slower twirling speed, the second is three “medium pitch” notes repeating, which corresponds with a medium twirling speed, and the third is three “high” notes repeating, which corresponds with a high twirling speed. (In reality, of course, all of the notes are fairly high-pitched and all the twirling speeds are quite fast; regardless, the changes in pitch and speed are noticeable.)

Below is a video of the project:

Additionally, here is a photo of the red board and bus board:

I faced a variety of issues with this project, the biggest of which is the following: when I first started the project, I joined two motors by their heads and secured them in this position. I ensured that the motors were spinning in opposite directions, so that when they were secured together (upside down) they would spin together. I then added a ziptie around the attached heads. The purpose of this was to have a doll that would have legs that would not spin, an upper body/head that would not spin, but hips that would spin. And in accomplishing this, I did succeed; however, three consecutive motors stopped working while trying to keep this working, and eventually I had to stop trying and only use one motor. Other issues include my struggle to make the motor not go so extremely fast, and how to design the girl so that it looked at least a little bit realistic.

Below is the code I used for the project. 🙂

//Ballerina file

int motor1Pin = 9;
int buttonPin = 3;
int speakerPin = 5;

int currentNote = 0;
int song1[] = {NOTE_C5, NOTE_D5, NOTE_E5};
int song2[] = {NOTE_D6, NOTE_E6, NOTE_F6};
int song3[] = {NOTE_E7, NOTE_F7, NOTE_G7};

int currentSpeed = 1;

void setup() 
{ 
 pinMode(motor1Pin, OUTPUT);
 pinMode(buttonPin, INPUT);
 pinMode(speakerPin, OUTPUT);
 
 Serial.begin(9600);
} 
 
void loop() 
{ 
 if (digitalRead(buttonPin) == LOW) {
 currentSpeed += 1;
 if (currentSpeed > 3)
    currentSpeed = 1; 
 currentNote = 0;
 }
 
 analogWrite(motor1Pin, currentSpeed * 25 + 25);

 if (currentSpeed == 1)
    tone(speakerPin, song1[currentNote], 500);
 else if (currentSpeed == 2)
    tone(speakerPin, song2[currentNote], 500);
 else if (currentSpeed == 3)
    tone(speakerPin, song3[currentNote], 500);

 currentNote++; 
 if (currentNote >= 3)
    currentNote = 0;

 delay(500);
 
 analogWrite(motor1Pin, 0);

 delay(500);

}

 

Finding Dory :)

For my “Stupid Pet Trick” I wanted to do something that was simply… adorable. I hoped to create something sweet, silly, and uncomplicated. For that reason, I decided to go ahead and make a project that involved one of the cutest Pixar characters of all time: baby Dory. I mean, look at her:

I decided to make my project a little “game” (though really more like a simple task) in which the user helps bring Dory and her parents together (for those who remember, that was the main idea of the movie “Finding Dory”). The user has two photo cell sensors (one for each hand) and is able to use those to help Dory and her parents; the catch is that if the user only uses one hand at a time (i.e. only presses the sensor that is connected to the servo that has Dory on it, or only presses the sensor that is connected to the servo that has her parents on it), then the correlating party (Dory or her parents) will actually move farther away from each other. Only if the user uses both hands with the sensors at the same time will Dory and her parents move closer together, eventually leading them to be together and triggering the huge Neopixel heart behind them. (The idea for the concept comes from the movie: both Dory and her parents were constantly looking for each other – without both parties looking, they never would have found each other again.)

The project is shown in the video below (but I highly suggest watching it here, on Youtube, instead – since the video on the blog usually lags):

While creating this project I encountered a variety of obstacles, the most severe of which had to do with the servos:

  • First of all, using three servos on one Arduino (without an external power source) can cause issues, but fortunately I was able to tweak the code so that the servos were able to function well regardless.
  • Secondly, to make the servos all do exactly what I wanted required quite a lot of math/thinking deeply about the angles of each servo at all times. For example, I wanted the servos (with Dory and her parents) to move gradually rather than to make big jerks; moreover, because of positioning, the two servos have to move in opposite directions always. These considerations, combined with many others, led to a lot (and I mean a lot) of debugging and the need to continuously make small edits to the code.
  • Thirdly, keeping things attached well to the servos was difficult (as per usual). I used popsicle sticks to attach the characters to the servos, and used a lot of sticky tack to connect them. The major problem that I still have is that these popsicle sticks are still a bit too heavy for the servo, and sometimes lead to the head of the servo (the part that twirls) to pop off.
  • Additionally, the photo cell sensors are problematic in the same way that they always are: depending on the light in the room, they read very different numbers. To avoid this issue, I tested the project at the very spot where I sit in the class.
  • Lastly, because there are two photo cell sensors involved, it is likely that the user might accidentally cast a shadow on a sensor that he/she is not intending to affect.

Below I include copies of the code I used in this project. I used two different files (“FindingDory” and “OceanLights”) because I have two different red boards: at the top of my project is a string of Neopixels that are simply there for aesthetics. I did not want them to take power away from my servos/sensors, so I attached them to a different red board altogether that ensures that they are always on.

//FindingDory file

#include <Servo.h>
#include <Adafruit_NeoPixel.h>
#ifdef __AVR__
   #include <avr/power.h>
#endif

Servo doryServo;
Servo parentsServo;
Servo togetherServo;

Adafruit_NeoPixel heartLights;

int doryDistanceSensor = A0;
int parentsDistanceSensor = A1;

//names of the sensor data
float dorySensorDistance, parentsSensorDistance;
//names of the servo angles
int doryCurrentAngle, parentsCurrentAngle, toMoveAngle, togetherCurrentAngle;
//min and max values for reading of photo cell sensors
float minThresh = 150.0f;
float maxThresh = 750.0f;

void setup() {
   doryServo.attach(9);
   parentsServo.attach(10);
   togetherServo.attach(11);

   heartLights = Adafruit_NeoPixel(27, 5, NEO_GRB +    NEO_KHZ800);

   pinMode(doryDistanceSensor, INPUT);
   pinMode(parentsDistanceSensor, INPUT);
 
   //initial angles for each servo
   doryCurrentAngle = 60;
   parentsCurrentAngle = 120;
   togetherCurrentAngle = 0;
 
   //write the initial angles to the servos
   doryServo.write(doryCurrentAngle);
   parentsServo.write(parentsCurrentAngle);
   togetherServo.write(togetherCurrentAngle);

   //"begin" makes sure all LEDs are off (at 0)
   heartLights.begin();
   //"show" is like writing the value (0) to the LEDs
   heartLights.show();

   Serial.begin(9600);
}

void loop() {
   //read sensors
   dorySensorDistance = analogRead(doryDistanceSensor);
   parentsSensorDistance =  analogRead(parentsDistanceSensor);

   //if Dory and parents are both detected
   if (dorySensorDistance <= maxThresh &&    parentsSensorDistance <= maxThresh) {
      toMoveAngle = dtoa2(dorySensorDistance);
      if (toMoveAngle > doryCurrentAngle) {
         doryServo.write(toMoveAngle);
         doryCurrentAngle = toMoveAngle;
      }
 
      toMoveAngle = dtoa1(parentsSensorDistance);
      if (toMoveAngle < parentsCurrentAngle) {
         parentsServo.write(toMoveAngle);
         parentsCurrentAngle = toMoveAngle;
      }
   }

   //if only Dory is detected
   else if (dorySensorDistance <= maxThresh) {
      toMoveAngle = dtoa1(dorySensorDistance);
      if (toMoveAngle < doryCurrentAngle) {
         doryServo.write(toMoveAngle);
         doryCurrentAngle = toMoveAngle;
      }
    }

    //if only parents are detected
    else if (parentsSensorDistance <= maxThresh) {
       toMoveAngle = dtoa2(parentsSensorDistance);
       if (toMoveAngle > parentsCurrentAngle) {
          parentsServo.write(toMoveAngle);
          parentsCurrentAngle = toMoveAngle;
       }
   }

   //what to do when dory and parents meet in the middle
   if ((doryCurrentAngle > 150) && (parentsCurrentAngle < 30)) {
      togetherCurrentAngle = 150; //family photo come up
      doryCurrentAngle = 180; //dory go down
      parentsCurrentAngle = 0; //parents go down
      doryServo.write(doryCurrentAngle);
      parentsServo.write(parentsCurrentAngle);
      togetherServo.write(togetherCurrentAngle);
 
      //setting the color of the lights
      for(int i=0; i<heartLights.numPixels(); i++) {
   heartLights.setPixelColor(i, heartLights.Color(150,0,0));
      }

      //turn lights on
      heartLights.show();
      //lights stay on for 5 seconds
      delay(5000);
      setup();
   }
}

//formula for distance to angle 1
int dtoa1(float photoDist) {
   return float((photoDist - minThresh) / (maxThresh-minThresh)) * 180;
}

//formula distange to angle 2
int dtoa2(float photoDist) {
   return float((maxThresh - photoDist) / (maxThresh-minThresh)) * 180;
}
//OceanLights file

#include <Adafruit_NeoPixel.h>
#ifdef __AVR__
   #include <avr/power.h>
#endif

Adafruit_NeoPixel oceanLights;

void setup() {
   oceanLights = Adafruit_NeoPixel(26, 6, NEO_GRB + NEO_KHZ800);
   oceanLights.begin();
   oceanLights.show(); // Initialize all pixels to 'off'
}

void loop() {
   rainbowCycle(20);
}

void rainbow(uint8_t wait) {
   uint16_t i, j;

   for(j=0; j<256; j++) {
      for(i=0; i<oceanLights.numPixels(); i++) {
         oceanLights.setPixelColor(i, WheelGB((i+j) & 255));
      }
      oceanLights.show();
      delay(wait);
   }
}

// Slightly different, this makes the rainbow equally distributed throughout
void rainbowCycle(uint8_t wait) {
   uint16_t i, j;

  for(j=0; j<256*5; j++) { // 5 cycles of all colors on wheel
     for(i=0; i< oceanLights.numPixels(); i++) {
        oceanLights.setPixelColor(i, WheelGB(((i * 256 / oceanLights.numPixels()) + j) & 255));
     }

     oceanLights.show();
     delay(wait);
   }
}

uint32_t WheelGB(byte WheelPos) {
   WheelPos = 255 - WheelPos;
   if(WheelPos < 85) {
      return oceanLights.Color(0, WheelPos * 3, WheelPos * 3);
 }
   if(WheelPos < 170) {
      WheelPos -= 85;
      return oceanLights.Color(0, WheelPos * 3, 255 - WheelPos * 3);
 }
   if(WheelPos < 255) {
      WheelPos -= 170;
      return oceanLights.Color(0, 255 - WheelPos * 3, 0);
   }
}

Why Design Does Not Need a Definition (Roberto Casati: “The Norm of Design”)

Beginning with his lecture titled “The Norm of Design,” Roberto Casati set out to accomplish the following: he wanted to 1) demonstrate that a definition of design is unnecessary, 2) set up a useful theoretical framework for design that comes from cognitive science, and 3) describe something he terms “blockers” (which are basically signifiers that do the opposite of signifying affordances – they signal to the user not to do something). In this first lecture, he truly only covered the first of these three points (he covered the two others in his second lecture on Thursday, which I was fortunate enough to attend and can say that it was even more interesting than the first).

The image below shows a brief picture of the main ideas of his talk:

As noted in the image, Casati discussed a) the notion that defining design is a fruitless activity, and that it is better to think of design as something that solves problems (like engineering) but still manages to make a statement, b) the idea that design should not continue to be thought of as something that lies in between art and engineering, and c) that just like other objects (such as chairs) there is no definition that can include all things that should be considered design, yet will also exclude all things not considered to be design.

Of all the topics he discussed, what I found the most interesting was the idea of thinking about design in an analogous way to Platonic forms: people have an ideal concept of design in their minds, in that people have an intuitive sense as to what counts more as design and what counts less as design. Importantly, this way of judging and “defining” design is enough – it does not require a true, written definition. We will never find a perfect example of design, for such a thing (like a Platonic form) does not exist; rather, we can judge objects as to whether they are closer or farther from that ideal. In such a way, these forms/ideals can change over time, and are not constrained by worded definitions.

In sum, I enjoyed the concept of the lecture because to me, intuitively, design is something that cannot, and in many ways, should not, have a definition. The progressive, ever-changing, dynamic, multi-faceted world of design necessitates an open mind, and giving up on the search for a specific definition of design only helps, rather than hurts, the efforts of that world.

Interactive Record Player — Beethoven’s “Ode to Joy”

Ever since learning how to use the servo last class, I couldn’t wait to use it. When brainstorming for this project, the first thing that came to my mind was a record player: it was fun, vintage, dynamic, and I was certain I could come up with an interesting way to make it interactive. Here is an image of the final product below:

My initial plan was the following: I wanted to have a “record” (disk) that would constantly rotate a complete 360 degrees, and around the edges of the record would be little slots which would hold metallic (conductive) pins. When the record player’s needle would touch a metallic pin, a note from Beethoven’s song “Ode to Joy” would play. The interactive aspect of the device would be the fact that (1) the pins are removable, so users can take out the pins and move them to whichever slots they like, which changes the spacing/rhythm of the song, and (2) there would be a knob that controlled the speed of the disk, so the user could make the song faster or slower.

However, there were two main issues that I encountered that made me change my plan slightly. (1) The first was the fact that (obviously) the servo can only move 180 degrees, and thus cannot continuously rotate. Although we learned this in class, I unfortunately forgot about this fact until I had already started the project. I thus adapted my plan, and just made the disk rotate back and forth 180 degrees. (2) The second issue was the knob. The knob caused soooo many issues for me; it seemed that the knob kept throwing random values, and then would make the whole player stop moving, jerk around, or somehow interfere with the detection of the metallic pins. After implementing the record player with the knob, I decided to simply remove the knob altogether. Sadly, this makes the device less interactive.

Two last things: the pins and the needle are both extremely finicky. First, although the pins are metallic, they do not connect to the aluminium foil reliably, and thus I had to cover all of them with aluminium foil, and bend them very particularly so they would connect well with the foil on the disk. Although they caused much strife, they do work reasonably well now. Second, the needle tends to get caught under the pins while the disk is rotating, and as such often requires a helping hand to guide it and ensure that it touches the pins on the disk. Ideally, this could be fixed with the right materials and time.

Here is a picture of pins I used, before and after I covered them with aluminium foil:

Below is a close-up picture of the disk. You can see the extra slots between the pins that allow the user to move the pins around and place them in whatever slots they like.

Finally, below is a picture of the record player at work. Although it is not entirely needed, I used my hand to guide the needle, so that I can demonstrate the ideal way the player should function. In the video, I have the pins placed in every other slot; of course, the user can arrange the pins however he or she would like.

While this is definitely not a traditional musical instrument, the plan was to keep it an “instrument” in the sense that the user could control the music to a large extent. Although the song is chosen for the user, the user can control the pace/rhythm of the notes (and, in the original plan, the speed of the disk rotation); in an ideal model, there would be a way to have multiple songs, that the user could switch to by pressing a button.

Below I include the code for those interested:

#include <Servo.h>;
#include "pitches.h";

int discPin = 9;
int speakerPin = 5;
int needlePin = 2;
Servo disc;

bool isPlaying, goingUp;
int playingSpeed, spinDelay, discPosition = 0;

int song[] = {MI, MI, FA, SOL, SOL, FA, MI, RE, DO, DO, RE, MI, MI, RE, RE, MI, MI, FA, SOL, SOL, FA, MI, RE, DO, DO, RE, MI, RE, DO, DO, RE, RE, MI, DO, RE, MI, FA, MI, DO, RE, MI, FA, MI, RE, DO, RE, SOL0, MI, MI, FA, SOL, SOL, FA, MI, RE, DO, DO, RE, MI, RE, DO, DO};
int duration[] = {400, 400, 400, 400, 400, 400, 400, 400, 400, 400, 400, 400, 600, 200, 800, 400, 400, 400, 400, 400, 400, 400, 400, 400, 400, 400, 400, 600, 200, 800, 400, 400, 400, 400, 400, 200, 200, 400, 400, 400, 200, 200, 400, 400, 400, 400, 400, 400, 400, 400, 400, 400, 400, 400, 400, 400, 400, 600, 200, 800};
int currentNote = 0;

void setup() {
    disc.attach(discPin);
    pinMode(speakerPin, OUTPUT);
    pinMode(needlePin, INPUT);

    Serial.begin(9600);
}

void loop() {
    disc.write(discPosition);
 
    isPlaying = digitalRead(needlePin) == HIGH; 
    if (isPlaying) {
        Serial.println(currentNote);
        tone(speakerPin, song[currentNote], duration[currentNote]);
        delay(duration[currentNote] + 200);
        currentNote++;
        if (currentNote >= sizeof(song)/sizeof(int))
           currentNote = 0;
 }
    else {
        Serial.println("...");
        delay(600);
 }
 
    nextDiscPosition();
}

void nextDiscPosition() {
    if (discPosition <= 0)
        goingUp = true;

    if (discPosition >= 180)
        goingUp = false;

    if (goingUp)
        discPosition += 10;
    else discPosition -= 10;
}

“[Design is] Not Just What It Looks Like and Feels Like. Design Is How It Works.”

The section from “Design Meets Disability” by Graham Pullin covers a LOT of different concepts/ideas regarding (obviously, considering the title) the importance of incorporating design principles into products made for those with disabilities. I’m going to narrow in on three topics that I found particularly interesting.

(1) First, I found the discussion about the way that eyeglasses are now considered a fashion statement/accessory/normal piece of apparel (rather than a product to correct a physical disability) absolutely fascinating. Although this transformation of the social perception of glasses took place surprisingly recently, I, myself, and everybody I know would not even think of an individual’s need to wear glasses as a disability. This fact is what really stuck with me from the reading: changing the cultural/social perception of an item for an impairment does not simply affect the item itself or the overall appearance of the wearer, it actually changes our definition and understanding of the notion of disability itself. In reality, we should all think that, for example, my terrible vision is a clear physical impairment, just as much as if my hearing was bad and I needed hearing aids – yet, we do not. After reading about this and thinking about it, I cannot think of a better reason or motivation to pursue innovative designs for other products for the “disabled” – for who knows, perhaps years from now we will think of someone wearing a prosthesis just as “disabled” as we now think of someone wearing glasses.

(2) Second, I thought the point about how there must be a “middle ground” between invisibility and “flashiness” when designing products for those with disabilities (and in general, of course) was particularly insightful. Pullin explains that a lot of designers who realize that invisibility is not necessarily the way to go when designing such products tend to go too far to the other extreme: they use really bright colors and flashy designs to “make a statement.” However, as he points out, people do not necessarily want this extreme, even if they also dislike designs that prioritize invisibility. Rather, in a similar way to well-designed eyeglasses, there should be a middle ground; products should use sleek, stylish, functional materials and designs that are neither invisible nor so attention-drawing.

(3) Lastly, I really liked the idea discussed more to the end of the text regarding the way in which adding a useful feature to a product/piece of technology is not always the way to go, even if the user would have appreciated or used that feature. The reason for this is that at some point (maybe very early on even) adding additional features can actually worsen the overall user experience. I thought about this idea this way: it is like taking one step forward and two steps back, with the step forward being the added feature, and two steps back being the worsened overall user experience.

 

On Shutting Up and Why You Shouldn’t Say Something Has “Already Been Done”

In “Making Interactive Art: Set the Stage, Then Shut Up and Listen,” we are reminded that interactive art is not like other types of art in that it is not a “statement” but rather a “conversation.” When creators of interactive art tell users exactly how to use their projects, or explain exactly what they were trying to express with the art and what they want the users to learn/get out of it, those creators are effectively shutting down the conversation that interactive art is supposed to start. In this context, a conversation refers to the way that people are supposed to a) have free reign to “explore” the art and figure out how to use it themselves, b) be open to a range of interpretations of the art, and c) be able to take away something unique and special from the art, which could be the same or different from what the creator intended.

This article should serve as a good reminder to all of us in class, especially when it comes to creating our larger projects: we do not need to over-explain or over-interpret our own art, because users should be able to have their own unique experience with it. And we should remember that while interactive art is, definitely, art, that it does not mean, nor should it, that we, interactive artists, must adopt all the customs of other areas of art.

The message of “Physical Computing’s Greatest Hits (And Misses)” is one that might be the most important for a class of new interactive artists to learn: nothing has every truly “already been done.” The author explains that while there are many “types” of interactive art that people seem to intuitively return to again and again, that it doesn’t mean that such projects are not worthy of attention, for there can be countless creative variations and improvements of each type. More importantly, the attitude of “I can’t do that, it’s already been done,” is simply a terrible one for an artist to have; it essentially completely bars a person from certain types of art, and from coming up with innovative ways to incorporate that type. The author then spends the article denoting all the most common types/subtypes of interactive art projects, and provides examples/links to many beautiful variations of the projects.

The author’s inclusion of creative variations and implementations of art that, technically, has “already been done,” shows that keeping one’s mind open to all possibilities, and remembering the fundamental, core features of many types of art, can lead to amazing results. I think that all of us in class should remember when we are brainstorming about projects that just because something might have been done before, it does not mean that we cannot still attempt it and add something unique of our own.

 

Nose v. Nose

This week my project paid tribute to both of the last two assignments: I wanted to 1) make a project that did not require the user to use their hands, and 2) I wanted to make another game (because I had a lot of fun making my LED Soccer game last week). So, this week I created…

Nose v. Nose!

The idea is simple: two people must use their noses to win the game by rubbing their noses from the top to the bottom of the soft potentiometer. The LED lights are what keeps the score: the game starts with the yellow LED light in the middle, and then when the red player gets a point (by rubbing their nose) the light moves to the first red LED light. However, if the green player then gets a point, the light moves one step to the right, so it goes back to the yellow LED light (i.e. the scoring is more like a tug-of-war than traditional counting). So, to win, a player must get the light to move first to the close green/red LED light, then to the far one, and then once more to win, at which point the lights will flash many times.

Here is a video of me playing the game (alone, sadly); you can’t see the LED lights above my head very well, but if you watch closely you’ll see that each time I rub my nose on the sensor an LED light lights up, and then when I win at the end the LED lights flash. (As usual, it’s best to let the video load before playing.)

To show how the scoring works, I include another video below (just using my hands so as not to block the view of the LEDs). I first play for the red player, and get two points (at which time I would only need one more point to win). However, then I move to be the green player. When I am the green player, I have to rub the sensor three times just to get the red LED lights to turn off and to have the yellow light in the middle light up, showing that the score is at a tie again. Then, I rub three more times so that the green player wins.

The hardest parts about making this game were the following: 1) the soft potentiometers are rather difficult/sensitive to work with and continuously stopped working for a myriad of reasons, especially since I did not connect them directly to the bus board but instead used rainbow wires; 2) the sensors require hard pressure, which is actually pretty difficult to achieve with one’s nose; 3) the motion of rubbing one’s nose on the potentiometer has the extra effect of pulling out the potentiometer from its connection to other wires, which obviously makes the whole game stop working. After lots of trial and error, I managed to deal with these problems, although the game is still a bit finicky.

Overall, I enjoyed making the game and am happy that I was able to make something more silly/creative than I have the last two projects.

I include the code below in case anybody is interested in how the game works.

int ledRows[5] = {8, 9, 10, 11, 12};
int noseInput1 = A0;
int noseInput2 = A1;

int d1, d2, max1, max2;
int currentRow;
bool win1, win2;

void setup() {
     for (int i=0; i<5; i++) {
         pinMode(ledRows[i], OUTPUT);
     }

     pinMode(noseInput1, INPUT);
     pinMode(noseInput2, INPUT);

     max1 = 0;
     max2 = 0;

     currentRow = 2;

     Serial.begin(9600);
}

void loop() {
     if (currentRow < 0) {
          for (int i=0; i<30; i++) {
               digitalWrite(ledRows[0], HIGH);
               digitalWrite(ledRows[1], HIGH);
               delay(100);
               digitalWrite(ledRows[0], LOW);
               digitalWrite(ledRows[1], LOW);
               delay(100);
          }
          setup();
 }

else if (currentRow == 0) {
     digitalWrite(ledRows[0], HIGH);
     digitalWrite(ledRows[1], HIGH);
     digitalWrite(ledRows[2], LOW);
     digitalWrite(ledRows[3], LOW);
     digitalWrite(ledRows[4], LOW);
 }

else if (currentRow == 1) {
     digitalWrite(ledRows[0], LOW);
     digitalWrite(ledRows[1], HIGH);
     digitalWrite(ledRows[2], LOW);
     digitalWrite(ledRows[3], LOW);
     digitalWrite(ledRows[4], LOW);
 }

else if (currentRow == 2) {
     digitalWrite(ledRows[0], LOW);
      digitalWrite(ledRows[1], LOW);
      digitalWrite(ledRows[2], HIGH);
      digitalWrite(ledRows[3], LOW);
      digitalWrite(ledRows[4], LOW);
 }

else if (currentRow == 3) {
      digitalWrite(ledRows[0], LOW);
      digitalWrite(ledRows[1], LOW);
      digitalWrite(ledRows[2], LOW);
      digitalWrite(ledRows[3], HIGH);
      digitalWrite(ledRows[4], LOW);
 }

else if (currentRow == 4) {
      digitalWrite(ledRows[0], LOW);
      digitalWrite(ledRows[1], LOW);
      digitalWrite(ledRows[2], LOW);
      digitalWrite(ledRows[3], HIGH);
      digitalWrite(ledRows[4], HIGH);
 }

else if (currentRow > 4) {
      for (int i=0; i<30; i++) {
           digitalWrite(ledRows[3], HIGH);
           digitalWrite(ledRows[4], HIGH);
           delay(100);
           digitalWrite(ledRows[3], LOW);
           digitalWrite(ledRows[4], LOW);
           delay(100);
      }
      setup();
 }
 
 d1 = analogRead(noseInput1);
 d2 = analogRead(noseInput2);

     if (d1 > max1)
           max1 = d1;
      else if (max1-d1 > 700) {
           currentRow -= 1;
           max1 = 0;
      }

     if (d2 > max2)
           max2 = d2;
      else if (max2-d2 > 700) {
           currentRow += 1;
           max2 = 0;
      }
      Serial.print(d1);
      Serial.print(" ");
      Serial.print(d2);
      Serial.println();
      Serial.print(currentRow);
      Serial.println();
      delay(200);
}