At this point, computing, or coding in particular, to me means a new way of thinking. I’m pretty sure that many people can relate to the story of coming from a rather outdated educational system to a new one, which actually cares about what you think and how you think. Though for me this transition from memorizing as a way of learning to critical thinking was introduced after entering the IB, after coming to NYUAD, it only deepened.
In particular, taking Intro to IM (and coding for the first time) challenged the way I look and solve problems a lot. Trying to come up with efficient ways (instead of time-consumingly ‘hardcoding’ the whole thing) that can be then very easily changed and applied to something else too, as well as bottom-down approach and breaking things down to smallest possible components gave me a lot of trouble at first, but at the same time gave me a good foundation of new valuable cross-disciplinary skills.
Especially in relation to my love for (graphic) design, questioning the way I build things that people later interact with reshaped the way I think when designing. I started trying to predict what the reaction of the person will be and taking this prediction to my advantage when design decisions are to be made. This is where most of the readings came in handy – as the theoretical basis of design is often underdeveloped and underestimated, I never really put that much effort into exploring design through written pieces that raise critical questions and put things we take for granted into perspective.
Overall, calling the experience with computing becoming a better person would a bit of a stretch, but calling it becoming a person who is more critical and practical in regards to problem-solving and designing captures it a little better.
For my final project, I wanted to do a sort of continuation of my midterm project (the Sunflower); however, this time I would have used a real plant with a moisture sensor and other data sensors that I could then analyze on a screen using processing (AKA to know when to water the plant etc.). However, I didn’t think this involved much interaction (or the interaction was just too long term).
So then, I thought about creating an interactive game, a form of Dance Dance Revolution but for the hand. Again, I liked this concept a lot because the interaction is more clear but it lacked creativity.
So I’m considering combining the two and creating a game where the player has to move the plant on screen (using tangible buttons) and collect water droplets. Hopefully, as they collect more water, the more the plant grows. I’m not yet sure I want to do this 100% though. For this, I would need my Arduino, buttons (arrows), wiring and a box of some sort. The rest would be coded into Processing/Arduino directly.
I initially took IM for 2 reasons; to get a bit familiar with coding incase I need to adjust parts of my website, and because all my IM major friends told me I’d enjoy it, which I did. But having looked at and understood how such interesting things can and are made with coding has been really interesting and thought provoking for me. From the games that I used to think only professionals could make, to mind blowing interactive art.
In high school I took a course that taught us about the impact of computing on the world, from RFID to the Internet and security. But in this course I learnt to actually make things and work with computing, and actually do something. Coding is still very challenging for me to wrap my head around, but I no longer see it as a foreign skill that only certain people can do.
Throughout my childhood, whenever I was asked what I wanted to become, my only answer was “An inventor”. Not a doctor or lawyer or even an artist. Inventor. I was told that is not a job and so I sort of slowly let it go. I still remember when we got our IM kits, and I saw it said “Inventor’s kit”. It felt like destiny.
I still feel a bit intimidated by coding and computing but I definitely feel it has given me much more room for exploration.
For my final project, I hope to create an interactive installation that combines both light and sound that uses analog input that influences both LED and a generative art piece created using Processing.
Here is a rough sketch of the project.
I realize that it is hard to see these sketches, but essentially I plan to have one large projection of a Processing sketch, and in front of that, six beams that hold LEDs, and finally a control panel for the user.
The Processing sketch will be able to be controlled by the user through a large touch sensor, or a series of touch sensors, and effects will happen in the corresponding spot on the sketch that the user touches on the touch pad. I am still not sure how to do this, or if this is even possible to do considering that I want the correspondence to be very precise. I am in the process of looking at pieces of generative, interactive art created using Processing that I might be able to gain inspiration from.
Secondly, I will create a second control panel with six touch sensors that will correspond to each of the LED beams hanging in front of the user. These will be clear acrylic beams with three RGB LEDs inside. When there is no touch or force detected, the LEDs will remain at a certain brightness. When a touch is detected, the LED will light up exactly how strong the force the user puts into the sensor. Each LED will have exactly one color that the user is able to manipulate. A touch of the sensors will also result in a corresponding sound being played aloud. The beams will also appear to “wrap around the user,” with the closest beams being directly to the right and left of the user.
The Processing sketch will also have a sound being played, probably a more bass-like, ambience noise, while the beams and their sensors will produce sounds that correspond to musical notes. This will allow the user to be immersed in a sound and light piece that they are able to see direct feedback from.
As of now, I believe that these are the parts I require:
18 RGB LEDs
6 panels of transparent acrylic
6 sound amplifiers
6 force/touch sensors (small)
1 large touch sensor with the ability to detect where the touch occurred (I do not know if this is possible)
Until this semester, I haven’t really stopped to think about what computing means to me. Computing has been really eye-opening for me because I can now understand various aspects of a computer’s inner workings, and not only that, but I’m actually interested in it. Physical computing is an especially interesting part of that because it enables us to create virtual programs that can respond to our physical world.
Before last year, I hadn’t had any experience with coding, and as a freshman, I never thought I would minor in Interactive Media. Frankly, I didn’t even know what it was. I didn’t know that I would be able to code on my own or that I would be able to understand the way some programming languages work. Simply, I never thought that my interests would overlap with coding. I always thought coding was rigid, mysterious, difficult–and that you had to have a talent for it. I didn’t know you could create art using code. Just two days ago, I was going through my inbox, and I found an e-mail that I had sent in the 6th grade to my IT teacher with my homework submission. That week, we learned to create our first basic HTML webpage, where we were asked to write a short description of ourselves:
Aside from having to encounter my terrible grammar and color scheme or having to read about my strange obsession with Oreos, seeing this page made me think about how that was my first and last encounter with coding–until I took my first Interactive Media class just a year ago.
For my final project, I want to do something that gives digital output, with a physical input. I call this idea: “Wreck this Virtual Habitat”.
As for the use if sensors, I was thinking I could incorporate maybe pressure sensors, by having a pressure sensor with a lot of coins on it, and the more coins you remove from the pressure sensor, the more the environment gets ruined.
#include <Servo.h>
Servo myservo;
int pos = 0;
int ServoPin = 10;
int ServoAngle;
void setup() {
// start serial port at 9600 bps:
Serial.begin(9600);
myservo.attach(ServoPin);
}
void loop() {
if (Serial.available() > 0) {
// read the incoming byte:
ServoAngle = Serial.read();
myservo.write(ServoAngle);
}
}
Processing Code:
int new_angle, this_angle, temp_angle;
int e_rad = 100, e_ctr_x = 250, e_ctr_y = 200;
int l_length = 100;
int r_ctr_x = e_ctr_x, r_ctr_y = e_ctr_y;
color angle_color = 200;
PImage bg;
Serial port;
Serial type;
void setup() {
bg = loadImage("trees.jpg");
size(800, 533);
new_angle = 90;
printArray(Serial.list());
String portname=Serial.list()[3];
println(portname);
port = new Serial(this,portname,9600);
this_angle = 90;
strokeWeight(15);
}
void draw() {
background(bg);
textSize(60);
text("D to destroy, C to Clean" ,0,100);
if (this_angle < new_angle) {
//println("1) ", new_angle, angle);
this_angle = this_angle + 5;
}
if (this_angle > new_angle) {
//println("2) ", new_angle, angle);
this_angle = this_angle - 5;
}
angle_color = int((float(this_angle)/180) * 255);
fill(255, angle_color, 0);
ellipse(e_ctr_x, e_ctr_y, e_rad, e_rad);
//calculate the outer point of the lever arm
int x2 = int(cos(radians(this_angle)) * l_length + e_ctr_x);
int y2 = int(sin(radians(this_angle)) * l_length + e_ctr_y);
//println(x2, y2);
line(e_ctr_x, e_ctr_y, x2, y2);
if (temp_angle != this_angle) {
port.write(this_angle); //write the servo angle to the serial port
temp_angle = this_angle;
println(this_angle);
}
}
void keyPressed(){
switch(key) {
case 'd':
new_angle = 0;
break;
case 'c':
new_angle = 180;
break;
}
//println(new_angle);
}
This is what the interface looks like on the computer (the processing screen):
When you click C, the servo turns to the clean ocean, full of animals and plants and the text turns to yellow. When you click D, the servo turns to the polluted ocean scene and the text turns to red.
For this week’s assignment, we were asked to create a project that combines both Arduino and Processing by allowing them to perform a serial “handshake”.
To do this, I used my OOP processing project and replaced the mouse interaction with a rotary potentiometer. This was, for the most part, easy to do. We completed an in-class example where we controlled a basic ellipse shape across the X-axis as well, and I was surprised that I could apply the same simple code (with a few minor tweaks) to a processing sketch that was a bit more complex, without breaking the code.
Here is a video demonstration:
I created a box for the potentiometer, in an attempt to make it a little bit more visually appealing.
Here’s my code:
Arduino:
void setup() {
// put your setup code here, to run once:
Serial.begin(9600);
Serial.println('0');
}
void loop() {
if(Serial.available()>0){
char inByte=Serial.read();
int sensor = analogRead(A0);
delay(0);
Serial.println(sensor);
}
}
Processing:
//arrayList to hold all stars
ArrayList<Star> stars = new ArrayList<Star>();
import processing.serial.*;
Serial myPort;
int xPos=0;
int State = 0;
//instantiate new moon object
Moon moon = new Moon();
int modifier;
float raindrop;
int red, green, blue;
void setup()
{
size(585,430);
background(0);
raindrop= 0;
printArray(Serial.list());
String portname=Serial.list()[1];
println(portname);
myPort = new Serial(this,portname,9600);
myPort.clear();
//myPort.bufferUntil('\n');
//generate 30 random stars
for (int i = 0; i < 30; i++)
{
//adds them to star ArrayList for easy access
stars.add(new Star());
}
}
void draw()
{
//move raindrop down screen
raindrop = raindrop + 4; //speed
//if raindrop falls below canvas, reset to zero
if (raindrop >= height)
raindrop = 0;
//map xPos to rgb values of background
red = int(map(xPos, 0, width, 83, 0));
green = int(map(xPos, 0, width, 157, 0));
blue = int(map(xPos, 0, width, 253, 0));
modifier = int(map(xPos, width/2, width, 29, 0));
background(red, green, blue);
if (xPos > width/2)
{
for (int i = 0; i < stars.size() - modifier; i++)
{
Star s = stars.get(i);
s.drawStar();
}
}
moon.update();
moon.drawMoon();
//rainfall
fill(211,211,211);
rect(10, raindrop, 2, 5);
rect(50, raindrop+20, 2, 5);
rect(80, raindrop, 2, 5);
rect(110, raindrop+100, 2, 5);
rect(140, raindrop+150,2, 5);
rect(180, raindrop-200, 2, 5);
rect(200, raindrop-150, 2, 5);
rect(240, raindrop-50, 2, 5);
rect(240, raindrop, 2, 5);
rect(300, raindrop+20, 2, 5);
rect(440, raindrop, 2, 5);
rect(440, raindrop, 2, 5);
rect(550, raindrop+100, 2, 5);
rect(530, raindrop-250, 2, 5);
rect(530, raindrop-200, 2, 5);
rect(580, raindrop-300, 2, 5);
rect(300, raindrop-400, 2, 5);
rect(140, raindrop-350, 2, 5);
rect(400, raindrop-300, 2, 5);
rect(400, raindrop-250, 2, 5);
rect(400, raindrop-200, 2, 5);
rect(550, raindrop, 2, 5);
//this part of my code uses & adapts from "skyline" by Shiwen Qin on OpenProcessing
//building 1
fill(250);
rect(35,255,5,55);
fill(250);
rect(40,250,40,60);
fill(51, 51, 51);
quad(80,250,80,310,95,310,95,260);
fill(106,106,71);
for (int y=258; y<310; y+=8){
fill(106,106,71);
rect(36,y,2,2);
}
for (int y=258; y<300;y+=10){
for(int x=44; x<78; x+=10){
fill(106,106,71);
rect(x,y,3,3);
}
}
//building 2
fill(51, 51, 51);
rect(93,265,40,60);
for (int y=270; y<300;y+=10){
for(int x=96; x<130; x+=10){
fill(165,160,102);
rect(x,y,5,3);
}
}
//building 3
fill(220,220,220);
rect(150,225,15,120);
fill(220,220,220);
rect(164,215,10,140,6);
fill(169,169,169);
rect(166,218,2,140,7);
fill(105,105,105);
arc(170,250,70,70,-PI/2,0);
rect(170,250,35,140);
fill(192,192,192);
arc(170,250,60,60,-PI/2,0);
rect(170,250,30,140);
fill(192,192,192);
arc(170,250,40,40,-PI/2,0);
rect(170,250,20,140);
//fourth building
fill(250);
fill(250);
rect(235,225,5,75);
fill(250);
rect(240,225,40,80);
fill(106,106,71);
for (int y=258; y<310; y+=8){
fill(106,106,71);
rect(236,y,2,2);
}
for (int y=258; y<300;y+=10){
for(int x=244; x<278; x+=10){
fill(106,106,71);
rect(x,y,3,3);
}
}
// fifth building
fill(102, 102, 102);
rect(300,185,36,120);
fill (51, 51, 51);
rect (295, 185, 5, 120);
rect (305, 185, 5, 120);
//sixth building
fill(51, 51, 51);
rect(376,172,2,10);
rect(375,180,3,15);
quad(350,206,350,316,380,316,380,190);
fill(102, 102, 102);
quad(375,198,375,316,405,316,405,215);
fill(51, 51, 51);
rect(387,215,1,115);
rect(396,215,1,115);
//seventh building
fill(51, 51, 51);
rect(430,200, 40 ,150);
fill(250);
rect(430,200, 40 ,5);
rect(470,200, 2 ,150);
//seventh building .2
fill(192,192,192);
rect(490,200, 40 ,150);
fill(250);
rect(490,200, 40 ,5);
rect(500,200, 2 ,150);
//eighth building
fill(51, 51, 51);
rect(225,225,10,120);
rect(270,225,10,120);
//building 8
arc(540,190,70,70,-PI*4/6,-PI*1/6,CHORD);
quad(523,159,523,325,570,325,570,172);
for(int y=170;y<325 ;y+=5){
fill(106,106,71);
quad(523,y,570,y+2,570,y+4,523,y+2);
}
//ninth building
fill(51, 51, 51);
quad(585,165,615,155,620,325,585,325);
fill(31,30,72);
triangle(614,155,622,158,619,325);
for(int y=210;y<325 ;y+=5){
fill(106,106,71);
quad(585,y,615,y-1,615,y+1,585,y+2);
}
for(int y=210;y<325 ;y+=5){
fill(64,64,34);
quad(615,y-1,621,y,621,y+2,615,y+1);
}
//shore
fill(69, 137, 163);
rect(0,310,900,400);
//mangroves, forloop
for(int x=0;x<900;x+=20){
mangroves(x,310,10,10,3,28,5,255);
//varying parameters for mangroves
mangroves(x+10,305,8,8,6,41,8,255);
mangroves(x+5,300,5,4,14,62,17,255);
}
}
void cloud(int x,int y,int w,int h,int red,int green,int blue,int a){
fill(red,green,blue,a);
ellipse(x,y,w,h);
}
//sets variables they're being created in
void mangroves(int x,int y,int w,int h,int red,int green,int blue,int a){
fill(red,green,blue,a);
ellipse(x,y,w,h);
ellipse(x+5,y+5,w,h);
ellipse(x-5,y-3,w,h);
ellipse(x+3,y-5,w,h);
ellipse(x-3,y+5,w,h);
}
void serialEvent(Serial myPort){
String s=myPort.readStringUntil('\n');
s=trim(s);
if (s!=null)
xPos=(int)map(int(s),0,650,0, width); //jere
println(xPos);
myPort.write(State);
}
class Moon
{
int x;
int y;
int sizeMod = 0;
Moon()
{
//instantiate moon at x = 60, y = 90
this.x = 60;
this.y = 90;
}
void drawMoon()
{
int blue, green;
//map xPos to green and blue rgb values for moon
green = int(map(xPos, 0, width, 221, 250));
blue = int(map(xPos, 0, width, 0, 205));
noStroke();
fill(255, green, blue);
//map Pos X to rgb values for background/sky
int bg_red = int(map(xPos, 0, width, 83, 0));
int bg_green = int(map(xPos, 0, width, 157, 0));
int bg_blue = int(map(xPos, 0, width, 253, 0));
//map xPos to variable sizeMod, starting at 0, ending at 20
sizeMod = int(map(xPos, 0, width/6, 0, 20));
//width/6 divides canvas into 6, for each moon/sun phase
if (xPos <= width/6)
{
//sizeMod decreases size of moon, starts at 80, ends at 80 - 20 = 60
ellipse(x, y, 80 - sizeMod, 80 - sizeMod);
}
else if (xPos > width/6 && xPos <= 2 * (width/6))
{
arc(x, y, 60, 60, HALF_PI, 3 * HALF_PI, OPEN);
}
else if (xPos > 2 * width/6 && xPos <= 3 * width/6)
{
ellipse(x, y, 60, 60);
//draw two overlapping circles to give illusion of crescent moon
fill(bg_red, bg_green, bg_blue);
ellipse(x + 10, y, 50, 50);
}
else if (xPos > 3 * width/6 && xPos <= 4 * width/6)
{
ellipse(x, y, 60, 60);
//can't figure out how to flip arc, just cover with rectangle
fill(bg_red, bg_green, bg_blue);
rect(x - 30, y - 30, 30, 60);
}
else if (xPos > 4 * width/6 && xPos <= 5 * width/6)
{
ellipse(x, y, 60, 60);
//draw two overlapping circles to give illusion of crescent moon
fill(bg_red, bg_green, bg_blue);
ellipse(x - 10, y, 50, 50);
}
else
{
ellipse(x, y, 60, 60);
}
}
void update()
{
x = xPos;
}
}
class Star
{
int x;
int y;
Star()
{
//instantiate star with random x and random y values, every time you restart sketch it' random
this.x = int(random(0, width));
this.y = int(random(0, height/3));
}
void drawStar()
{
fill(255);
ellipse(x, y, -1.5, -1.5);
}
}
I’ve always been fascinated with the prospect of utilizing computing or coding as a medium to generate art, and discover intersections between the visual and the tangible. So I felt that Interactive Media would be ideal in helping me explore and combine art and technology, and when we started delving deeper into using Processing, it made me realize that I might be a little closer to visualizing some of my projects. Having no prior experience in coding, it was kind of a challenging process to execute a lot of the concepts I had in mind, and I would end up being frustrated most of the time. However, I came to understand that this is a new world of possibilities that only recently opened up to me, and I know more now than when I started out. It’s also already a huge milestone that I can look up functions online and more or less understand how to employ them in Processing to achieve certain effects. It’s also quite interesting how we’re now learning about the ability to combine Arduino and Processing, which really enabled me to think about all the possible intersections between different programs and coding languages.
I’m hoping that the projects I created in this class so far, are only the beginning of my computing journey and the belief that I still have a lot to learn is a little comforting at the moment. As the deadline for the final project looms near, I was really hoping to surprise myself with some badass coding skills I have stored in my subconscious, but I think it’s important for me (and all of us really) to be ambitious but within the limits of our current knowledge.
For this week’s assignment, we were supposed to use one of our Processing creations and connect it with Arduino. I decided to go with my Computer Art recreation, as I saw a lot of possibilities to play with the work a little bit.
What I ended up doing is simply mapping the potentiometer values to the number of dots in each segment as well as the size of the dots. In this way, if put on the maximum potentiometer value, the dots gradually consume the whole screen.
There were almost no issues with this, as I was working with an already existing code that worked properly. All I had to do is to start the communication with Arduino and add mapping of the values. The only thing that gave me a little trouble was finding the right values so that the increase in the size and number of dots is smooth and gradual. It just took a couple of trials and errors to achieve the desired effect and voilà.
Here is the Processing code:
//setting up the number of dots used in different segments
int numberCirclesA = 700;
int numberCirclesB = 1000;
int numberCirclesC = 3000;
int numberCirclesD = 5000;
//setting up communication with arduino
import processing.serial.*;
Serial myPort;
//setting up variables for x, y locations, and width of the dots
float x;
float y;
float w = 3;
void setup() {
size (800, 390);
//noLoop(); // to be activated only to see the exact replica of the original image
//setting up communication with arduino
printArray(Serial.list());
String portname=Serial.list()[51];
println(portname);
myPort = new Serial(this, portname, 9600);
myPort.clear();
myPort.bufferUntil('\n');
}
void draw () {
background (255);
noStroke();
fill(0);
// different segments in which the dots are being drawn
for (int i = 0; i < numberCirclesA; i++) {
pushMatrix();
x = random(0, width);
y =random(0, height);
ellipse (x, y, w, w);
popMatrix();
}
for (int i = 0; i < numberCirclesB; i++) {
pushMatrix();
y = (random(110, 150));
x = (random(0, width));
ellipse(x, y, w, w);
popMatrix();
}
for (int i = 0; i < numberCirclesA; i++) {
pushMatrix();
x = random(0, width);
y = (random(0, height -30));
ellipse (x, y, w, w);
popMatrix();
}
for (int i = 0; i < numberCirclesB; i++) {
pushMatrix();
y = (random(40, height - 70));
x = random(0, width);
ellipse(x, y, w, w);
popMatrix();
}
for (int i = 0; i < numberCirclesC; i++) {
pushMatrix();
y = (random(20, height - 150));
x = random(0, width);
ellipse(x, y, w, w);
popMatrix();
}
for (int i = 0; i < numberCirclesD; i++) {
pushMatrix();
y = (random(60, height - 200));
x = random(0, width);
ellipse(x, y, w, w);
popMatrix();
}
for (int i = 0; i < numberCirclesD; i++) {
pushMatrix();
y = (random(40, height - 175));
x = random(0, width);
ellipse(x, y, w, w);
popMatrix();
}
//tracking the mouser cursor
print(mouseX);
print (" ");
println(mouseY);
}
//mapping the values of a potentiometer to number and width of the dots
void serialEvent(Serial myPort) {
String s=myPort.readStringUntil('\n');
s=trim(s);
if (s!=null) {
w=(int)map(int(s), 0, 1023, 3, 15 );
numberCirclesD=(int)map(int(s), 0, 1023, 5000, 20000);
numberCirclesA=(int)map(int(s), 0, 1023, 700, 20000);
numberCirclesB= (int)map(int(s), 0, 1023, 1000, 20000);
numberCirclesC= (int)map(int(s), 0, 1023, 3000, 20000);
}
println(numberCirclesD);
myPort.write('0');
}
And here is Arduino code we used in class:
void setup() {
// put your setup code here, to run once:
Serial.begin(9600);
Serial.println('0');
pinMode(2, OUTPUT);
}
void loop() {
if(Serial.available()>0){
//inByte reads the values from Processing
char inByte=Serial.read();
int sensor = analogRead(A0);
delay(5);
Serial.println(sensor);
digitalWrite(2, inByte);