Interaction Lab(Moon) Recitation 8: Drawing Machines, Hanlu Zhang (Mary)

  • Instructor: Moon
  • Partner: Lichen Dong
  • Aim:
  • Build a circuit to control the stepper.
  • Build a circuit that can control stepper by potentiometer and the MotorKnob example in Arduino.
  • Write a sketch on Processing that send values to Arduino to control the motor
  • Corporate with my partner to combine two motors  into a mechanical arm that can hold a marker. Use processing to control the movement of each motor, and make adjustments with my partner to draw on the paper
  • Material
  • 1 42STH33-0404AC stepper motor
  • 1 SN75440NE ic chip
  • 1 power jack
  • 12 V power supply
  • 1 potentiometer from your kit
  • 1 Arduino and USB cable from your kit
  • Laser-cut mechanisms
  • Pen that fits the laser-cut mechanisms
  • Schematics
  • (http://ima.nyu.sh/interaction-lab/lab-8-drawing-machines/)
  • Process
  • Part1
  • First I connect the circuit according to the schematics and use power to make it rotate.
  •    
  • Part2
  • Then I add a potentiometer into the circuit to control the stepper.
  • However, the stepper can rotate but can’t be controlled by the potentiometer, then with professor Antonius’ reminder, I found that the out put from potentiometer is 0-1023 while the input that stepper need is from 0-200. So I use map function to make the data suitable, and then the stepper can be controlled
  • .
  • Test video:
  • Part 3
  • Then I remove the potentiometer and control the stepper with data from Processing. I create a sketch which is 200*200, and map the mouse position with angle of stepper
  • Then I put together the parts of the laser-cut mechanisms like the picture below
  • And the test movie is below:
  • Part 4
  • Finally, I combine my mechanisms with my partner’s, and control the pen together. Here’s the video that my partner control two computer together while I’m taking this video.
  • Coursed learned:

  • Use of map() function
  • Ways of interaction

Interaction Lab(Moon) Midterm Project: User Test Part II

  • Project Name: Xylophone–Music Learner
  • Producer: Lichen Dong
  • Using experience: Lichen’s project it’s constructed by battens that represent different keys in the Xylophone, and when you knock the key, a drop of color will drop in the barrel below. The project looks very nice as it reminds me of one of my toy in childhood, and it also reminds me a traditional instrument called “Yangqin“. And when I knock the keys with a stick, user experience is good as it feels that I’m a real musician.
  • Suggestions
    • My first suggestion will be that it’s will be better to add some performing instructions so that I can play some songs on the Xylophone, which will let me gain more pleasure from playing it.
    • Maybe it will looks better to paint the keys in the same color with drops so the physical part and processing part will be more connected
    • Maybe it’s also possible to make the project more interactive that when the color drop, users click the corresponding key to make a sound.
  • Test video (video by Lichen)

Interaction Lab(Moon) Midterm Project: User Test Part I

  • Midterm Project: Star Puzzle
  • Name: Hanlu Zhang(Mary)
  • Date: October.2 2017
  • Instructor: Moon
  • Questions I have for the testers
    • Is it easy for you to understand the project?
    • Are the instructions clear enough?
    • Is the degree of difficulty proper?
  • User’s feedbacks
    • Problems1: The dots are too little to be clicked so sometime just miss them and have to restart the whole levels
      • Possible reasons:
      • The dots is indeed a little bit too small;
      • When mouse is on the dot, the change of color is not obvious enough
      • The original color of dots is not obvious enough.
      • Possible solutions:
      •  Make the dots bigger. But consider the visual effects, it will be a better choice to keep the size of dots but change the range that the click can be counted as clicked.
      • Change the original color and the color after being selected to make it more obvious.
    • Problems2: It’s hard to know what’s the star is, especially in Level3 and Level 4, one of which has lines inside the star and the other has three stars in one scene
      • Possible reasons:
      • The introductions and informations I give at the beginning is not enough that user can’t understand what the game is.
      • The shortage of instructions before each level.
      • The shortage to tell people what does each shape look like rather than say “star”
      • Possible solutions
      • Give instructions before each level like : Draw a normal star/Draw a star with 7 points/Draw a star with lines inside/Draw 3 stars in this level. And it will be easier for users to understand.
      • At the start page try to explain a little bit more or add another state for rules.
    • Problem3: The feedback to users are too few that users will feel confused or annoyed when all the lines disappear.
      • Possible reasons:
      • When they make some mistakes, I don’t give enough feedback to show that the lines are disappeared because of you click a wrong dots or don’t click on and dots.
      • Sometimes users make too much mistakes and lose the patience to continue.
      • Possible solutions:
      • Give more feedbacks like when connected a wrong lines, the reminder that “wrong lines”will appear, and also says “no dots selected” when clicking on background.
      • To make it more interesting, some effects can be added. For example, for user whoo have restarted the current level twice, when the mouse is near dots, it will “shake” unless it’s the right one.

Interaction Lab(Moon) Midterm Project: Star Puzzle- Hanlu Zhang(Mary)

Midterm Project: STAR PUZZLE

  • Date: October.2 2017
  • Instructor: Moon
  • Introduction

Star Puzzle is a game that user will connect dots to draw stars and each line can only be drawn once. If a line is drawn twice or a line doesn’t exist is drawn or the user click somewhere that doesn’t have a star, the current level will be restart. The game has 4 levels in total.

  • Inspiration 

At first I want to make a game that users can draw Chinese constellations, however I find them to abstract to become a visual game. Then, during my research online, I saw a game that let users to draw a shape in one continual line(https://www.openprocessing.org/sketch/4827#), which inspire me a game that I always play with my mom when I was young that we try to draw stars with different number of points in a continual line. So I decided to make a game that users need to figure how to draw all the lines of the star in one time.

  • Process 
  1. Background

As the game is about drawing stars, so I want to make the background looks like real sky. Therefore, I set an array with 1500 dots with random position and random size between 0.1 to 3. The opacity is random and will run circular as it’s under the “void”, so the stars look like that they are “blinking”.

To make the background more interactive, I also use “dist” function to detect the distance between  the mouse position and stars. if the mouse is near the star, the dot will be a little bit bigger.

here is the code:

And the effect is the video below:

 

2. Setup

The main elements in my projects are dots and lines. So I first set up arrays for dots and lines in different levels.

Then I setup some variables for detecting:

select dot: the dot user click on to star, I define this with the mousePressed and distance between mouse and dot’s center.

totalLines: when mouse click, totalLines +1, which can detect how many lines user has been drawn in total

countLines: when a right line is drawn, countLines +1, which can detect how many correct lines has been drawn.

solve: which to show whether the user finish the current level.

draw: to decide whether the line can be draw.

3.Detection

First is for whether the lines can be draw. i will detect it each time mouseReleased. When solve == false, which means current level haven’t been solved, and a dot is selected, then drawing == true that lines can be drawn. The the dot be selected first is startDot and the later one is endDot.

And in void draw, I also detect the endDot, if endDot doesn’t exist, the line is between mouse and startDot. If endDot exist, the line between them is drawn and endDot becomes the new startDot. The code is below

 

Second is whether the current level has been finished. I use if statement to detect whether user have finished the current level. The code is:

countLine = totalLine means the user doesn’t draw any lines twice and countLines = currentLines.length (I will explain this array later) means all the lines in current level has been drawn. When these two statements are fulfilled, the user has drawn all the lines correctly and can enter next level.

  • Problems and Developments
  1. As I plan to design several puzzles, I have different arrays in both lines and dots, but when I first write the code, I design everything based on level which only contains lines1 and dots1. So after I finishing the structure of my code, I became confused that whether I have to rewrite all the code for level2 and again for level 3, which may make my code super long. Then with the help of Jiwon, I understand that I can set up another arrays that are “Dot[] currentDots;” and “Line[] currentLines;” and declare them with l the lines array and dots array in it, So that I can use currentLines/Dots instead of specific arrays and my processing become more organized.
  2.  As I have different level, but I don’t know how to make the action of “moving to next level”. As Kaye has similar part in her code, so she shared the use of mode and case functions. Then, when  solve == true, mode will switch to the next one, and all the variables can be reset.

To make is more complete, I also create start and end scenes

3. After setting the start page, I set the if statement that if mousePressed in start page, first level will start. However, when I test it, I found that sometimes it detected the mouseReleased, but doesn’t detect the Press. Then Professor moon tell me that this happens because I write the “if mousePressed” function in the “void draw”, which has some distance with the function “void mousePressed” I write in the later part. So sometimes, processing may miss the order as the frameRate has refresh before it perform the order.

So I move this code under the mousePressed and I also move the mousePressed function in mode 5(ending part) into the same place to avoid this problem.

  • User Test

After finishing the first draft, I ask some friends to test it, and I received some responses from them. Professor moon and fellows in lab also give me some suggestions to make it better.

1. First response is that the current level should be reset automatically when user makes a mistake so that they don’t need to restart from the first level. So that I set another if statement in the checkResult part that if countLines doesn’t equal to totalLines-1, which means user draw lines more than ones, current level reset. However for the situation that user click somewhere that doesn’t have dots is a little bit tricky. With professor Moon’s advice, I create a new variable called “count” and if one dot is selected, count will plus 1 . Each time mouseReleased, processing will check the count, if count = 0, which means no dot is selected, the current level will be reset.

The effect is like the video below:

2. In the first draft, the shape that user need to draw in the level will show in the background and they will draw the lines on that graph like that:

Then professor Moon suggest me delete the graph in the background to make the visual effects better and also make the game harder, so in the final draft, each level will start with dots only.

3. Some of my friend told me that the levels in first draft is too simple and suggest me to add a harder level so that people who are good at this kind of game won’t feel boring. So I add a new level that have 12 points and 18 lines, which looks like that:

  • Demo

Here is the demo of my project

  • Lesson Learned
  1. The use of array and class

In my project, I use several arrays to list the lines and dots in different levels, which makes my project organized, as well as make the logic more clear. The use of class makes it possible to control each line or dots in array, making my project easier to code.

2. Create new functions

I create some new functions like “selected””drawNightSky””setupNightSky”, which makes the code under setup and draw shorter and more clear to understand.

3. Smart use of “println();”

From this project, I feel the importance of “println();”. First, when I find the position of dots, I just insert the background photo and let processing “println” the mouse position when I click the dots’ positions.

Second I learn from Professor Moon and fellow Jiwon that when bug happens, I can use “println” important datas that are used to control the following actions to see whether data match the order. Or I can write “println something” after some certain code to say whether the order is working so that I can find where the problem is.

4. Be careful! Be patient!

During processing, I make some stupid mistakes like confusing the “currentLines” and “currentDots”, or type semicolon after “if()”. These mistakes takes a lot of time to be found and fixed, so being careful can save time.

And when something wrong happens in my code, being patience is important or it will spend more time to fining the bug.

  • Conclusion

From making this project, I practiced what I have learned in class, as well as having experience of the whole process of making a project. There are still some problems existing in my project like the instructions are not clear enough or the lack of feedback to user, which I will explain more and give some possible solutions in the later documentation. But the whole process really bring me lots of fun.

  • Special Thanks

Thanks Professor Moon for giving me suggestions of using “count” to detect whether dots are selected and suggestions in visual effects. Thanks Jack for helping me organize my logic and structure before starting coding. Thanks Jiwon for suggestions of using “currentLines/dots”. Thanks Kaye for sharing the use of mode/case with me. Thanks my roommate Demi who encourage and support me during the whole process. Thank you all !

PImage img1;
PImage img2;
PImage img3;
PImage img4;
PImage img5;
PImage img6;
PImage img7;
int mode = 0;
color dotColor = color(255);
color dotColorOver = color(200, 200, 0);
color dotColorClicked = color(200, 200, 0);
int countLines;

Dot[] currentDots;
Line[] currentLines;

Dot[] dots1 = new Dot[5];
Line[] lines1 = new Line[5];
//level one dots and lines
Dot[] dots2 = new Dot[7];
Line[] lines2 = new Line[7];
//level two dos and lines
Dot[] dots3 = new Dot[12];
Line[] lines3 = new Line[18];
//level four dos and lines
Dot[] dots4 = new Dot[13];
Line[] lines4 = new Line[15];
//level four dos and lines

int selectedDot=99, startDot = 99, endDot = 99;
int totalLines = 0;

boolean drawing;
boolean solved;

// night sky
int numofCircles = 1500;
float []size = new float[numofCircles];
float []x = new float[numofCircles];
float []y = new float[numofCircles];
color[] clr = new int [numofCircles];

void setup() {
  size(1000, 780);
  frameRate(15);
  drawing=false;
  solved=false;
  SetupDotsAndLines();

  //NightSky
  setupNightSky();
  img1 = loadImage("Title.png");
  img2 = loadImage("Start.png");
  img3 = loadImage("LevelTitle1.png");
  img4 = loadImage("LevelTitle2.png");
  img5 = loadImage("LevelTitle3.png");
  img6 = loadImage("LevelTitle4.png");
  img7 = loadImage("End.png");
  println("length of currentDots: " + currentDots.length);
}

void draw() {
  drawNightSky();
  switch(mode) {
  case 0:
    image(img1, 0, 0);
    image(img2, 250, 400);
    break;
  case 1: //level 1
    image(img3, 0, 0);
    break;

  case 2://level2
    image(img4, 0, 0);
    break;
  case 3://level3
    image(img5, 0, 0);
    break;
  case 4://level4
    image(img6, 0, 0);
    break;
  case 5://end
    image(img7, 200, 250);
  }
  // draw the dots
  if (mode > 0 && mode < 5) {
    for (int i=0; i<currentDots.length; i++) {
      currentDots[i].display();
    }
    for (int i=0; i<currentLines.length; i++) {
      if (currentLines[i].visible == true) { 
        currentLines[i].display();
      }
    }
  }

  //draw lines
  if (drawing==true) { 
    stroke(#FFEC8B, 250);
    if (selectedDot != 99) {
      line(currentDots[selectedDot].x, currentDots[selectedDot].y, mouseX, mouseY);
    }
  }
}

void mousePressed() {
  println("startDot: " + startDot + ", endDot: " + endDot + ", selectedDot: " + selectedDot);

  if (mode == 0) {
    mode = 1;
    totalLines = -1;
    println("total lines in case 0: " + totalLines);
  } else if (mode == 5) {
    selectedDot=99;
    startDot = 99;
    endDot = 99;
    totalLines = 0;
    solved=false;
    SetupDotsAndLines();
    for (int i = 0; i < currentLines.length; i++) {
      currentLines[i].visible = false;
      mode = 0;
    }
  }
}

void mouseReleased() {
  if (solved==false) {
    totalLines++;
    println("totalLines: " + totalLines);
    if (selectedDot!=99) {
      currentDots[selectedDot].c=dotColor;
    }
    drawing=false;  

    int count = 0;
    for (int i = 0; i < currentDots.length; i++) {
      if (currentDots[i].selected()==true) {
        count++;
      }
    }
    println(count);
    if (count == 0) { 
      selectedDot=99;
      startDot = 99;
      endDot = 99;
      totalLines = 0;
      for (int i = 0; i <currentLines.length; i++) {
        currentLines[i].visible = false;
      }
    }

    for (int i=0; i<currentDots.length; i++) {
      if ((currentDots[i].selected()==true) && (i!=startDot)) {
        drawing=true;
        currentDots[i].c=dotColorClicked;
        selectedDot=i;
        break;
      }
    }

    if (drawing==true) {
      if (startDot==99) {
        startDot=selectedDot;
        //println("In mouse released - startDot: " + startDot);
      } else if (endDot==99) {
        endDot=selectedDot;
        //println("In mouse released - endDot: " + endDot);

        drawLine(startDot, endDot);
        checkResult();
      }
      startDot=selectedDot;
      endDot=99;
    } else {
      startDot=99;
      endDot=99;
    }
  }
}

void mouseMoved() {
  if (solved==false) {
    for (int i=0; i<currentDots.length; i++) {
      if (selectedDot==i) {
      } else
        if (currentDots[i].selected()==true) {
          currentDots[i].c=dotColorOver;
        } else {
          currentDots[i].c=dotColor;
        }
    }
  }
}

/* mouseDrag is the same as mouseMove */
void mouseDragged() {
  mouseMoved();
}
void SetupDotsAndLines() {
  currentDots = dots1;
  currentLines = lines1;

  //level1 dots 
  dots1[0] = new Dot(502, 181);
  dots1[1] = new Dot(255, 368);
  dots1[2] = new Dot(347, 666);
  dots1[3] = new Dot(660, 667);
  dots1[4] = new Dot(755, 369);
  println("created dots1");
  //level1 lines
  lines1[0] = new Line(0, 2);
  lines1[1] = new Line(0, 3);
  lines1[2] = new Line(1, 3);
  lines1[3] = new Line(1, 4);
  lines1[4] = new Line(2, 4);
  println("created lines1");

  currentDots = dots2;
  currentLines = lines2;
  //level2 docts 
  dots2[0] = new Dot(505, 182);
  dots2[1] = new Dot(307, 283);
  dots2[2] = new Dot(259, 498);
  dots2[3] = new Dot(394, 672);
  dots2[4] = new Dot(618, 673);
  dots2[5] = new Dot(752, 497);
  dots2[6] = new Dot(705, 283);
  println("created dots2");

  //level2 lines
  lines2[0] = new Line(0, 3);
  lines2[1] = new Line(0, 4);
  lines2[2] = new Line(1, 4);
  lines2[3] = new Line(1, 5);
  lines2[4] = new Line(2, 5);
  lines2[5] = new Line(2, 6);
  lines2[6] = new Line(3, 6);
  println("created lines2");

  currentDots = dots3;
  currentLines = lines3;
  //level3 docts
  dots3[0] = new Dot(502, 137);
  dots3[1] = new Dot(256, 278);
  dots3[2] = new Dot(257, 560);
  dots3[3] = new Dot(502, 702);
  dots3[4] = new Dot(745, 562);
  dots3[5] = new Dot(746, 279);
  dots3[6] = new Dot(422, 279);
  dots3[7] = new Dot(339, 421);
  dots3[8] = new Dot(420, 560);
  dots3[9] = new Dot(584, 560);
  dots3[10] = new Dot(664, 421);
  dots3[11] = new Dot(583, 278);
  println("created dots3");

  //level3 lines
  lines3[0] = new Line(0, 6);
  lines3[1] = new Line(0, 11);
  lines3[2] = new Line(1, 6);
  lines3[3] = new Line(1, 7);
  lines3[4] = new Line(2, 7);
  lines3[5] = new Line(2, 8);
  lines3[6] = new Line(3, 8);
  lines3[7] = new Line(3, 9);
  lines3[8] = new Line(4, 9);
  lines3[9] = new Line(4, 10);
  lines3[10] = new Line(5, 10);
  lines3[11] = new Line(5, 11);
  lines3[12] = new Line(6, 7);
  lines3[13] = new Line(7, 8);
  lines3[14] = new Line(8, 9);
  lines3[15] = new Line(9, 10);
  lines3[16] = new Line(10, 11);
  lines3[17] = new Line(6, 11);
  println("created lines3");

  currentDots = dots4;
  currentLines = lines4;
  //level4 docts
  dots4[0] = new Dot(262, 318);
  dots4[1] = new Dot(383, 407);
  dots4[2] = new Dot(338, 549);
  dots4[3] = new Dot(187, 550);
  dots4[4] = new Dot(144, 407);
  dots4[5] = new Dot(503, 319);
  dots4[6] = new Dot(624, 407);
  dots4[7] = new Dot(578, 549);
  dots4[8] = new Dot(429, 550);
  dots4[9] = new Dot(744, 317);
  dots4[10] = new Dot(865, 408);
  dots4[11] = new Dot(819, 548);
  dots4[12] = new Dot(669, 550);
  println("created dots4");

  //level4 lines
  lines4[0] = new Line(0, 2);
  lines4[1] = new Line(0, 3);
  lines4[2] = new Line(1, 3);
  lines4[3] = new Line(1, 4);
  lines4[4] = new Line(2, 4);
  lines4[5] = new Line(5, 7);
  lines4[6] = new Line(5, 8);
  lines4[7] = new Line(6, 8);
  lines4[8] = new Line(1, 6);
  lines4[9] = new Line(1, 7);
  lines4[10] = new Line(9, 11);
  lines4[11] = new Line(9, 12);
  lines4[12] = new Line(10, 12);
  lines4[13] = new Line(6, 10);
  lines4[14] = new Line(6, 11);
  println("created lines4");

  currentDots = dots1;
  currentLines = lines1;
}

void setupNightSky() {
  for (int i=0; i<numofCircles; i++) {
    x[i] = random(width);
    y[i] = random(height);
    size[i] = random(.1, 3);
  }
}

void drawNightSky() {
  background(#00005b);
  for (int i = 0; i < size.length; i++) {
    fill(random(235, 255), random(235, 255), 255, random(100, 255));
    noStroke();
    float distance = dist(mouseX, mouseY, x[i], y[i]);
    if (distance < 10) {
      ellipse(x[i], y[i], size[i]+3, size[i]+3);
    } else { 
      ellipse(x[i], y[i], size[i], size[i]);
    }
  }
}

class Dot {
  int x; // dot x position
  int y; // dot y position
  int s; // dot size
  color c; // dot color
  boolean selected;

  Dot(int localX, int localY) {
    x = localX;
    y = localY;
    s = 20;
    c = color(192);
  }

  void display() {
    noStroke();
    fill(c);
    ellipse(x, y, s, s);
  }

  boolean selected() {
    float disX = x - mouseX;
    float disY = y - mouseY;

    if (sqrt(sq(disX) + sq(disY)) < s/2 ) {
      //println("selected dot with x: " + x);

      return true;
    } else {
      return false;
    }
  }
}

class Line {
  int startDotIndex, endDotIndex;
  int startX, startY;
  int endX, endY;
  boolean visible;

  Line(int startDot, int endDot) {
    startDotIndex = startDot;
    endDotIndex = endDot;
    startX=currentDots[startDot].x;
    startY=currentDots[startDot].y;
    endX=currentDots[endDot].x;
    endY=currentDots[endDot].y;
    visible=false;
  }
  void display() {
    stroke(#FFD700, 250);
    line(startX, startY, endX, endY);
  }
}

void drawLine(int startDot, int endDot) {

  int a = 20;
  int b = 20;
  if (startDot < endDot) {
    a = startDot;
    b = endDot;
  } else if (startDot > endDot) {
    a = endDot;
    b = startDot;
  } else {
    drawing=false;
  }
  if (drawing==true) {
    for (int i = 0; i < currentLines.length; i++) {
      if (a == currentLines[i].startDotIndex && b == currentLines[i].endDotIndex) {
        currentLines[i].visible = true;
        println("line " + i  + " is visible");
      }
    }
  }
}

void checkResult() {
  int countLines=0;
  for (int i=0; i<currentLines.length; i++) {
    if (currentLines[i].visible==true) {
      countLines++;
    }
  }

  println("countLine: " + countLines);
  println("currentLines.length:"+currentLines.length);

  for (int i=0; i<currentLines.length; i++) {
    if ((countLines==totalLines-1)&&(countLines==currentLines.length)) {
      drawing=false;
      solved=true;
      mode++;
      switch(mode) {
      case 2:
        currentDots = dots2;
        currentLines = lines2;
        break;
      case 3:
        currentDots = dots3;
        currentLines = lines3;
        break;
      case 4:
        println("case 3");
        currentDots = dots4;
        currentLines = lines4;
        //println("currentDots length: " + currentDots.length);
        break;
      case 5:
        currentDots = dots1;
        currentLines = lines1;
        break;
      }

      println("mode: " + mode);

      selectedDot=99;
      startDot = 99;
      endDot = 99;
      totalLines = 0;
      solved=false;
    } else if (countLines!=totalLines-1)
    {
      selectedDot=99;
      startDot = 99;
      endDot = 99;
      totalLines = 0;
      currentLines[i].visible = false;
    }
  }
}

Interaction Lab(Moon) Recitation 6: Serial Communication, Hanlu Zhang (Mary)

  • Date: October 21,2017
  • Instructor: Moon
  • Aim: (http://ima.nyu.sh/interaction-lab/lab-6-serial-communication/)
  1. Create a circuit using your Arduino to send data from physical inputs (ie. variable resistors, buttons, tilt switch) to Processing. Receive the data and express it visually in your Processing sketch.
  2. Create a Processing sketch that sends data to Arduino. Receive that data and express it using physical components (ie. servo, led, buzzer).
  • Materials needed: 
    • 1 * Breadboard
    • 1 * Arduino
    • 1 * potentiometer
    • 1 * Buzzer
    • Hookup Wires
  • Process
  • Project 1
  • I want to create a project that the size and pellucidity of the circle on the screen can be controlled by the potentiometer. I first connect a potentiometer to the Arduino, the circuit is the picture below.
  • then I began the Processing part, I int the r g b, which is the number from Arduino, as the value of  potentiometer is from 0-1023, I change the output as “analogRead(A0)/4” so that the value is from (0-127).
  • Then I found nothing is on my screen. With the help of Professor Moon, I figure out that I need to set up a background below the int draw otherwise the change of the circle can’t be show.
  • Finally, the project looks like below. As the color is random, each time the color will be different.
  • 2. Processing to Arduino
  • For P to A project, I want to make a project that I can turn on and turn off the buzzer by the red and green buttons on the screen.
  • First I set up the circuit that have a buzzer.
  • Then I begin the Processing part, I draw to buttons on the screen. And I want to make the effect that clicks the button. I learn from Professor that I can limit it by distance function that if the distance between center of circle and mouse is smaller than radius and clicking the button, the “High” signal can be send to Arduino.
  • Then for the Arduino part, the difficulty I has is how to turn on and turn off the Buzzer, from the library I find the “tone” and “noTone” function.
  • Finally it looks like the video below
P to A
Processng:
import processing.serial.*;

Serial myPort;
int valueFromArduino;


void setup() {
  size(500, 500);
  background(0);
  printArray(Serial.list());
  // this prints out the list of all available serial ports on your computer.

  myPort = new Serial(this, Serial.list()[ 4 ], 9600);
  // WARNING!
  // You will definitely get an error here.
  // Change the PORT_INDEX to 0 and try running it again.
  // And then, check the list of the ports,
  // find the port "/dev/cu.usbmodem----" or "/dev/tty.usbmodem----" 
  // and replace PORT_INDEX above with the index number of the port.
}


void draw() {
  // to send a value to the Arduino
  fill(255, 0, 0);
  ellipse(150, 250, 100, 100);
  fill(0, 255, 0);
  ellipse(350, 250, 100, 100);
  float distance1 = dist( mouseX, mouseY, 150, 250);
  float distance2 = dist(mouseX, mouseY, 350, 250);
  if ((mousePressed)&&(distance1 < 50)) {
    myPort.write('H');
  } else if
    ((mousePressed)&&(distance2 < 50)) {
    myPort.write('L');
  }
}


Arduino:
int valueFromProcessing;
int Buzzer = 8;


void setup() {
  Serial.begin(9600);
  pinMode(Buzzer, OUTPUT);
}


void loop() {
  // to receive a value from Processing
  while (Serial.available()) {
    valueFromProcessing = Serial.read();
  }

  if (valueFromProcessing == 'H') {
    tone(Buzzer, 80);
  } else if (valueFromProcessing == 'L') {
    noTone(Buzzer);
  }

  // too fast communication might cause some latency in Processing
  // this delay resolves the issue.
  delay(10);
}


A to P
Processing:
import processing.serial.*;
int a;
float r =random(0, 255);
float g =random(0, 255);
float b =random(0, 255);

Serial myPort;
int valueFromArduino;


void setup() {
  size(500, 500);
  background(255);

  printArray(Serial.list());
  // this prints out the list of all available serial ports on your computer.

  myPort = new Serial(this, Serial.list()[4], 9600);
  // WARNING!
  // You will definitely get an error here.
  // Change the PORT_INDEX to 0 and try running it again.
  // And then, check the list of the ports,
  // find the port "/dev/cu.usbmodem----" or "/dev/tty.usbmodem----" 
  // and replace PORT_INDEX above with the index number of the port.
  random(0, 255);
}


void draw() {
  // to read the value from the Arduino
  while ( myPort.available() > 0) {
    valueFromArduino = myPort.read();
  }
  background(255);
  int a = valueFromArduino;
int d = valueFromArduino;

  fill(r,g,b, a);  // println(valueFromArduino);
  ellipse(width/2, height/2,d,d);
}

Arduino:
void setup() {
  Serial.begin(9600);
}


void loop() {
  int poteValue = analogRead(A0)/4;
  Serial.write(poteValue);
  //Serial.println(poteValue);

  // too fast communication might cause some latency in Processing
  // this delay resolves the issue.
  delay(10);
}

Interaction Lab(Moon) field trip to Maker Carnival: Hanlu Zhang (Mary)

On Saturday afternoon, I went to Maker Carnival, and there are three things that impressed me.

  • The first one is coding by model

In the Carnival, I met so many companies that provide kids’s technology education, and what impressed me is the using of code is so easy that everyone can do it. Before I think processing or Arduino are the easiest way to code, but the carnival give more example.

For this one different has different function, so that as long as you attach the model you need, you can crate your project. The hole on it is for Lego so that you can easily attach them with Lego.

This one is a robotics that can moving by the black track, this one is not only creating by models, but also can coding on cellphone and send it to the robotics by bluetooth like that:

  • The second is the universality of 3D printing

In the Carnival, lots of booths has 3D printer products, some of them are amazing:

This is a 3D printing Ferris wheel, the small parts on it can move when rolling it.

This is a people model, which can interact with people’s reaction (however they haven’t finished it, so it’s just a model now.)

  • The third one is the potential of Arduino

In the carnival, I found that over 2/3 exhibitions are based on Arduino, which shows the infinite potential of Arduino. Below are to Arduino projects that I like:

This one is a Slots, when you click the button, the images on it will rolling, and stop randomly, and the probability of having three same images is super low.

This one is a time bomb, if you input the wrong code three times, or the time is up, the bomb will have the sound like “BOOM”

Conclusion:

This carnival is much more interesting then my imagination, and it spire me a lot for my midterm as well as my future.

 

Interaction Lab(Moon) Recitation 5: Animation in Processing, Hanlu Zhang (Mary)

  • Date: October, 13th, 2017
  • Instructor: Moon
  • Aim:Create an animation with Processing using any 2D primitive or vertex shapes
  • Process

I plan to make draw a cat which can play with me, which means it can interact with my actions.

First I draw a cat using function ellipse(); triangle();and line(); which looks like the picture below:

Then I hope it eyes will squint when the mouse is in the circle of its face, and I plan to use dist(); function that if the distance between mouse and center of the head is smaller than the head’s radius, the eyes will squint. But after writing it,  it doesn’t work.

float d1 = dist(400, 300, mouseX, mouseY);

void draw

if (d1 < 175) {
l2 = 20;
} else {
l2 = 70;
}

with fellow’s help, I found that the dist function should be written after the void draw, so that the processing can detect the position of mouse again and again. Then it looks like this:

To make it more interesting, I decide to use a ball instead of the mouse, also I hope the ball can rotate when I click the mouse, so I write:

if (mousePressed)
{
translate(mouseX, mouseY);
rotate(angle);
fill(#b0e2ff);
arc(0, 0, 50, 50, 0, PI*0.5);
arc(0, 0, 50, 50, PI*1, PI*1.5);
fill(#cd3333);
arc(0, 0, 50, 50, PI*.5, PI);
arc(0, 0, 50, 50, PI*1.5, PI*2);
angle+=1000;
} else {
fill(#b0e2ff);
arc(mouseX, mouseY, 50, 50, 0, PI*0.5);
arc(mouseX, mouseY, 50, 50, PI*1, PI*1.5);
fill(#cd3333);
arc(mouseX, mouseY, 50, 50, PI*.5, PI);
arc(mouseX, mouseY, 50, 50, PI*1.5, PI*2);
}

Finally it looks like that:

Conclusion:

This is an interesting project but I still have a lot to improve, as I also want to change the cat’s face with the mouse’s different position, or make the mouse and ear rotate a little bit when click the ball.

int l1 = 70 ;
int l2;
float d1;
float angle = 0.0;
void setup() {
  size(800, 600);
}

void draw() {
  background(255);
  smooth();
  strokeJoin(ROUND);
  fill(255);
  //noStroke();
  triangle(195, 110, 230, 240, 330, 140);
  triangle(595, 110, 570, 240, 470, 140);
  fill(#F3e59a);
  triangle(220, 130, 240, 240, 320, 140);
  triangle(580, 130, 560, 240, 460, 140);//ears
  ellipse(width/2, height/2, 380, 350);//head
  fill(255);
  ellipse(325, 255, 100, 100);
  ellipse(475, 255, 100, 100);
  fill(0);
  ellipse(325, 255, l1, l2);//left eye
  ellipse(475, 255, l1, l2);//right eye
  ellipse(400, 335, 40, 20);//nose
  fill(#f29c9c);
  ellipse(400, 375, 50, 60);
  stroke(0);
  fill(#F3e59a);
  arc(430, 345, 60, 60, 0, PI);
  arc(370, 345, 60, 60, 0, PI);//Mouse
  smooth();
  line(300, 335, 150, 300);
  line(300, 340, 150, 340);
  line(300, 345, 150, 380);
  line(500, 335, 650, 300);
  line(500, 340, 650, 340);
  line(500, 345, 650, 380);
  d1 = dist(400, 300, mouseX, mouseY);
  if (d1 < 175) { 
    l2 = 20;
  } else {
    l2 = 70;
  }
  if (mousePressed)
  {
    translate(mouseX, mouseY);
    rotate(angle);
    fill(#b0e2ff);
    arc(0, 0, 50, 50, 0, PI*0.5);
    arc(0, 0, 50, 50, PI*1, PI*1.5);
    fill(#cd3333);
    arc(0, 0, 50, 50, PI*.5, PI);
    arc(0, 0, 50, 50, PI*1.5, PI*2);
    angle+=1000;
  } else {
    fill(#b0e2ff);
    arc(mouseX, mouseY, 50, 50, 0, PI*0.5);
    arc(mouseX, mouseY, 50, 50, PI*1, PI*1.5);
    fill(#cd3333);
    arc(mouseX, mouseY, 50, 50, PI*.5, PI);
    arc(mouseX, mouseY, 50, 50, PI*1.5, PI*2);
  }
}

Interaction Lab(Moon) STPS: Candy Cat- Hanlu Zhang(Mary)

Stupid Pet Trick Show: Candy Cat

Date: September 29,2017

Instructor: Moon

Aim: Make a interesting physically interactive device which respond to a physical action or series of actions a person takes.

Ideation: When I see lucky cat in shops, shaking their paws again and again, I have a desire to high five with it, so I have the idea to make a lucky cat that can high five with people. My first idea is when you clap with the cat, a gold coin chocolate will drop down. Considering chocolate is too heavy, I decide to use candy instead, and change the name into “Candy Cat”. Also this device can give you some comfort when you are stressful or cheer you up when you are depression.

Material

  • Breadboard*1
  • Arduino*1
  • Servo*1
  • LED*2
  • 220V resistance*2
  • Touch sensor*1
  • Some wires
  • Paper and other materials

Schematics

 

Code and Connection

I choose a touch sensor to detect the action of high five, and decide to use a servo to control the candy box through a string. To make it more interesting, I add to LED lights behind the cat’s eyes.

I first code the servo part, as my servo doesn’t move according to the voltage, I can’t use the map() function, so I tried to let it write the directly. So I write:

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

But it doesn’t work, with Professor Moon’s help, I realized that I wrote

val = digitalRead(button)

if (button == HIGH) {

 myservo.write(180); }

But as I define “button=2”, the result of digitalRead is a const rather than high or low. After changing it to “If (val == HIGH), it begin to work.

Then I began coding the LED part, Then I find a problem that both servo and LED work well separately, but when they work together, as Arduino reads the code from top to bottom, it’s hard to make the LED blink when servo is moving. So I discussed this problem with Jiwon. And we found that if we write the servo code as the example “sweep”, then we can control the LED by servo’s angle. So I write:

So I can control the LED by the remainder of angle divided by 10.

Then I finished coding and connecting part, the effect is like the video below:

 

Handwork:

The basic part of my hand work is a Lucky cat and a candy can.

Than I stick a paw on right side and cut a hole to let the sensor accessible.

 

On the left side, I make a small box to contain the candy, and stick another pice of paper on the bottom, which is movable. The candy can drop from the box if the bottom open.

in the box is the servo and LEDs. For the servo, I fasten a string on it, the other side of which is on the bottom of candy can. When the servo shift, the string will be released or fasten, and the bottom of box will open or close.

For the eyes part, I cut two candy-shape holes behind the eyes, so the eyes will have the shape of candy when LED is blinking. However, as the LED is not light enough, the shape is obscure.

Then I finish all of my project, the device looks like that:

And here is the test video:

User experience

Here are two videos of people who experience it.

Reflection

This project still have many problems like the whole device is not stable, the candy can’t be too big or the box can’t support it, and the servo isn’t sticked securely in the box. Also during the show time I receive some good advice on how to make my project better. I think though this project far away from excellent, it’s my first try of IMA and through this experience, I get a deeper understanding of IMA.

#include <Servo.h>

Servo myservo;
int sensorPin = 7;
int servo = 9;
int pos = 0;
const int ledPin1 = 12;
const int ledPin2 = 13;

void setup() {
  myservo.attach(9);
  Serial.begin(9600);
  pinMode(ledPin1, OUTPUT);
  pinMode(ledPin2, OUTPUT);
}

void loop() {
  Serial.println(digitalRead(sensorPin));
  Serial.print("    ");

  if (digitalRead(sensorPin) == HIGH) {
    digitalWrite(ledPin1, HIGH);
    digitalWrite(ledPin2, HIGH);
    for (pos = 0; pos <= 180; pos += 1) {
      // goes from 0 degrees to 180 degrees
      // in steps of 1 degree
      if (pos % 10 == 5) {
        digitalWrite(ledPin1, HIGH);
        digitalWrite(ledPin2, HIGH);
      }
      else if (pos % 10 == 0) { //control the light by the remainder of angle divided by 10
        digitalWrite(ledPin1, LOW);
        digitalWrite(ledPin2, LOW);
      }
      myservo.write(pos);
      delay(10);
    }
    delay(1000);
    for (pos = 180; pos >= 0; pos -= 1) { // goes from 180 degrees to 0 degrees
      if (pos % 10 == 5) {
        digitalWrite(ledPin1, HIGH);
        digitalWrite(ledPin2, HIGH);
      }
      else if (pos % 10 == 0) {
        digitalWrite(ledPin1, LOW);
        digitalWrite(ledPin2, LOW);
      }
      myservo.write(pos);
      delay(10);
    }
    digitalWrite(ledPin1, LOW);
    digitalWrite(ledPin2, LOW);
  }
  else {
    pos = 0;
    myservo.write(pos);
    digitalWrite(ledPin1, LOW);
    digitalWrite(ledPin2, LOW);
  }
}

Interaction Lab(Moon) Recitation : Sensors (Mary)

  • Instructor: Moon
  • Partner: Zeping Fei(Phyllis)
  • Aim:
  • Choose one of the sensor to attach to my Arduino and use the data from our sensor to turn on and off an output.
  • Sensors provided:
  • Moisture Sensor
  • Vibration Sensor
  • Infrared Distance Sensor
  • Ultrasonic Ranger
  • 3-Axis Analog Accelerometer
  • Schematics
    • Just change the potentiometer into MoistureSensor
  • Exercise 1
  • We choose the Moisture Sensor, which can detect different moisture. First we simply attach the sensor to pin 9 and attach the LED to pin 13. We use the sample code blink, to test whether the sensor is  working.
  • video: light
  • Exercise 2
  • After testing, we connect a servo with the Moisture Sensor, using the circuit we practice in class.
  • Then we meet the problem of how to write my code.
  • With the help of a fellow, we first define which is myservo, which is snesor
  • Then we write which pin it’s connected with
  • Use “map” to let the servo move.
  • exercise2-1
  • We found that the servo cannot achieve 180 degree as the current is’n big enough, so we change the   map(sensorValue , 0, 1023 , 0, 180); to  map(sensorValue , 0, 600, 0, 180);
  • Than the angle became large.
  • exercise2-2
  • We also try to add a “delay(30)” after it, which make the circuit looks cute.
  • exercise2-3
Servo myservo;
int sensorPin = A0;    // select the input pin for the sensor
int servo = 9;      // select the pin for the servo

void setup() {
  myservo.attach(9);
  Serial.begin(9600);
}

void loop() {
  int sensorValue = analogRead(sensorPin);
  int angle = map(sensorValue , 0, 600, 0, 180);
  delay(1000);
  Serial.print(sensorValue);
  Serial.print("    ");
  Serial.println(angle);
  myservo.write(angle);
}

Interaction Lab(Moon) Recitation 2: Basic Circuits, Hanlu Zhang (Mary)

  • Instructor: Moon
  • Partner: Lichen Dong
  • Aim:
  • Schematics (http://ima.nyu.sh/interaction-lab/recitation-1-circuits/)
  • Exercise1

    First, we connect the breadboard and DFRduidnio , to give the circuit electric supply.

    Then we put other pieces into the circuit. When we first try, we found only yellow light is working and the switch can’t control the circuit.

So we checked the circuit, try to see whether the LED is in the right direction. Finally we figure out that when connect the DFR and lights, the pins are in the wrong order.

And we did it!

1

  • Exercise 2

The procedure of making one is really smoothly. As some part of the circuit is similar with the last one, we only moved part of the circuit.

Then we finish.

Exercise2

  • Exercise 3

We first connect it by the circuit diagram, and we found it doesn’t work

First we checked whether all the pins are in right place, then we think maybe the photoresists

 is in a wrong order. But it doesn’t. With Jiwon’s help, we find the reason that when we connect power, I connected both the two lines with ground.

Exercise3-1

Then we wonder whether we can control the voicer with photoresists

As these two need different voltage, we first remove the resist.

Then with the help of professor moon, we know that the code for light and voicer are different that voicer need a signal of a value and the signal need to change so that it can make voices, but LED only need a signal to light.

Exercise3-2

Exercise1
/*
   Traffic Light
   This code copied from the book Beginning-Arduino.
*/
int carRed = 12; //assign the car lights
int carYellow = 11;
int carGreen = 10;
int button = 9; //button pin
int pedRed = 8; //assign the pedestrian lights
int pedGreen = 7;
int crossTime =5000; //time for pedestrian to cross
unsigned long changeTime;//time since button pressed

void setup() {
  	pinMode(carRed, OUTPUT);
  	pinMode(carYellow, OUTPUT);
  	pinMode(carGreen, OUTPUT);
  	pinMode(pedRed, OUTPUT);
        pinMode(pedGreen, OUTPUT);
        pinMode(button, INPUT); 
        digitalWrite(carGreen, HIGH); //turn on the green lights
	digitalWrite(pedRed, HIGH); 
}

void loop() {
	int state = digitalRead(button);
        //check if button is pressed and it is over 5 seconds since last button press
        if(state == HIGH && (millis() - changeTime)> 5000){
               //call the function to change the lights
               changeLights();
        }
}

void changeLights() {
	digitalWrite(carGreen, LOW); //green off
	digitalWrite(carYellow, HIGH); //yellow on
	delay(2000); //wait 2 seconds
		
	digitalWrite(carYellow, LOW); //yellow off
	digitalWrite(carRed, HIGH); //red on
        delay(1000); //wait 1 second till its safe
		
	digitalWrite(pedRed, LOW); //ped red off
	digitalWrite(pedGreen, HIGH); //ped green on

	delay(crossTime); //wait for preset time period
		
	//flash the ped green
        for (int x=0; x<10; x++) {
	        digitalWrite(pedGreen, HIGH);
		delay(250);
		digitalWrite(pedGreen, LOW);
		delay(250);
         }
 	  			
        digitalWrite(pedRed, HIGH);//turn ped red on
	delay(500);

	digitalWrite(carRed, LOW); //red off
	digitalWrite(carYellow, HIGH); //yellow on	
	delay(1000);
	digitalWrite(carYellow, LOW); //yellow off
        digitalWrite(carGreen, HIGH); 

	changeTime = millis(); //record the time since last change of lights
	//then return to the main program loop
}
Exercise 2
/*
   Temperature Alarm
*/
float sinVal;            
int toneVal;
unsigned long tepTimer ;    

void setup(){ 
    pinMode(8, OUTPUT);        
    Serial.begin(9600);        
}

void loop(){ 
    int val;               
    double data;          
    val=analogRead(0);  
    data = (double) val * (5/10.24);  // convert the voltage to temperture
     
    if(data>27){        // If the temperture is over 27 degree, buzzer will alarm.  
          for(int x=0; x<180; x++){
            sinVal = (sin(x*(3.1412/180)));
            toneVal = 2000+(int(sinVal*1000));
            tone(8, toneVal);
            delay(2); 
     }   
    } else {    // If the temperturn is below 27 degree, buzzer will not alarm  
           noTone(8);           
    }
     
    if(millis() - tepTimer > 500){     // output the temperture value per 500ms
             tepTimer = millis();
             Serial.print("temperature: ");     
             Serial.print(data);              
             Serial.println("C");              
       } 
}

Exercise3
/*
  Ambient Light controlled LED 
*/
int LED = 13;                     //Led pin
int val = 0;                      

void setup(){
     pinMode(LED,OUTPUT);         
     Serial.begin(9600);        
}

void loop(){
     val = analogRead(0);         // read voltage value 
     Serial.println(val);        
     if(val<1000){                // if the value is less than 1000,LED turns off
          digitalWrite(LED,LOW);
     }else{                        // if the value is more than 1000,LED turns on
          digitalWrite(LED,HIGH);
     }
     delay(10);                   
}

exercise3-2
/*
  Ambient Light controlled LED
*/
int LED = 12;                     //Led pin
int val = 0;

void setup() {
  pinMode(LED, OUTPUT);
  Serial.begin(9600);
}

void loop() {
  val = analogRead(0);         // read voltage value
  Serial.println(val);
  if (val < 1000) {            // if the value is less than 1000,LED turns off
    tone(12, 4000);
    delay(1000);
    //digitalWrite(LED,LOW);
  } else {                       // if the value is more than 1000,LED turns on
    //digitalWrite(LED,HIGH);
    noTone(12);
  }
  delay(10);
}