Final Project User Testing : Nicholas and Shama

For our user testing we waited to include the box piece we had built to test out its functionality. We focused on the intuitiveness of the buttons and a turn pot to select choices. To help in clarity we labelled the buttons, but from our first user test, we realized that it would be even better to include an instruction sheet to summarize the main point of our stock trading program. We limited our instructions to only 4 main points that cover every feature included on the box, and we made sure that the language used was very clear and concise.

To match the clarity of the instruction sheet, we made sure to separate our main buttons with the selection knob in the center to highlight the difference of the buttons and separate their function from each other.

Finally, our user discussed that the sounds felt very interactive and reacted well with the buttons being pressed i.e cashier sound when sell all button is pressed.

By placing the speakers on the side of the box, the user also had an element of surprise as they were not typically expecting a sound to accompany their button press, making the interaction much more enthralling.

Below are some elements of our project, as well as a link to the  videos of our user testing process.

https://drive.google.com/drive/folders/12kkwuDz9aOtw_oJ0Va5f3_14Ctc2HzHd?usp=sharing

serial comm class exercises

Exercise 1 :

p5js

let serial; // variable to hold an instance of the serialport library
let portName = "/dev/tty.usbmodem101"; // fill in your serial port name here
let yPos;
let onOff=0;
let xPos = 0;

function setup() {
  createCanvas(640, 480);
  serial = new p5.SerialPort(); // make a new instance of the serialport library
  serial.on("list", printList); // set a callback function for the serialport list event
  serial.on("connected", serverConnected); // callback for connecting to the server
  serial.on("open", portOpen); // callback for the port opening
  serial.on("data", serialEvent); // callback for when new data arrives
  serial.on("error", serialError); // callback for errors
  serial.on("close", portClose); // callback for the port closing

  serial.list(); // list the serial ports
  serial.open(portName); // open a serial port
  yPos=height/2;
}

function draw() {
  background(255);
  ellipse(xPos, yPos, 50, 50); // draw the circle
  if (mouseIsPressed){
    if(mouseX<=width/2)
      onOff=1;
    else
      onOff=2;
  }else{
    onOff=0;
  }
}

// get the list of ports:
function printList(portList) {
  // portList is an array of serial port names
  for (let i = 0; i < portList.length; i++) {
    // Display the list the console:
    print(i + " " + portList[i]);
  }
}

function serverConnected() {
  print("connected to server.");
}

function portOpen() {
  print("the serial port opened.");
}

function serialEvent() {
  // read a string from the serial port
  // until you get carriage return and newline:
  let inString = serial.readLine();
  //check to see that there's actually a string there:
  if (inString.length > 0) {
    let inVal = parseInt(inString)
    xPos = map(inVal, 1023, 0, 0, width)
  }

  serial.write(onOff);
}

function serialError(err) {
  print("Something went wrong with the serial port. " + err);
}

function portClose() {
  print("The serial port closed.");
}

/* ARDUINO CODE

void setup() {
  Serial.begin(9600);
  pinMode(2, OUTPUT);
  pinMode(5, OUTPUT);
  while (Serial.available() <= 0) {
    Serial.println("0,0"); // send a starting message
    delay(300);              // wait 1/3 second
  }
}
void loop() {
  while (Serial.available() > 0) {
    // read the incoming byte:
   int inByte = Serial.read();
    switch (inByte) {
      case 0:
        digitalWrite(2, LOW);
        digitalWrite(5, LOW);
        break;
      case 1:
        digitalWrite(2, HIGH);
        break;
      case 2:
        digitalWrite(5, HIGH);
        break;
    }
    int sensorValue = analogRead(A0);
    Serial.print(sensorValue);
    Serial.print(",");
    sensorValue = analogRead(A1);
    Serial.print(sensorValue);
    Serial.println();
  }
}

*/

Arduino

void setup() {
  Serial.begin(9600);
  while (Serial.available() <= 0) {
    Serial.println("0"); // send a starting message
    delay(300);              // wait 1/3 second
  }
}
void loop() {
  while (Serial.available() > 0) {
    // read the incoming byte:
    int inByte = Serial.read();
    int sensorValue = analogRead(A0);
    Serial.print(sensorValue);
    Serial.println();
  }
}

Exercise 2:

p5js

let serial; // variable to hold an instance of the serialport library
let portName = "/dev/tty.usbmodem101"; // fill in your serial port name here
let yPos;
let onOff=0;
let xPos = 0;
let outVal = 0;

function setup() {
  createCanvas(640, 480);
  serial = new p5.SerialPort(); // make a new instance of the serialport library
  serial.on("list", printList); // set a callback function for the serialport list event
  serial.on("connected", serverConnected); // callback for connecting to the server
  serial.on("open", portOpen); // callback for the port opening
  serial.on("data", serialEvent); // callback for when new data arrives
  serial.on("error", serialError); // callback for errors
  serial.on("close", portClose); // callback for the port closing

  serial.list(); // list the serial ports
  serial.open(portName); // open a serial port
  yPos=height/2;
}

function keyReleased() {
  if (keyCode === LEFT_ARROW) {
    outVal = max(outVal - 10, 0) ;
  } else if(keyCode === RIGHT_ARROW) {
    outVal = min(outVal+10, 255);
  }
  return false;
}

function draw() {
  background(255);
  ellipse(xPos, yPos, 50, 50); // draw the circle
  if (mouseIsPressed){
    if(mouseX<=width/2)
      onOff=1;
    else
      onOff=2;
  }else{
    onOff=0;
  }
}

// get the list of ports:
function printList(portList) {
  // portList is an array of serial port names
  for (let i = 0; i < portList.length; i++) {
    // Display the list the console:
    print(i + " " + portList[i]);
  }
}

function serverConnected() {
  print("connected to server.");
}

function portOpen() {
  print("the serial port opened.");
}

function serialEvent() {
  // read a string from the serial port
  // until you get carriage return and newline:
  let inString = serial.readLine();
  serial.write(outVal);
}

function serialError(err) {
  print("Something went wrong with the serial port. " + err);
}

function portClose() {
  print("The serial port closed.");
}

/* ARDUINO CODE

void setup() {
  Serial.begin(9600);
  pinMode(2, OUTPUT);
  pinMode(5, OUTPUT);
  while (Serial.available() <= 0) {
    Serial.println("0,0"); // send a starting message
    delay(300);              // wait 1/3 second
  }
}
void loop() {
  while (Serial.available() > 0) {
    // read the incoming byte:
   int inByte = Serial.read();
    switch (inByte) {
      case 0:
        digitalWrite(2, LOW);
        digitalWrite(5, LOW);
        break;
      case 1:
        digitalWrite(2, HIGH);
        break;
      case 2:
        digitalWrite(5, HIGH);
        break;
    }
    int sensorValue = analogRead(A0);
    Serial.print(sensorValue);
    Serial.print(",");
    sensorValue = analogRead(A1);
    Serial.print(sensorValue);
    Serial.println();
  }
}

*/

Arduino

void setup() {
  Serial.begin(9600);
  while (Serial.available() <= 0) {
    Serial.println("0"); // send a starting message
    delay(300);              // wait 1/3 second
  }
}
void loop() {
  while (Serial.available() > 0) {
    // read the incoming byte:
    int inByte = Serial.read();
    analogWrite(3, inByte);
    Serial.print("ye");
    Serial.println();
  }
}

Exercise 3:

p5js

let serial; // variable to hold an instance of the serialport library
let portName = "/dev/tty.usbmodem14201"; // fill in your serial port name here
let velocity;
let gravity;
let position;
let acceleration;
let wind;
let drag = 0.99;
let mass = 50;
let hDampening;
let inVal = 0;
let outVal = 0;

function setup() {
  createCanvas(640, 360);
  noFill();
  position = createVector(width/2, 0);
  velocity = createVector(0,0);
  acceleration = createVector(0,0);
  gravity = createVector(0, 0.5*mass);
  wind = createVector(0,0);
  hDampening=map(mass,15,80,.98,.96);
  serial = new p5.SerialPort(); // make a new instance of the serialport library
  serial.on("list", printList); // set a callback function for the serialport list event
  serial.on("connected", serverConnected); // callback for connecting to the server
  serial.on("open", portOpen); // callback for the port opening
  serial.on("data", serialEvent); // callback for when new data arrives
  serial.on("error", serialError); // callback for errors
  serial.on("close", portClose); // callback for the port closing
    serial.list(); // list the serial ports
  serial.open(portName); // open a serial port
}

function draw() {
  background(255);
  if (!keyPressed){
    wind.x=0;
    velocity.x*=hDampening;
  }
  applyForce(wind);
  applyForce(gravity);
  velocity.add(acceleration);
  velocity.mult(drag);
  position.add(velocity);
  acceleration.mult(0);
  ellipse(position.x,position.y,mass,mass);
  if (position.y > height-mass/2) {
      velocity.y *= -0.9;  // A little dampening when hitting the bottom
      position.y = height-mass/2;
    }
 outVal = position.y >= height-mass/2-5 ? 255 : 0;
 wind.x = map(inVal, 0, 1023, -5, 5)*hDampening;
}

function applyForce(force){
  // Newton's 2nd law: F = M * A
  // or A = F / M
  let f = p5.Vector.div(force, mass);
  acceleration.add(f);
}

function keyPressed(){
  if (key==' '){
    mass=random(15,80);
    position.y=-mass;
    velocity.mult(0);
  }
}





function printList(portList) {
  // portList is an array of serial port names
  for (let i = 0; i < portList.length; i++) {
    // Display the list the console:
    print(i + " " + portList[i]);
  }
}

function serverConnected() {
  print("connected to server.");
}

function portOpen() {
  print("the serial port opened.");
}

function serialEvent() {
  // read a string from the serial port
  // until you get carriage return and newline:
  let inString = serial.readLine();
  inVal = parseInt(inString);
  serial.write(outVal);
}

function serialError(err) {
  print("Something went wrong with the serial port. " + err);
}

function portClose() {
  print("The serial port closed.");
}

Arduino

void setup() {
  Serial.begin(9600);
  while (Serial.available() <= 0) {
    Serial.println("0"); // send a starting message
    delay(300);              // wait 1/3 second
  }
}
void loop() {
  while (Serial.available() > 0) {
    // read the incoming byte:
    int inByte = Serial.read();
    analogWrite(3, inByte);
    int sensorValue = analogRead(A0);
    Serial.print(sensorValue);
    Serial.println();
  }
}

 

Nicholas and Shama – Flute Box

For this assignment we decided to use pressure sensors to create a synth sound when pressed. We placed our sensors on a box and programmed everything on P5js and connected it with Arduino using serial control.

After getting our sound to work, we quickly realized that our chosen notes (c4,E4,G4,C5) more closely resemble a digital flute. We then aligned our sensors to the side of the box to mimic the setup of a flute, but in the medium of a box. Of course, our flute box has no air involved but the pressure added to the sensor does change the intensity of the sound produced which is pretty similar to how a flute intrinsically works.

We controlled the flow of data with a variable controlled with a switch, and only sent data to p5js if the switch was toggled using the sample code from class.

 while (Serial.available() > 0 && toggled) {

      // read the incoming byte:

    int analogReading = analogRead(FORCE_SENSOR_PIN);

    int analogReading1 = analogRead(FORCE_SENSOR_PIN1);

    int analogReading2 = analogRead(FORCE_SENSOR_PIN2);

    int analogReading3 = analogRead(FORCE_SENSOR_PIN3);

    Serial.print(analogReading);

    Serial.print(",");

    Serial.print(analogReading1);

    Serial.print(",");

    Serial.print(analogReading2);

    Serial.print(",");

    Serial.print(analogReading3);

    Serial.print("\n");

    Serial.println();

  }

 

To output the sound input by the sensors, we created an array of MonoSynth instances, in which each instance controlled the note being played and the volume.

monoSynth = [

      new p5.MonoSynth(),

      new p5.MonoSynth(),

      new p5.MonoSynth(),

      new p5.MonoSynth(),

  ];

  notes = [‘C4', 'E4', 'G4', 'C5']

function playSynth(i, val) {

  userStartAudio();

  let intval = int(val)

  let note = notes[i];

  // note velocity (volume, from 0 to 1)

  let velocity = intval<100?0:map(intval, 0, 1023, 0, 1);

  // time from now (in seconds)

  let time = 0;

  

  // note duration (in seconds)

  let dur = 1/6;

  if(intval > 100)

    monoSynth[i].play(note, velocity, time, dur);

}

if (inString.length > 0) {

    let sensors = split(inString, ","); // split the string on the commas

    if (sensors.length == 4) {

      // if there are three elements

      for(let i=0; i < sensors.length; i++){

        playSynth(i, sensors[i]);

      }

    }

  }

 

Since the velocity parameter in monoSynth.play() is continuous, we were able to map the input value to a value between 0 and 1, so when the user presses a key heavier, the sound plays louder.

Distance Sensor

For this assignment I had a very similar idea to Maimuna’s post about a car sensor which is usually what comes to mind when thinking of using an ultrasonic sensor. My project is also a car sensor, I just added more LED’s to fit my narrative of a warning meter which should go from “On” to red , to orange, then red proximity (in 2 intervals = 2 LED’s for each color).

I decided to use two LEDs for each level to indicate the different values that represent proximity which go from around 4- 4o, until the range is out of the ultrasonic sensor. Essentially, the last red LED will light up at around an  output of 5, which means the car will hit the wall/object or is dangerously close to it.

I only used 1 white LED because it is only there to indicate that the car is within the range of the sensor to begin determining proximity.

One Issue that I had while working on this would be the LED’s. The first time I hooked everything up the LED’s were noticeably dim, this was not due to the resistors (I used 270 Ohms) but the LED’s themselves. I ended up switching out the LEDs I grabbed from the lab with the ones we had in the box which worked much more brighter as they have a voltage drop of 2.0-2.4v (unlike the ones in the lab, (I still don’t know their voltage drop).

For my demo, I just made a car from a food box and some tires I just taped to the sides.

Light Sensor

For my circuit, I decided to use an LDR, because to me touch-less circuits oftentimes include elements that could rely on sound or on light. I used a 2222 Transistor to switch the process of having my led light up when there is light, which felt somewhat useless. Instead, I have my circuit configured in a way that inverses this process and makes my LED light up when the LDR is not met with light (detects darkness).

The use of this circuitry could easily be attributed to smart lighting systems which turn the light on when it is dark. I was initially inspired by this process of smart systems as I have them integrated all over my room. It was very interesting looking at a very simplified version of this process and making it myself with the basic mechanics.

In this demo I use my hands to create the shadow over the LDR, but you could use anything to create a shadow, which is why I would say my circuit is hands-free, as no hand contact comes to the circuit for the light bulb to turn on, only shadow/light.

https://drive.google.com/file/d/1tnnrFYYkjPxqjYdOkOOp6tNWB11C8N0z/view?usp=sharing

 

Shama’s Midterm: Guitar Hero

By looking at the time this is posted, you can tell there were a lot of last minute tedious fixes I had to make to make my game work smoothly. I will begin with the details that surprisingly took the longest. After my first draft, I noticed that the space in between my menu buttons (easy,medium, hard etc.) were clickable, and this was the same for the x-axis of my buttons. The issue was that the buttons had a very badly adjusted offset, I fixed this through trial and error (easy but extremely tedious). My next issue came when I realized that my game didn’t end after the songs ended, I had to create an if statement for this (pretty easy fix). After thinking everything was going well, I then noticed that if the window was resized, everything would get thrown off course, so I aligned each elements position to be relative to the next so that it can be responsive to any window size changes.

After going through these tedious changes, I had to start focusing on the actual songs and the creation speed of my arrows. I wanted the songs and the arrows to be in sync almost. While I could’ve calculated this more technically using each song’s bpm, I decided that based off the song’s tempo, I would assign them to the level difficulties. Starting from there the songs and the symbols were not so out of sync, but this wasn’t enough. I took a more tedious route here by adjusting the speed and vertical distance of my arrows to suite each song and level difficulty, if you pay close attention a majority of the arrows will perfectly line up with the song’s beats.

My biggest issues with this project was understanding how to rework my code in a simpler and cleaner way, I kind of took the long messy route because its what I understood best.

I really enjoyed making my own designs and deciding which interaction to use based on what I already know from playing different versions of guitar Hero. I previously experimented with using a sound response for each key pressed on time, but that ended up clashing with the music in the background and sounding awfully annoying, so I decided to go with a box that lights up green when the key is detected to be pressed in the proper range using the splice function. The screen will flash red otherwise.

I also decided to make the game over screen appear if 6 keys were missed in a row, I chose this number after testing it on my friend who said “6 missed keys are fair enough to lose the game, but also challenging enough to want to play again”.

Overall, I learned tremendously a lot from working on this game and by taking the long route, I began to understand what shortcuts I can begin to make instead. In the future, I would like to be able to fluently implement faster code, instead of taking 10 lines to do one thing I’d like to be able to do it in 1.

And finally, here is my Midterm project !!!!! (feel free to resize the window😎 )

Shama Midterm Progress

For my midterm project I decided to remake my own design version of Guitar Hero. The game functions are straightforward and the concept is laid out, so all I have to focus on is actually coding it in p5js and designing my own UI. I firstly began with a reference of the functions I’d like to remake, my main point of inspiration is from this code by Joseph Aronson.

When testing out this version of the game I instantly knew what parts I liked and what I would eventually change. The main factors that worked well in my opinion would be the interactivity of pressing the buttons or missing them (when you press the border lights up green, when you miss the screen flashes red). However, the buttons ZXCV felt very uncomfortable for my hand to quickly tap on the keys, which goes against the original idea of Guitar Hero which came in the form of ergonomic keys on a toy guitar handle.

For this reason I decided to remake my interface with only three keys, and I chose to use the up, left, and right keys since they felt the most comfortable to rest my hand on.

To take this idea a step further, I will also be adding different music to the different levels that will correspond to how fast the user must respond with a matching key i.e an the extreme level would have an Eminem Rap song as opposed to the easy level that might have a slow song.

Additionally, I will add a sprite character playing the guitar to the side of the screen which will be programmed to stop/play according to the music playing or not (when the user loses, the sprite will not be moving).

Currently, I have customized my own interface according to the three buttons I want to use, and am working on adding sound (which is not working in the way I want it to as of yet). I have also made my starting title/menu screen which is working, and when the user chooses the level “easy” the screen successfully transitions to the game screen. I still have to add my moving sprite on the game screen and I need to figure out how my key output sounds will connect to the music I insert. There is still a lot of fixes I have to make, but for now I’m very happy with the progress.

Assignment 4: Generative Text

For this assignment I began with my first iteration which just basically drew out my desired shape onto my text outline using texttopoint. I followed a similar theme from my past assignments of working with rainbow squares, just because I like to explore how I can manipulate the movement of this same shape and its random colors to make different generative art. I also played with using cosine to see how differently my rects would move when I began adding interaction

My next step was adding interaction. For this part, I mainly followed professor’s code. I changed the values so it can correspond to an outcome that I was aiming for which is to be rigid in its movements, as the rectangles on their own feel quite stiff, so I wanted the rigidness to be consistent. After manipulating the values and adding some of my own math, I ended up with this final outcome:

I ended up removing the value that causes the rectangles to move slightly, because I liked how it looked in place ( like a glitch effect). I also made my rectangles smaller since the word was fussy to look at when everything was too close to each other. I also attempted to reuse cosine in noise so that when the mouse hovers over the letters, the rectangles expand in a cool pattern.

Assignment 3: Slime Blocks

For this assignment, I took inspiration from the shape and motion of the slime block in Minecraft.

The main features I wanted to replicate were the bouncing motions, the size change, and the transparency. I also added click input just to make the art more interactive within the p5js context. My first iteration did not have any class or array and just had the basic idea laid out, starting with transparent squares that are random in size, being placed in repetition following the mouse xy location while pressed.
Going from there, I had to make a class for my rectangle which would have a constructor that holds all the features I want to attribute to my rectangles such as: size, color, speed, location and gravity.

To recreate the bouncing motion, I incorporated the loop from this code. I then arranged each function within my class (display and move) to instantiate the bouncing movement and rectangle display within each rectangle that is created going through my array rectangles [].
After understanding the basics of organizing my class and functions to create the bouncing outcome I was looking for, I decided to play with the gravity variable and see what would happen if I used noise instead.

For my last iteration, I replaced gravity with noise which visually doesn’t make much of a difference. However, at a closer look, the bounce of the rectangles in relation to each other look much more organic in comparison to using gravity, whilst still being random as well.

Assignment 2

Before beginning this assignment, I was watching a ton of videos online. The loading symbol in the shape of a circle which would show up when the video was buffering stood out to me a lot. This shape and movement stayed in mind while I began assignment 2, and so I decided to center my work around that.

I was able to recreate the movement of the shape using a for loop by changing the length of the arc in each iteration. To mimic the multiplicity of speeds a loading bar has depending on internet connectivity/buffering speed, I also decided to make each arc move in different speeds ranging from (-2,2).

Since 1 arc wasn’t achieving a visually fulfilling motion, I decided to make multiple arcs using a for loop as well.

One challenge I faced for this project was making the ends of my arc lines  fade off just like in the reference image above. In order to make up for that, I managed to successfully apply the lerp color gradient background which I attempted to use for Assignment 1 but was unable to, this time it worked well as part of my process.

Credits for the lerp gradient