Physical Computing

Arduino Code

int goodLight = 11; int badLight = 13; int pin = 5; int oil = 6; int water = 9; // 1 amp 9 volts int buttonState = LOW; // the current state of the output pin int readingButton; // the current reading from the input pin int previousButtonState = HIGH; // the previous reading from the input pin long time = 0; // the last time the output pin was toggled long debounce = 200; int buttonValue; void setup() { Serial.begin(9600); pinMode(goodLight, OUTPUT); pinMode(badLight, OUTPUT); pinMode(pin, INPUT); pinMode(water, OUTPUT); pinMode(oil, OUTPUT); } void loop() { readingButton = digitalRead(pin); //digitalWrite(9, HIGH); if (readingButton == HIGH && previousButtonState == LOW && millis() - time > debounce) { if (buttonState == HIGH){ buttonState = LOW; }else{ buttonState = HIGH; time = millis(); } } // Handshaking for p5 if (Serial.available() > 0) { int inByte = Serial.read(); buttonValue = buttonState; Serial.println(buttonValue); /* if (inByte == 111) { //Key pressed "o" Serial.println("Input Evaluated"); digitalWrite(led, HIGH); digitalWrite(9, HIGH); delay(1000); digitalWrite(9, LOW); digitalWrite(led, LOW); }*/ if (inByte == 98) { //Good receiving // Water Serial.println("Dropping Water"); digitalWrite(goodLight, HIGH); digitalWrite(water, HIGH); delay(700); digitalWrite(water, LOW); digitalWrite(goodLight, LOW); } if (inByte == 99) { //Bad receiving // Oil Serial.println("Dropping Oil"); digitalWrite(badLight, HIGH); digitalWrite(oil, HIGH); delay(1000); digitalWrite(oil, LOW); digitalWrite(badLight, LOW); } } // Close Serial available previousButtonState = readingButton; }

paper.js Code

var waterSound = document.getElementById("waterSound"); waterSound.src = 'waterDrop.mp3'; var spriteData = { pop: { start: 0, length: 1.1 }, }; var activeCircle = -1; var happyPosX = 890; var happyPosY = 163; var upsetPosX = 286; var upsetPosY = 320; var worriedPosX = 320; var worriedPosY = 530; var thrilledPosX = 350; var thrilledPosY = 180; var unexcitedPosX = 950; var unexcitedPosY = 430; var hopefulPosX = 500; var hopefulPosY = 80; var calmPosX = 780; var calmPosY = 550; var scaredPosX = 1010; var scaredPosY = 280; var ballPositions = [[window.innerWidth/2, window.innerHeight/2], [happyPosX, happyPosY], [upsetPosX, upsetPosY], [worriedPosX, worriedPosY], [thrilledPosX, thrilledPosY], [unexcitedPosX, unexcitedPosY], [hopefulPosX, hopefulPosY], [scaredPosX, scaredPosY], [calmPosX, calmPosY]]; var handle_len_rate = 2.4; var circlePaths = []; var circleTexts = []; var radius = 50; var dragRadius = 150; var readyCircle = []; var textList = ["Drag Here", "happy", "upset", "worried", "thrilled", "unexcited", "hopeful", "scared", "calm"]; var colorList = ["white", "white", "black", "black", "white", "black", "white", "black", "white"]; var colorTextList = ["black", "black", "white", "white", "black", "white", "black", "white", "black"]; var circlePath = new Path.Circle({ center: ballPositions[0], radius: dragRadius, fillColor: colorList[0], strokeColor: 'white', strokeWidth : 0, text : textList[0] }); circlePaths.push(circlePath); for (var i = 0, l = ballPositions.length; i < l; i++) { var smallCircle = new Path.Circle({ center: ballPositions[i+1], radius: 60, fillColor: colorList[i+1], strokeColor: 'white', strokeWidth : 0, text : textList[i+1] }); var circleText = new PointText(circlePaths[i].position.x,circlePaths[i].position.y); circleText.content = textList[i]; circleText.style = { fontFamily: 'Montserrat', fontWeight: 'bold', fontSize: 20, fillColor: colorTextList[i], justification: 'center' }; circlePaths.push(smallCircle); circleTexts.push(circleText); } //console.log(smallCircles); //circlePaths.push(smallCircle); // Adds the gooey effect /************************************************ Mouse Click **************************************/ function onMouseDown(event) { var distRecord = 999999; var recordCircle = -1; for(i = 1; i < circlePaths.length; i++ ){ var distant = dist(event.point.x,event.point.y,circlePaths[i].position.x,circlePaths[i].position.y); if(distRecord > distant){ recordCircle = i; distRecord = distant; } } activeCircle = recordCircle; //console.log(circlePaths[1]); //circlePaths[recordCircle].position.x = event.point.x; //circlePaths[recordCircle].position.y = event.point.y; var newPaths = [circlePaths[recordCircle],circlePaths[0]]; generateConnections(newPaths); } /************************************************ Mouse Drag **************************************/ function onMouseDrag(event) { //console.log(ballPositions); circlePaths[activeCircle].position = event.point; // Gets the position of the actively clicked circle circleTexts[activeCircle].position = event.point; // Gets the position of the actively clicked circle text var newPaths = [circlePaths[activeCircle],circlePaths[0]]; generateConnections(newPaths); //circlePaths[0].fillColor = "rgb(" + Math.round(Math.random()*255) + "," + Math.round(Math.random()*255) + "," + //Math.round(Math.random()*255) + ")"; var distance = dist(circlePaths[0].position.x,circlePaths[0].position.y,event.point.x,event.point.y); if(distance <= 300 ){ circlePaths[0].fillColor = circlePaths[activeCircle].fillColor; if (circlePaths[activeCircle].fillColor == 'black'){ console.log('The fill is black'); circleTexts[0].fillColor = 'white'; } else { circleTexts[0].fillColor = 'black'; } } } /************************************************ Mouse Release **************************************/ function onMouseUp(event) { console.log('You released the mouse!'); //smallCircle.position = event.point; // Making circle follow the mouse //generateConnections(circlePaths); var distance = dist(circlePaths[0].position.x,circlePaths[0].position.y,event.point.x,event.point.y); if(distance <= 300 && distance >= (dragRadius-30)+1 ){ circlePaths[0].fillColor = circlePaths[activeCircle].fillColor; //readyCircle.push(circlePaths[activeCircle]); console.log(readyCircle); } else if(distance <= dragRadius-30){ waterSound.currentTime = spriteData.pop.start; waterSound.play(); //alert(circlePaths[activeCircle].text); if (circlePaths[activeCircle].text == "happy"){ console.log("Happy"); serial.write('c'); circlePaths[1].position.x = happyPosX; circlePaths[1].position.y = happyPosY; circleTexts[activeCircle].position = [happyPosX, happyPosY]; } else if (circlePaths[activeCircle].text == "upset"){ console.log("Upset"); serial.write('b'); circlePaths[2].position.x = upsetPosX; circlePaths[2].position.y = upsetPosY; circleTexts[activeCircle].position = [upsetPosX, upsetPosY]; } else if (circlePaths[activeCircle].text == "worried"){ console.log("Worried"); serial.write('b'); circlePaths[3].position.x = worriedPosX; circlePaths[3].position.y = worriedPosY; circleTexts[activeCircle].position = [worriedPosX, worriedPosY]; } else if (circlePaths[activeCircle].text == "thrilled"){ console.log("Thrilled"); serial.write('c'); circlePaths[4].position.x = thrilledPosX; circlePaths[4].position.y = thrilledPosY; circleTexts[activeCircle].position = [thrilledPosX, thrilledPosY]; } else if (circlePaths[activeCircle].text == "unexcited"){ console.log("Unexcited"); serial.write('b'); circlePaths[5].position.x = unexcitedPosX; circlePaths[5].position.y = unexcitedPosY; circleTexts[activeCircle].position = [unexcitedPosX, unexcitedPosY]; } else if (circlePaths[activeCircle].text == "hopeful"){ console.log("Hopeful"); serial.write('c'); circlePaths[6].position.x = hopefulPosX; circlePaths[6].position.y = hopefulPosY; circleTexts[activeCircle].position = [hopefulPosX, hopefulPosY]; } else if (circlePaths[activeCircle].text == "scared"){ console.log("Scared"); serial.write('b'); circlePaths[7].position.x = scaredPosX; circlePaths[7].position.y = scaredPosY; circleTexts[activeCircle].position = [scaredPosX, scaredPosY]; } else if (circlePaths[activeCircle].text == "calm"){ console.log("Calm"); serial.write('c'); circlePaths[8].position.x = calmPosX; circlePaths[8].position.y = calmPosY; circleTexts[activeCircle].position = [calmPosX, calmPosY]; } } else{ // remove this circle from the readyCircle; } } var connections = new Group(); function generateConnections(paths) { // Remove the last connection paths: connections.children = []; for (var i = 0, l = paths.length; i < l; i++) { for (var j = i - 1; j >= 0; j--) { var path = metaball(paths[i], paths[j], 0.5, handle_len_rate, 300); if (path) { connections.appendTop(path); path.removeOnMove(); } } } } generateConnections(circlePaths); // --------------------------------------------- function metaball(ball1, ball2, v, handle_len_rate, maxDistance) { var center1 = ball1.position; var center2 = ball2.position; var radius1 = ball1.bounds.width / 2; var radius2 = ball2.bounds.width / 2; var pi2 = Math.PI / 2; var d = center1.getDistance(center2); var u1, u2; if (radius1 == 0 || radius2 == 0) return; if (d > maxDistance || d <= Math.abs(radius1 - radius2)) { return; } else if (d < radius1 + radius2) { // case circles are overlapping u1 = Math.acos((radius1 * radius1 + d * d - radius2 * radius2) / (2 * radius1 * d)); u2 = Math.acos((radius2 * radius2 + d * d - radius1 * radius1) / (2 * radius2 * d)); } else { u1 = 0; u2 = 0; } var angle1 = (center2 - center1).getAngleInRadians(); var angle2 = Math.acos((radius1 - radius2) / d); var angle1a = angle1 + u1 + (angle2 - u1) * v; var angle1b = angle1 - u1 - (angle2 - u1) * v; var angle2a = angle1 + Math.PI - u2 - (Math.PI - u2 - angle2) * v; var angle2b = angle1 - Math.PI + u2 + (Math.PI - u2 - angle2) * v; var p1a = center1 + getVector(angle1a, radius1); var p1b = center1 + getVector(angle1b, radius1); var p2a = center2 + getVector(angle2a, radius2); var p2b = center2 + getVector(angle2b, radius2); // define handle length by the distance between // both ends of the curve to draw var totalRadius = (radius1 + radius2); var d2 = Math.min(v * handle_len_rate, (p1a - p2a).length / totalRadius); // case circles are overlapping: d2 *= Math.min(1, d * 2 / (radius1 + radius2)); radius1 *= d2; radius2 *= d2; var path = new Path({ segments: [p1a, p2a, p2b, p1b], style: ball1.style, closed: true }); var segments = path.segments; segments[0].handleOut = getVector(angle1a - pi2, radius1); segments[1].handleIn = getVector(angle2a + pi2, radius2); segments[2].handleOut = getVector(angle2b - pi2, radius2); segments[3].handleIn = getVector(angle1b + pi2, radius1); return path; } // ------------------------------------------------ function getVector(radians, length) { return new Point({ // Convert radians to degrees: angle: radians * 180 / Math.PI, length: length }); }
Class 14: Moody Marble

December 14 2016

For a final physical computing project, my teammate Ellen Il Eun Kim and I created a tool that creates a graphical image based on the mood of a user about a specific topic. Using two pumps, water, paint, and an iPad, a user is asked a question and then is able to drag and drop their response to a question using a blob-like interface. After a user drags and drops their answer choices, the pumps paint a graphical image of the user's response on paper. This image is a sentiment analysis of that individual's unique reaction, and will is hung in a gallery next to other user's pieces for an overall comparison. Sentiment analysis provides an excellent source of information and insight that can determine marketing strategy, product messaging, and improve overall customer service.

Something that I especially focused on for this project was the graphical user interface. Over time, the user interface changed, as also did our project based on user testing. Our final interface was created using a JavaScript library called paper.js. The code is shown along with the project.

Class 12: Final Project Progress

December 10 2016

So far, this is a short composition of our process for creating a blob user interface, and testing the pumps with water and oil.

Class 11: Moving forward, teaming up, and moody water

November 30 2016

Creating a physical Mortal Kombat game requires more time and work than I am capable of doing by myself for the time given. Since the playtest, I have teamed up with Ellen to create a physical data visualization with water and oil. Based on the mood of the user and how they feel about the subject, they will contribute to the mixture of other's feelings before them.

Class 10: Playtest and Redesign

November 11 2016

After playtesting my idea this past week, to enhance a toy with interaction, I learned that my project caused great confusion. My project needed a specific outcome and audience, and because it lacked this, it failed. After observing how people interacted with the action figure during the playtest, I have revised my project significantly to adjust to the user expectations that I observed. The playtesters were not satisfied with simple interactive additions to a once dull action figure. Interestingly, the playtesters wanted to use the action figure as a tool to complete or fulfill something. They expected to learn or achieve something by moving the arms and legs of the figure.

Based off of the playtest feedback, I have changed the interaction of my project completely. What I will do now is use two action figures to create a physical fighting game, a physical Mortal Kombat. During the playtest, playtesters seemed to use the action figure as a control. This inspired me to make the action figure a tool for a fighting game. I now envision having two action figures as controls for a Mortal Kombat game, where the feedback is clear by having a healthbar or score for each figure on screen.

The hardest part about this project, in my mind, will be determining the right sensors to use to detect when an action figure arm or leg moves. For this project, the idea is have simple physical mechanics, and gameplay. I plan to use stretch sensors, each one attached from the back of the figure to both arms and legs, to detect if the arm or leg is being moved or not. I thought about accelorometers and force sensors, but these did not seem to work like I need them to.


Class 9: Final Project Materials

November 9 2016

Timeline:

  • Gather materials
  • Test sensors (capacitive touch sensors and force sensors) and get the circuit working. Have both digital and physical actions occurring.
  • Dissect the test toy and apply the circuit to the object.
  • Test functions with the test toy.
  • Apply working functions to the good toy.

BOM:

  • Iron Man (large) shiny, chrome action figure ($60 - $120 max)
  • 2 capacitive touch sensors ($8 @ $4 a piece)
  • 5 force sensors ($42 @ $8 a piece)
  • 1 master switch (to turn off all interaction if wanted by user -- have it)
  • 3+ white LEDs ($2 -$5 max)
  • 1 switch (or button) to toggle digital displays (have it)
  • Cheap action figure to test ($20 or less, hopefully but depends)
  • 3+ white LEDs ($2 -$5 max)
  • Small, good quality speaker (one that can play mp3 files -- $10)
Class 9: Final Project Proposal

November 2 2016

My leading idea for my final project in Physical Computing is to design an interactive toy (an Iron Man action figure). By enhancing characteristics of an action figure with physical interaction, the toy can inspire imaginations and create a better play experience for children. I have learned a lot this semester about what good interaction should be, and I feel that making an action figure interactive fulfills a goal to make our imaginations physical. This is commonly known with movies such as Toy Story and Child’s Play, where action figures come to life. It is important though, that toys are interactive and not robotic. I want a toy that I can “play” with and one that complements my actions, rather than performing automatically. When user’s play with action figures, how they play is solely based on imagination. My goal for this project is to enhance the character of a regular action figure by adding interaction.

What I would not like to do is dictate the imagination by adding directional feedback. I do not want to create a toy with feedback that limits the toy’s character, such as a toy speaking specific lines from a specific scene in a specific film when a button is pressed. This limits the imagination and is actually a joke, like when a little girl gets a doll that speaks sexist lines.

Instead, the interaction needs to remind and inspire the imagination of characteristics that make that toy the character that it is. Action figures are a certain color, a certain shape, and move a certain way that implies an underlying personality and character for that figure. This is straightforward. Interaction design is a tool, and one that we perform, that makes our lives easier by allowing us to communicate with the objects around us. I would like to give an action figure extra characteristics, based on interaction, to help users better understand the personality of the figure that they are playing with.

Here is the practical application of this.

This toy does not solve this problem very well.

If time allows, this would be another feature to think about adding.

Class 7: New York City Monumental Museum Installation Prototype

October 31 2016

Shown is the final project of teh New York City Monumental Museum Installation Prototype. Our original idea was to create an installation where the user would walk up and turn a knob to scroll through time to discover each building. The interaction for this original idea was mininmal, and might have put our users to sleep. After talking with Tom Igoe, Ellen and I decided to steer the installation in the direction of a game. The final product is an interactive quiz, where the users learn by listening to a factual question, select a building with the knob, and see if their guess was right. This made for a successful project in the end.

Another concept that Ellen and I thought about was accessibility design. We had an earlier idea about making toys for blind children, and so accessibility solutions were on our minds. We made this installion work for both visually and auditory impaired users.

p5.js Code

var serialMonitor = { mySwitch: null, myAnswer: null, realtime: null, } var timerSound; var knobSound; var correctSound; var wrongSound; var textColor = 0; var myBackgroundColor = 255; var questionOne; var questionOneFinished = false; var questionOnePass = false; var questionTwo; var questionTwoFinished = false; var questionTwoPass = false; var questionThree; var questionThreeFinished = false; var questionThreePass = false; var questionFour; var questionFourFinished = false; var questionFourPass = false; var questionFive; var questionFiveFinished = false; var questionFivePass = false; var serial; var onOff = 0; var knobValue = 0; var oldCurrentChoice = 0; var captureAnswer = 0; var oldAnswer = 0; var timer = 0; var startTime = 0; var currentStatus = "ask"; // var playing var usbPort = "/dev/cu.usbmodem411"; // Store the answer var answerList = []; function setup() { serialMonitor.mySwitch = document.getElementById("switch"); serialMonitor.myAnswer = document.getElementById("answer"); serialMonitor.realtime = document.getElementById("realtime_analog"); questionOne = document.getElementById("questionOne"); questionTwo = document.getElementById("questionTwo"); questionThree = document.getElementById("questionThree"); questionFour = document.getElementById("questionFour"); questionFive = document.getElementById("questionFive"); timerSound = document.getElementById("timerSound"); knobSound = document.getElementById("knobTurn"); correctSound = document.getElementById("correctSound"); wrongSound = document.getElementById("wrongSound"); createCanvas(windowWidth, windowHeight); // Serial Communication serial = new p5.SerialPort(); // make a new instance of serialport library serial.on('list', printList); // callback function for serialport list event serial.on('data', serialEvent);// callback for new data coming in serial.on('open', portOpen); serial.list(); // list the serial ports serial.open(usbPort); // open a port questionOne.onended = function() { currentStatus = "useTimer"; startTime = millis(); questionOne.pause(); questionOneFinished = true; answerList = [2]; serial.write('e'); }; questionTwo.onended = function() { currentStatus = "useTimer"; startTime = millis(); questionTwo.pause(); questionTwoFinished = true; answerList = [3]; serial.write('e'); }; questionThree.onended = function() { currentStatus = "useTimer"; startTime = millis(); questionThree.pause(); questionThreeFinished = true; answerList = [0]; serial.write('e'); }; questionFour.onended = function() { currentStatus = "useTimer"; startTime = millis(); questionFour.pause(); questionFourFinished = true; answerList = [4]; serial.write('e'); }; questionFive.onended = function() { currentStatus = "useTimer"; startTime = millis(); questionFive.pause(); questionFiveFinished = true; answerList = [1]; serial.write('e'); }; correctSound.onended = function() { if (questionOneFinished == false && questionTwoFinished == false && questionThreeFinished == false && questionFourFinished == false && questionFiveFinished == false){ currentStatus = "ask"; questionOnePass = false; questionTwoPass = false; questionThreePass = false; questionFourPass = false; questionFivePass = false; } else if (questionOneFinished == true && questionTwoFinished == false && questionThreeFinished == false && questionFourFinished == false && questionFiveFinished == false){ currentStatus = "askTwo"; questionOnePass = true; questionTwoPass = false; questionThreePass = false; questionFourPass = false; questionFivePass = false; } else if (questionOneFinished == true && questionTwoFinished == true && questionThreeFinished == false && questionFourFinished == false && questionFiveFinished == false){ currentStatus = "askThree"; questionOnePass = true; questionTwoPass = true; questionThreePass = false; questionFourPass = false; questionFivePass = false; } else if(questionOneFinished == true && questionTwoFinished == true && questionThreeFinished == true && questionFourFinished == false && questionFiveFinished == false){ currentStatus = "askFour"; questionOnePass = true; questionTwoPass = true; questionThreePass = true; questionFourPass = false; questionFivePass = false; } else if(questionOneFinished == true && questionTwoFinished == true && questionThreeFinished == true && questionFourFinished == true && questionFiveFinished == false){ currentStatus = "askFive"; questionOnePass = true; questionTwoPass = true; questionThreePass = true; questionFourPass = true; questionFivePass = false; } else if(questionOneFinished == true && questionTwoFinished == true && questionThreeFinished == true && questionFourFinished == true && questionFiveFinished == true){ currentStatus = "ask"; questionOnePass = false; questionTwoPass = false; questionThreePass = false; questionFourPass = false; questionFivePass = false; } }; wrongSound.onended = function() { // Repeat the current question if (questionOnePass == false && questionTwoPass == false && questionThreePass == false && questionFourPass == false && questionFivePass == false){ currentStatus = "ask"; } else if (questionOnePass == true && questionTwoPass == false && questionThreePass == false && questionFourPass == false && questionFivePass == false){ currentStatus = "askTwo"; } else if (questionOnePass == true && questionTwoPass == true && questionThreePass == false && questionFourPass == false && questionFivePass == false){ currentStatus = "askThree"; } else if (questionOnePass == true && questionTwoPass == true && questionThreePass == true && questionFourPass == false && questionFivePass == false){ currentStatus = "askFour"; } else if (questionOnePass == true && questionTwoPass == true && questionThreePass == true && questionFourPass == true && questionFivePass == false){ currentStatus = "askFive"; } }; refillChoices( questionChoices[currentQuestion] );// pass a different textAlign(CENTER); textFont("Vidaloka"); textSize(29); } function windowResized() { resizeCanvas(windowWidth, windowHeight); } function draw(){ if(currentStatus == "ask"){ //background(42, 99, 255); background(myBackgroundColor); fill(textColor); noStroke(); text('Which building is the tallest steel-supported brick building in the world?',width/2,height/2); // Make sure these sounds don't play on refresh correctSound.pause(); wrongSound.pause(); if(questionOne.paused){ questionOne.currentTime = 0; questionOne.play(); } } else if(currentStatus == "useTimer"){ choice("current"); checkTime(); //console.log("useTimer"); } else if(currentStatus == "judge"){ //nothing console.log("draw judge"); } else if(currentStatus == "askTwo"){ background(myBackgroundColor); fill(textColor); noStroke(); text("What building originally didnt have female bathrooms?\nThe management later alternated the floors, one for men and one for women,\na pattern that continues today.",width/2,height/2); // Make sure these sounds don't play on refresh correctSound.pause(); wrongSound.pause(); if(questionTwo.paused ){ questionTwo.currentTime = 0; questionTwo.play(); } } else if(currentStatus == "askThree"){ background(myBackgroundColor); fill(textColor); noStroke(); text("Which building has a 20 story high bomb resistant base?",width/2,height/2); // Make sure these sounds don't play on refresh correctSound.pause(); wrongSound.pause(); if(questionThree.paused ){ questionThree.currentTime = 0; questionThree.play(); } } else if(currentStatus == "askFour"){ background(myBackgroundColor); fill(textColor); noStroke(); text("Two images of which appear on a 10 dollar bill?",width/2,height/2); // Make sure these sounds don't play on refresh correctSound.pause(); wrongSound.pause(); if(questionFour.paused ){ questionFour.currentTime = 0; questionFour.play(); } } else if(currentStatus == "askFive"){ background(myBackgroundColor); fill(textColor); noStroke(); text("Which of these did King Kong, the giant ape in several films,\nclimb in both the original 1933 movie and the 2005 remake?",width/2,height/2); // Make sure these sounds don't play on refresh correctSound.pause(); wrongSound.pause(); if(questionFive.paused ){ questionFive.currentTime = 0; questionFive.play(); } } // Detect if on or off //console.log(onOff); if (onOff == 1){ if(questionOne.paused && questionOneFinished == false ){ questionOne.currentTime = 0; questionOne.play(); serial.write('s'); } } else if(onOff == 0){ questionOne.pause(0); questionTwo.pause(0); questionThree.pause(0); questionFour.pause(0); questionFive.pause(0); questionOneFinished = false; questionTwoFinished = false; questionThreeFinished = false; questionFourFinished = false; questionFiveFinished = false; questionOnePass = false; questionTwoPass = false; questionThreePass = false; questionFourPass = false; questionFivePass = false; currentStatus = "ask"; background(0); } // Call the function if question one has ended } // Closing draw function portOpen(){ //println('the serial port opened'); serial.write('x'); } var questionChoices = [ ['World Trade Center','Empire State Building','Chrysler Building','Flat Iron Building','Statue of Liberty'], ] var colorSet = [{r:255,g:210,b:92},{r:252,g:213,b:141},{r:255,g:199,b:66},{r:247,g:228,b:158},{r:255,g:216,b:112}]; var dynamicChoices = []; var currentQuestion = 0; function refillChoices( choicesList ){ dynamicChoices = []; for(i = 0; i < colorSet.length; i++ ){ var choice = { text: choicesList[i], color:{ r : colorSet[i].r, g : colorSet[i].g, b : colorSet[i].b } } dynamicChoices.push(choice); } console.log("list", dynamicChoices); } var choice = function(status){ fill(textColor); var testValue = null; if( status == "current" ){ testValue = knobValue; //console.log("current: " + testValue); if(timerSound.paused){ timerSound.play(); } } else if( status == "judge" ){ testValue = captureAnswer; //console.log("judge: " + testValue); } var myChoice = -1; if (testValue >= 0 && testValue <= 204) { myChoice = 0; } else if (testValue >= 205 && testValue <= 408) { myChoice = 1; } else if (testValue >= 409 && testValue <= 612) { myChoice = 2; } else if (testValue >= 613 && testValue <= 816) { myChoice = 3; } else if (testValue >= 817 && testValue <= 1023) { myChoice = 4; } if(status == "current"){ background( dynamicChoices[myChoice].color.r, dynamicChoices[myChoice].color.g, dynamicChoices[myChoice].color.b ); text( dynamicChoices[myChoice].text,width/2,height/2); if( myChoice != oldCurrentChoice ){ if(knobSound.paused){ knobSound.play(); oldCurrentChoice = myChoice; } else{ knobSound.pause(); knobSound.currentTime = 0; } } } else if(status == "judge"){ if( myChoice == answerList[ currentQuestion ]){ background(255); fill(textColor); text('Correct!',width/2,height/2); console.log('Correct!'); if(correctSound.paused && status == "judge" && onOff == 1){ correctSound.play(); } } else{ background(0); fill(255); text( ('Wrong.'),width/2,height/2); console.log('Wrong!'); if(wrongSound.paused && status == "judge" && onOff == 1){ wrongSound.play(); } } //console.log(answerList[ currentQuestion ], dynamicChoices[ answerList[currentQuestion] ].text); handshakeVal = 'x'; } }; function serialEvent(){ var inString = serial.readLine(); if (inString.length > 0){ inString = inString.trim(); var values = split(inString, ","); if (values.length > 2) { onOff = Number(values[0]); serialMonitor.mySwitch.innerHTML = onOff; captureAnswer = Number(values[1]); serialMonitor.myAnswer.innerHTML = captureAnswer; if(captureAnswer != oldAnswer ){ console.log("get new value"); choice("judge"); oldAnswer = captureAnswer; } knobValue = Number(values[2]); serialMonitor.realtime.innerHTML = knobValue; } serial.write(handshakeVal); // must be at the end } } var handshakeVal = 'x'; function printList(portList){ for (var i = 0; i < portList.length; i++){ println(i+" "+portList[i]); } } /* The Timer */ function checkTime(){ timer = millis(); var timePass = timer - startTime; var amountTime = 8000; if(timePass >= amountTime){ currentStatus = "judge"; serial.write("o"); } else{ if( (timePass < amountTime/3) && timePass > 0 ){ console.log("3 leds"); handshakeVal = 'c'; } else if( ( timePass < amountTime/3 * 2) && ( timePass > amountTime/3) ) { console.log("2 leds"); handshakeVal = 'b'; } else if( ( timePass < amountTime) && ( timePass > amountTime/3 * 2) ) { console.log("1 leds"); handshakeVal = 'a'; } } }

Arduino Code

// Declare which pin detects on or off int toggleOn = 5; // Start with button off int buttonState = LOW; // Read the button value int readingButton; // Store if the button was currently on or off, but assume it was on last time int previousButtonState = HIGH; // Declare the pins of the buildings int empireState = 7; int chrysler = 8; int tradeCenter = 9; int flatIron = 10; int liberty = 11; // Timer pins int timerPin1 = 2; int timerPin2 = 3; int timerPin3 = 4; // Variable to send values to p5 int sensorValue; int captureAnswer; int questionHasEnded; void setup() { Serial.begin(9600); // Declare the pins // On and off switch pinMode(toggleOn, INPUT); // Buildings pinMode(tradeCenter, OUTPUT); pinMode(empireState, OUTPUT); pinMode(chrysler, OUTPUT); pinMode(flatIron, OUTPUT); pinMode(liberty, OUTPUT); // timer pinMode(timerPin1, OUTPUT); pinMode(timerPin2, OUTPUT); pinMode(timerPin3, OUTPUT); } void buildingSelection() { // Get the knob value int analogValue = analogRead(A0); if (questionHasEnded) { // Logic for changing building lighting if (analogValue >= 0 && analogValue <= 204) { // Light up World Trade Center digitalWrite(tradeCenter, HIGH); digitalWrite(empireState, LOW); digitalWrite(chrysler, LOW); digitalWrite(flatIron, LOW); digitalWrite(liberty, LOW); } else if (analogValue >= 205 && analogValue <= 408) { // Light up Empire State Building digitalWrite(tradeCenter, LOW); digitalWrite(empireState, HIGH); digitalWrite(chrysler, LOW); digitalWrite(flatIron, LOW); digitalWrite(liberty, LOW); } else if (analogValue >= 409 && analogValue <= 612) { // Light up Chrysler Building digitalWrite(tradeCenter, LOW); digitalWrite(empireState, LOW); digitalWrite(chrysler, HIGH); digitalWrite(flatIron, LOW); digitalWrite(liberty, LOW); } else if (analogValue >= 613 && analogValue <= 816) { // Light up Flat Iron Building digitalWrite(tradeCenter, LOW); digitalWrite(empireState, LOW); digitalWrite(chrysler, LOW); digitalWrite(flatIron, HIGH); digitalWrite(liberty, LOW); } else if (analogValue >= 817 && analogValue <= 1023) { // Light up Statue of Liberty digitalWrite(tradeCenter, LOW); digitalWrite(empireState, LOW); digitalWrite(chrysler, LOW); digitalWrite(flatIron, LOW); digitalWrite(liberty, HIGH); } // Close knob values } else { // Make sure all lights are off digitalWrite(tradeCenter, LOW); digitalWrite(empireState, LOW); digitalWrite(chrysler, LOW); digitalWrite(flatIron, LOW); digitalWrite(liberty, LOW); } } void loop() { // Detect if the box is on or off buttonState = digitalRead(toggleOn); // If the project is turned on if (buttonState == LOW) { // Turn off the project buttonState = LOW; questionHasEnded = LOW; } else { // Turn on the project buttonState = HIGH; } buildingSelection(); // Get the knob value int analogValue = analogRead(A0); // Handshaking for p5 if (Serial.available() > 0) { int inByte = Serial.read(); sensorValue = buttonState; Serial.print(sensorValue); Serial.print(","); sensorValue = captureAnswer; Serial.print(captureAnswer); Serial.print(","); sensorValue = analogValue; Serial.println(analogValue); if (inByte == 101) { Serial.println("Q Ended"); //buttonState = HIGH; questionHasEnded = HIGH; } else if (inByte == 115) { Serial.println("Q Started"); //buttonState = LOW; questionHasEnded = LOW; } else if (inByte == 111) { Serial.println("Time Up"); //buttonState = LOW; questionHasEnded = LOW; captureAnswer = analogValue; Serial.print("Answer is: "); Serial.println(captureAnswer); } else { //timer indicators //x, a, b, c if (inByte == 120) { digitalWrite(timerPin1, LOW); digitalWrite(timerPin2, LOW); digitalWrite(timerPin3, LOW); } else if (inByte == 97) {// 1 led digitalWrite(timerPin1, HIGH); digitalWrite(timerPin2, LOW); digitalWrite(timerPin3, LOW); } else if (inByte == 98) {// 2 led digitalWrite(timerPin1, HIGH); digitalWrite(timerPin2, HIGH); digitalWrite(timerPin3, LOW); } else if (inByte == 99) {// 3 led digitalWrite(timerPin1, HIGH); digitalWrite(timerPin2, HIGH); digitalWrite(timerPin3, HIGH); } } } // Close Serial available } // Close loop
Class 7: Physical Interactive New York Monumental Quiz Process

October 31 2016

For the past week and a half, I have been working with a teammate, Ellen Il Eun Kim, to design and build an interactive prototype for a New York history museum. Our concept is an installation, that allows museum goers to interact through a fun quiz, that teaches users about the history of monumental structures in New York City.

Class 6: Synthesis Process

October 17 2016

I have been practicing with serial communication from the Arduino to p5.js. Everything has been working, except for some reason, the p5 result is delayed. After studying the labs, I think my problem is that the data is being received faster than p5 can respond. What I may need to do is check to see if data is received before sending another response (a call-and-response method).

Class 5: The Epic Battle

October 10 2016

Just when all hope was lost, and all that existed was the evil pilot (black action figure), a new storm trooper emerged to save the day (white action figure). The white figure has a motion sensor on the front. Whenever the black figure moves (from human interaction with a distance sensor), the white figure senses the black figures motion and fights back to save the human that is being attacked by the black figure.

For some reason, everything worked except the sound for the white figure. The white figure's speaker works when it is on the pin that belongs to the black figure. For some reason though, the white figure's speaker did not want to work and I am not sure why.

Class 5: Synthesis Project

October 7 2016

This week I worked on a team of two to create a project that incorporated both p5.js and Arduino. Using an older sketch of an iPod that I had drawn in p5.js where the user uses the mouse to hover over the white control area to play a song on the iPod, my team member Siman and I created physical buttons that played and paused the song on the iPod instead.

Class 4: Interactive action figure

October 4 2016

This is an interactive Star Wars action figure that comes to life when you are within a certain distance of the figure. The figure has a distance sensor attached to its back, and when you go to grab the figure, his arm moves on a 179 degree axis depending on your distance to the figure. The figure also has a light that blinks and a changing frequency both dependent on user distance.

While working with the distance sensor, I learned how gain control of the values that the sensor received. At first, I had trouble getting the figure's arm to move smoothly without being jittery. After frustration, a second year student pointed out to me that my code and wiring was correct, but the sensor had some loose wires. If wires are exposed to the air, the circuit picks up noise. After rewiring the sensor, and adding a resistor to the circuit, I was able to have better control of the distance sensor.

Class 4: Interactive action figure process

October 4 2016

This week I decided to make a Star Wars action figure interactive. After learning how to apply a distance sensor to my circuits, I had the idea that I could make a toy come to life when someone picks it up. Going off of the idea of creating an interactive Chuckie horror doll as a mid-term project, I thought that this would be a good step to take towards that goal.

I originally wanted an action figure of R2D2, so that the pitches of the speaker attached mimicked the sounds of the character. For this toy, however, I would rather have a mp3 file play the breathing of this character (like Darth Vader breathing). I have not figured out how to make that work yet.

Something that I wanted to do was embed the servo motor inside the toy. I wanted to take out the motor from it's plastic casing, but I was advised by other students in the shop that this may break the motor. As for now, the arm is disconnected.

Class 4: Preparation for application

September 30 2016

After practicing on my own, I figured out how to make the distance sensor work. In this simple application, the lights blink slower as my hand gets closer.


Class 3: Readings

September 27 2016

I believe that disability inspires interaction design because a common goal of interaction design is to do as much as possible without doing anything at all. In our world today, it seems like good interaction design is about decreasing interaction. Why is that? As I read Pullin’s Design Meets Disability, I realized that a common denominator in all the products and prosthetics was that they were all trying to be simple, yet so universal. There are problems with universal and inclusive designs though, as different people indeed have different abilities and desires. Disability is a strange way to go about considering design altogether since at some level we are all lacking an ability to do something. It seems more correct to realize that there is a desire for control that humans have that inspires interaction design. I talked with Professor Igoe this week, and after discussing sensors, we talked about what might make a good interactive product. Professor Igoe suggested considering creating interactions (in a Chuckie Doll) that surprise us. Maybe this is a way to go about solving the issue behind design that strives for simplicity and the capability to do as much as possible. Instead of worrying about designing interactions that must be understood and conform to everyone’s needs, perhaps we should focus on designing interactions that learn about us instead. I do think that disabilities make our world a better place because they push our need for good design. The less we can physically do, the more we rely on design and our interaction with design to help us. While most of the world sees interaction design as a method for solving problems, I will say that I think ITP is amazing in that separately, we use interaction design to produce ideas that do not necessarily need to solve problems, but instead create meaningful human experiences which adds value to interaction design in many other ways.

Class 3: Traffic Light Application

September 27 2016

Shown is a traffic light that senses brightness and darkness with a phototransistor. When the room is bright, and the analog values are high, the traffic light changes on a timer. When the room is dark, and the analog values are low, the traffic light stays on green. The idea behind this is that when a person or car is close to the traffic light, which means analog values should be low since a person would block the brightness, the light changes to green to let that person pass through. I stopped off by Professor Igoe's office and I was introduced to a distance sensor. This would be more practical to use, and so a distance sensor is what I used after the phototransistor was working. The distance sensor measures infared, which is a radiation with longer wavelengths than light. I was able to receive analog values for the distance sensor, however, the values were so precise that my application did not work. I found a minimum and maximum value for the sensor, and then I found a threshold.

Class 3: Observation

September 26 2016

The piece of interactive technology that I chose to observe is the traffic light at the corner of 8th and University Place near the NYU campus. I became interested in traffic lights ever since I received my Arduino kit in the mail, and I saw the red, green, and yellow LEDs. I immediately wanted to assemble a working light, and so not only was that my lab project for this week, but I also decided to observe a traffic light scenario to see how people interact with traffic lights and how traffic lights function.

Traffic lights are somewhat complex interactive systems because they require coordinated timing while sensing the presence of either a pedestrian or a car at any given moment. Once a traffic light has detected a person or car waiting to cross the road, the light must recalculate its timing based on user interaction.

My assumption was that people would generally obey traffic lights. I heard from the taxi driver when I arrived to New York City that there are several traffic deaths and injuries every year. I am originally from Texas where people do obey traffic lights, but on occasion creep through the lights. In New York City, however, the traffic system is different since there are always people crossing on every corner. I assumed that people would yield to the crosswalk signals, and that cars might try to creep through the lights as they might in Texas, if anything.

I was surprised to find out that cars tend to be more obedient to traffic lights than pedestrians in New York City. Cars would always stop at the traffic lights, however, I saw several people ignore the crosswalk signals. I think one of the difficulties people had with the crosswalk was noticing when the light changed or was about to change. This affected people that walked slower, since they had less time to cross the street. When I studied abroad in Australia, I remember that the crosswalks there had a drumming noise that let blind pedestrians know when they could cross the street. The easiest feature of traffic lights is their iconography and use of color. It is very clear what to do at a traffic light, although this is my assumption. Overall the entire transaction took anywhere from one to two minutes, and the people that crossed when the signal was red did not seem to get much further ahead than the other pedestrians, which indicates good timers and sensing.

Considering the readings, I think that traffic lights are very successful with their form and function. They are very simple, and require nearly no interaction, yet they interact with us regardless. If Crawford were to examine a traffic light, I feel as if he would agree that they are successful interactive systems, but they are rare in that they continuously try to have a conversation with us while we sometimes ignore them.

Class 3: Traffic Light Analog Sensor process

September 23 2016

I was able to add a sensor to my traffic light, but occasionally, the sensor does not work. I was not able to get a Phototransistor to work properly because the only analogRead it would print was 0. I tried a potentiometer next and it worked, sort of. It works fine but occasionally it will not sense a change in the potentiometer. I need to figure out if this is a coding problem or a wiring problem. I know actual traffic lights use motion sensors, so I wonder if Arduino has some sort of motion sensor? That is what I really need, something that could sense a person waiting for the light to change.

Class 3: Traffic Light (Digital input and Digital output) process

September 22 2016

So far so good. I was able to write an Arduino program on my own and create a traffic light on a timer, which I wanted to do last week. Digital input and digital output is pretty cool. The next step is to see if I can add sensors. When a person comes close to the light, it should automatically turn green, just like in the real world when traffic lights sense a car waiting for the light to change. Let's see if I can figure this out in less than a week, before our next class.


Class 2: Readings

September 19 2016

I was able to see many truths in both Design of Everyday Things and Emotional Design by Norman. I believe that the best designs are obvious in how they should be used, and I agree that natural signals with visual clues are the best way to suggest their usage. However, to what level should design be visibly obvious to a user? Furthermore, can simple and obvious devices truly perform complex tasks, like the phone system? Technically an interactive device can perform a complex task, like the case of the car. Although, I consider a car to be a combination of interactive devices rather than one interactive device itself. A car has a radio, door operations, a steering wheel, and so on which all work separately. Design seems to offer itself one function at a time, yet the human being can touch, hear, smell, and see simultaneously. So can simplified, visibly obvious interactive devices suggest their own capabilities then, without sacrificing interactivity? I can imagine that the answer to this question is that an interactive device could, but why would anyone want that? I just like the idea of interactivity as more of a conversation that incorporates simultaneous physical actions, rather than only considering clicks and touching the design of the future.

I also liked seeing all the possibilities of physical computing in Physical Computing’s greatest hits (and misses). I think I have an idea for my mid-term project.

Class 2: Lab 1 Police Lights Application

September 19 2016

Shown is a circuit of police lights. Both LED lights are lit, and when a pushbutton is pressed, one of the lights turns off. When the button is pushed quickly, the illusion of police lights is seen.

Also shown is the opposite circuit below. Only one light is lit, and when a pushbutton is pressed, both lights turn on.

Class 2: Lab 1 Police Lights Application Process

September 16 2016

For the first lab, I really wanted to create a manual traffic light. I wanted to push a button, and every time that button is pressed, I wanted a different colored LED light to turn on. This would have been perfect since I have red, green, and yellow lights in my kit. When I realized that this was a bit too complicated though, I decided to start by making a manual police siren with a pushbutton and only two lights. As a starting point, I recreated the potentiometer lab on my own. Everything worked. Next I experimented with the pushbuttons. I was able to get one light to turn on and off with a pushbutton, but when I tried to turn on and off two lights, I failed. Maybe I do not completely understand how the pushbutton switches up the current, although I do understand that a pushbutton simply closes the circuit. However, I was able to have two lights on at the same time that were both triggered by a pushbutton. When the pushbutton was open, the current would travel through both the red and blue lights. When the pushbutton was closed, all of the current would go to the blue light only.

I think what I want requires programming with the computer, which is to come since I looked ahead and googled how to make this work.


Class 1: Readings

September 7 2016

Physical interaction is a cyclic process, like all interaction design, that requires the effort of input, process, and output. However, unlike screen-based or 'picture behind glass' interaction design, physical interaction concerns itself with how 3D objects interact with the human body and human senses. Good physical interaction should imitate natural feedback found in the world and utilize the senses of humans (such as feeling, seeing, and manipulation) to amplify the human capability to solve a problem or perform a task.

In my experience, a good example of digital technology that is not interactive (completely) would be a majority of websites. Although the web itself is interactive, there are several sections on the web that lack interactivity and feel like digital books or advertisements that can be found offline. Crawford suggests that anything can be interactive, but to what measure (like a refrigerator light bulb) do we consider a device interactive? The web's success is due to it's interactivity. Should websites of the future have web banners and videos that we can only react to? I'm curious how we can make the web not just design behind glass, but involve the user to engage more often when searching the web.

Class 1: Fantasy Device

September 7 2016

Today in class we created a fantasy device. Along with two other team members, I assembled a device that converts animal voices to human language. Through an interface, a user selects their language and which animal they wish to communicate with. The user points the microphone funnel towards that animal and hears the animal speak with the headphones.

Designed and developed by Steven Simon 2016.