Project 1 – Intro to Physical Computing: Student Work https://courses.ideate.cmu.edu/60-223/f2018/work Intro to Physical Computing: Student Work Sun, 16 Dec 2018 16:38:47 +0000 en-US hourly 1 https://wordpress.org/?v=4.9.25 Surprise: The Musical Bug https://courses.ideate.cmu.edu/60-223/f2018/work/surprise-the-musical-bug/ https://courses.ideate.cmu.edu/60-223/f2018/work/surprise-the-musical-bug/#respond Thu, 27 Sep 2018 18:11:56 +0000 https://courses.ideate.cmu.edu/60-223/f2018/work/?p=4114 THE MUSICAL BUG

Front View of the Musical Bug

Closeup of Musical Buttons

Suprise Flag

Musical Bug as Suprise is Triggered

Musical Bug After Suprise

Narrative

This robot looks like a car with piano keys, making the user think that the songs and wheels might work together somehow. However, if the user hits a specific note the robot enters an infinite loop of a theme song and a flag breaks the top of the robot and shows a surprised face. This also surprises the user and renders the piano unusable. After that point, the “Bug” breaks and the keyboard no longer works.

Process & Discussion

Initially, the piano was designed to hide the wheels of the robot and if the user hit the wrong note the robot would run away. However, after much trial and error with motors that didn’t work and wires that weren’t connecting, we decided that movement was an unreliable source to depend on for our surprise. Thus, we decided to still incorporate the original structure but come up with a different idea for the surprise. The flag still gives the same idea as the robot running away as well as being completely unexpected. Because the robot looks so complex, the result of such a simple and useless reaction is surprising.

Some design challenges we had was how to deliver the surprise. The tissue paper was used to have an easy barrier for the flag to break. This component was decided after testing multiple different fabrics and materials such as regular paper, tape, thin fabric, paper towels, and a lid. We decided that the most reliable barrier was to use tissue paper to ensure that the flag would be able to break through. Another consideration was the form of the device. After experimenting with paper, plastic boxes, and different forms of cardboard boxes, we decided to stick with a regular cardboard box to keep the mystery of the device.

It was challenging to come up with a good idea for this project, and we ended up thinking about things we would be surprised seeing ourselves. We also learned to test motors before attaching them to the robot to ensure that they will work. Moving forward, we could better this project by concealing the surprise flag so that it does not stick out the bottom of the device. Or, to encourage the idea that the device is a piano, we could make the form of the device mimic a traditional piano. Thus, after a note or sequence of notes is pressed, the device would pop a flag out and then play an endless loop of a song. We also could have thought of a more unexpected thing that a piano could do such as run away.

Originally, we worked with two motors and concentrated on building a structure that encloses the wheels and wires. We ran into multiple issues with this. The biggest were: 1- there was too much friction between the ground and anything that touched it that was not the wheels. 2- the 2 motors seemed too weak to carry the entire components.

Naturally, our next step was to build the entire structure to see how much it would weigh and using a larger power source, and stronger motors. We kept tweaking the box and the amount of material that touched the ground. Still no luck. It was too heavy and the friction was too high.

This is when we decided to use 4 wheels and 4 motors, that way all the objects touching the ground were movable, which reduced the friction by a lot. At this point, the robot functioned the way it was supposed to and moved really well. However, when we came back to our next work session to build the encasement for the robot, we realized two out of four of the motors were not working. One was just not working and the other had a faulty wire. We soldered new wires to the motor, but it still was not working properly. We replaced the other motor with a working one, and tried to make-do with 3/4 working motors, but the movement was not as smooth as before. After a lot of trial and error, we got to a point where 2/4 motors were not reliable, and one motor would occasionally work and occasionally not. At that point, we decided to switch courses and try something else that is surprising. We already had the wheels built and wired, so we decided to use that as an optical illusion, making the users think it is a functional moving robot with wheels.

Schematic

Schematic for Musical Bug

Code:

// Musical Bug

// Jenny Han
// Ghalya Alsanea

// This code needs an Arduino, servo, speaker, and 7 buttons.
// This device assigns each button to a note and plays music.
// If the button G is pressed, the rest of the buttons become 
// disabled and the device releases a flag while playing a song
// on repeat.

#include<Servo.h>
Servo servo1;

const int SERVO;
const int SERVOPIN = 11;
int SPEAKER = 9;

//Setting the tones for the scale

int BUTTONC = 8;
int C = 261;

int BUTTOND = 7;
int D = 294;

int BUTTONE = 6;
int E = 329;

int BUTTONF = 5;
int F = 349;

int BUTTONG = 4;
int G = 392;

int BUTTONA = 3;
int A = 440;

int BUTTONB = 2;
int B = 492;



void setup() {
  //initialize inputs and outputs
  pinMode(SPEAKER, OUTPUT);

  pinMode(BUTTONC,INPUT);
  pinMode(BUTTOND,INPUT);
  pinMode(BUTTONE,INPUT);
  pinMode(BUTTONF,INPUT);
  pinMode(BUTTONG,INPUT);
  pinMode(BUTTONA,INPUT);
  pinMode(BUTTONB,INPUT);


  servo1.attach(SERVOPIN);
  servo1.write(0);
  Serial.begin(9600);
}

void loop() {
  int buttonC = digitalRead(BUTTONC);
  int buttonD = digitalRead(BUTTOND);
  int buttonE = digitalRead(BUTTONE);
  int buttonF = digitalRead(BUTTONF);
  int buttonG = digitalRead(BUTTONG);
  int buttonA = digitalRead(BUTTONA);
  int buttonB = digitalRead(BUTTONB);
  

//play music except for button G, the sequence starts

  if (buttonC) {
    tone(SPEAKER,C,100); //C 
    Serial.println("pressed!");
  } 
  if (buttonD) {
    tone(SPEAKER,D,100); //D
  }
  if (buttonE) {
    tone(SPEAKER,E,100); //E
  }
  if (buttonF) {
    tone(SPEAKER,F,100); //F
  }
  //if note hit then play song and release flag
  if (buttonG) {
    tone(SPEAKER,G,100); //G
    Serial.println("do a song!");
    servo1.write(180);
    song();
    
  }
  if (buttonA) {
    tone(SPEAKER,A,100); //A
  }
  if (buttonB) {
    tone(SPEAKER,B,100); //B
  }
  
}

//song sequence that plays when hit a certain note
void song()
{
    while (true) 
    {
      tone(SPEAKER,F,100); //F
      delay(300);

      
      tone(SPEAKER,E,100); //E
      tone(SPEAKER,F,100); //F
      delay(200);
      tone(SPEAKER,A,100);
      tone(SPEAKER,B,100); //F
      delay(400);
      tone(SPEAKER,D,100);
      delay(200);
      tone(SPEAKER,C,100);
      delay(200);
      tone(SPEAKER,E,100);
      delay(100);
      tone(SPEAKER,G,100);
      delay(200);
      tone(SPEAKER,A,100);
      delay(200);
      tone(SPEAKER,A,100);
      delay(300);
      tone(SPEAKER,F,100);
      
  
      
    }
}

 

]]>
https://courses.ideate.cmu.edu/60-223/f2018/work/surprise-the-musical-bug/feed/ 0
Surprise: Car That Runs Away https://courses.ideate.cmu.edu/60-223/f2018/work/surprise-car-that-runs-away/ https://courses.ideate.cmu.edu/60-223/f2018/work/surprise-car-that-runs-away/#respond Tue, 25 Sep 2018 18:34:10 +0000 https://courses.ideate.cmu.edu/60-223/f2018/work/?p=4078

This photo captures the front view of the car, which shows the green button on top, the LED “headlights”, and the front flap (the black rectangle containing green details and the LEDs) which lifts to allow access to the battery and the Arduino.

This photo shows the activated car, with its headlights on. This activation is caused by the hand over the photosensor inside the button, which has detected a lower level of light.

This photo captures the back view of the car, where another angle of the button can be seen.

DSC_0094

The car has a green button on top of it. When someone goes to press the button, a sensor in the button detects a change in the amount of light, and the car “runs” away. This is similar to our inspiration of a cat running away from a human that wants to pet it.

At this point, the wheels were being wired into the breadboard, along with their drivers. The front flap of the car and the wired button are also visible in this picture. This was during the early stages of configuring the electrical parts.

 

Here, the car was starting to be constructed. All of the wheels were attached to the base, and the walls were being put up, allowing the electrical parts to sit inside the vehicle. The top was made around the button, out of cardboard, in order to ensure it would sit correctly and allow the photosensor to be activated.

 

At this point, construction was nearly complete, with the exception of the front of the car. We made the design choice to have the front go out and become a flap the battery and Arduino visible in the front left part of the car could be accessible, in case we needed to change the code.

/**
*
* Linda Xia
* Kye Stapleton-Gray
*
* Project 1: Surprise!
*
* This Arduino "surprise" comes in the form of a toy-sized car, artfully made from popsicle sticks
* hot glued together. It contains a green "Push Me!" button, which is aimed to entice the user to
* tap it to turn it on. Little do they know that the device is already on, and the photoresistor
* hidden within the button alerts the little toy car to awaken and swiftly scamper away.
*
*/

const int back_in_1 = 8;
const int back_in_2 = 9;
const int back_in_3 = 4;
const int back_in_4 = 5;

const int front_in_1 = 11;
const int front_in_2 = 12;
const int front_in_3 = 2;
const int front_in_4 = 3;

const int led_1 = 13;
const int led_2 = 10;

const int sensitivity = 550;

void setup() {
Serial.begin(9600);

// Controls the back wheels DC motor output
pinMode(back_in_1, OUTPUT);
pinMode(back_in_2, OUTPUT);
pinMode(back_in_3, OUTPUT);
pinMode(back_in_4, OUTPUT);

// Controls the front wheels DC motor output
pinMode(front_in_1, OUTPUT);
pinMode(front_in_2, OUTPUT);
pinMode(front_in_3, OUTPUT);
pinMode(front_in_4, OUTPUT);

// The LED "eyes" of the little toy car
pinMode(led_1, OUTPUT);
pinMode(led_2, OUTPUT);

pinMode(A0, INPUT);
}

void loop() {

// Read the photoresistor value.
int photoValue = analogRead(A0);

/*
* If the photoresistor value dips below a certain sensitivity level, the little toy car
* is alerted that a human is near due to the change in light.
*/

if (photoValue < sensitivity) {
digitalWrite(back_in_1, HIGH);
digitalWrite(back_in_2, LOW);
digitalWrite(back_in_3, HIGH);
digitalWrite(back_in_4, LOW);

digitalWrite(front_in_1, HIGH);
digitalWrite(front_in_2, LOW);
digitalWrite(front_in_3, HIGH);
digitalWrite(front_in_4, LOW);

digitalWrite(led_1, HIGH);
digitalWrite(led_2, HIGH);
delay(1000);
}

// Otherwise, if there is no danger -- uh, human -- nearby, the car will be napping.
else {
digitalWrite(back_in_1, HIGH);
digitalWrite(back_in_2, HIGH);
digitalWrite(back_in_3, HIGH);
digitalWrite(back_in_4, HIGH);

digitalWrite(front_in_1, HIGH);
digitalWrite(front_in_2, HIGH);
digitalWrite(front_in_3, HIGH);
digitalWrite(front_in_4, HIGH);

digitalWrite(led_1, LOW);
digitalWrite(led_2, LOW);

}
}

 

 

For future improvements, it would be useful to make something like a knob on the device that could adjust the sensitivity of the photoresistor based on the brightness of the room, since variable lighting in the classroom caused issues in our demonstration. To make the device more “cat-like”, we could have allowed the car to be moving already, and speed up when a hand goes to press the button. It would have also been better to allow the button to actually be pressed, since we weren’t expecting for someone to actually try to press it hard and quickly enough that the sensor was set off.

Some challenges were that working with DC motors was a risky move, because neither of us had worked with them before, and extra hours were spent soldering threaded wire to the motors to create electrical connections, and soldering the drivers together. It was also difficult to find the right battery to power the motors, the drivers, and the Arduino. We ended up using 4 AA batteries and a 9V battery. It was confusing wiring those up because the wheels kept acting up or not moving at different points.

When constructing the car, we wanted to make the function as discreet as possible so no one would guess the surprise. This made us construct a closed box, with no way of peeking inside at the parts.

The electrical components we had already learned about in class were easy to connect, like the photoresistor and the LEDs. The scope of the project was right, since we were able to produce a polished project without spending crammed hours at the end. In the future, we would love to incorporate more complex and sensitive sensors, motors, and other electrical accessories to create a less direct replica of an already existing being (the cat). Some of the projects we saw from others in the class inspired us to be more creative, like the slowly moving package box, and the caring-actions-turned-violent plant watering project.

]]>
https://courses.ideate.cmu.edu/60-223/f2018/work/surprise-car-that-runs-away/feed/ 0
Surprise: Plant Care https://courses.ideate.cmu.edu/60-223/f2018/work/surprise-plant-care/ https://courses.ideate.cmu.edu/60-223/f2018/work/surprise-plant-care/#respond Tue, 25 Sep 2018 18:14:26 +0000 https://courses.ideate.cmu.edu/60-223/f2018/work/?p=4021

The contraption in action

The final contraption without solenoid power source: A beaker rests on top of a wooden box with a moisture sensor and a plant in a cup is placed on the side of the box, covering the solenoid. 9V battery is used to power the Arduino in the box.

The tragic aftermath: water is added to the beaker, the solenoid has knocked over the plant cup.

Solenoid needs 12 volts of power to run

This is a box. Not just an ordinary box, but a tiny wooden box with a glass beaker on top, a potted plant to its side, and electronics on the inside. When the user pours water into the beaker, a sensor that is in the beaker detects that there is water in the beaker. This then triggers the solenoid (a small device that punches out a small “arm” with sudden force) which knocks the plant over. The plant must be resting right on the side of the box to both cover the solenoid and be close enough so that the solenoid can reach it.

The process

A sketch of the box with measurements for laser cutting. We wanted to make the device as small as we could so every hole and width was measured carefully.

We couldn’t find out why our code wasn’t working to power the solenoid but it turned out to be a wiring problem instead.

The parts that are on the inside of the box, before we made the box.

Schematic

Code

int val = 0; //value for storing moisture value 
const int SENSORPIN = A0;//Declare a variable for the soil moisture sensor 
int SENSORPWR = 7;//Variable for Soil moisture Power
const int SOLENOID = 3;

void setup() 
{
  Serial.begin(9600);   // open serial over USB

  pinMode(SENSORPWR, OUTPUT);//Set Sensor power and solenoid as an OUTPUT
  pinMode(SOLENOID, OUTPUT);
  pinMode(SENSORPIN, INPUT);//sensor pin reads input
  digitalWrite(SENSORPWR, LOW);//Set to LOW so no power is flowing through the sensor
  digitalWrite(SOLENOID, LOW);
}

void loop() 
{
  int moisture = readMoist();
  Serial.print(&quot;Moisture = &quot;); //test that moisture sensor is working   
  //get soil moisture value from the function below and print it
  Serial.println(moisture);
  if(moisture &gt; 800){//turn solenoid on if moisture detected, but after 3 seconds
    delay(3000);
    digitalWrite(SOLENOID, HIGH);
    Serial.println(&quot;solenoid on&quot;);
    delay(50);
    digitalWrite(SOLENOID, LOW);
    Serial.println(&quot;solenoid off&quot;);
  }
  
  delay(1000);//take a reading every second
}
//This is a function used to get the moisture content
int readMoist()
{

    digitalWrite(SENSORPWR, HIGH);//turn SENSORPWR &quot;On&quot;
    delay(10);//wait 10 milliseconds 
    val = analogRead(SENSORPIN);//Read the SIG value form sensor 
     digitalWrite(SENSORPWR, LOW);//turn SENSORPWR &quot;Off&quot;
    return val;//send current moisture value
}

 

 Description

The first challenge we had to face was thinking about what we wanted to build for our project. Our concept was to make something that appeared benign and harmless but had the opposite effect. We thought of “harming” a plant because plants are things that are to be cared for, so you would naturally want to nurture it. We came up with the idea of appearing to care for the plant by giving it water, but the act of watering would punch the plant and knock it over.

In order to do this, we needed a moisture sensor and a solenoid. We chose to work with a solenoid because of its speed and power. However, the solenoid required 12V of power, so we needed an external power source which was big and bulky and detracted from the aesthetic of the piece a little bit. The wiring was a little difficult, and we had to be extra careful because we were working with the 12V power source. Writing the code wasn’t difficult, but we couldn’t figure out what was wrong with it when we ran it. It turned out there was nothing wrong with the code, but we had missed connecting one of the ground wires.

One thing I would modify is to only have the solenoid go off once after the water is poured into the cup, but it could be repeated without having to press restart. The solenoid just kept going off repeatedly 3 seconds after detecting moisture (we created this delay to not have the solenoid go off immediately) until it stopped detecting moisture, which maybe wasn’t the best. It is an easy fix: I could tweak the code so that it keeps track of how many times the solenoid went off, stop after one, and reset the count when the moisture sensor gets back to 0.

The box was laser cut and carefully measured to have all the holes aligned precisely, and be as compact as possible. The potted plant sits on a thin piece of wood so that the solenoid can easily and swiftly knock it over. However, this instability cause some accidental spills. The cup with the plant is also mostly empty with soil only on the very top, again to make it light. We also added some wires on the outside connecting the sides to the top to make it look like the beaker was going to do something, but the wires were not connected to anything on the inside.

]]>
https://courses.ideate.cmu.edu/60-223/f2018/work/surprise-plant-care/feed/ 0
Surprise: Wake Up! https://courses.ideate.cmu.edu/60-223/f2018/work/surprise-wake-up/ https://courses.ideate.cmu.edu/60-223/f2018/work/surprise-wake-up/#respond Tue, 25 Sep 2018 16:09:46 +0000 https://courses.ideate.cmu.edu/60-223/f2018/work/?p=3905

The “alarm clock”

Clock display

Top of the box with button and some circuitry showing inside

the soldering of the project

Project Description:

The screen on the front displays the time. The box will make a buzzer sound when the display reaches “8:30:0” and there is a button on the top of the box that silences the alarm. The display of time now increases much faster than before.

#include <Adafruit_LiquidCrystal.h>

#include <Wire.h>
#include <LiquidCrystal_I2C.h>

LiquidCrystal_I2C lcd(0x3F,16,2);

int hourTime = 8;
int minTime = 29;
int secTime = 55;
int currDelay = 1000;

bool alarmOn = false;

const int BUZZER_PIN = 13;
const int SNOOZE_PIN = 10;

void setup()
{
Serial.begin(9600);
lcd.begin();
lcd.backlight();
pinMode(BUZZER_PIN, OUTPUT);
pinMode(SNOOZE_PIN, INPUT);
digitalWrite(BUZZER_PIN, LOW);
}

void loop() {
lcd.setCursor(0,0);
DisplayDateTime();
Serial.println(alarmOn);

if(hourTime == 8 &amp;&amp; minTime == 30 &amp;&amp; secTime == 0){
alarmOn = true;
digitalWrite(BUZZER_PIN, HIGH);
Serial.println("turn on alarm");
}

if(digitalRead(SNOOZE_PIN) == LOW){
alarmOn = false;
digitalWrite(BUZZER_PIN, LOW);
currDelay = 200;
Serial.println("speed up");
}

delay(currDelay);
lcd.clear();
}

void DisplayDateTime(){
secTime += 1;
if(secTime == 60){
secTime = 0;
minTime += 1;
}
if(minTime == 60){
minTime = 0;
hourTime += 1;
}
lcd.print(hourTime);
lcd.print(":");
lcd.print(minTime);
lcd.print(":");
lcd.print(secTime);
}

 

start constructing the wire conncection with a buzzer

working through external libarary of the clock

LiquidCrystal  screen works!

running test

laser cut a box for it
inside the box

testing (change the button)

Schematic

testing video (buzzer are replaced by LED)

Discussion:

In creating this project we ran into some trouble with learning the liquidCrystal library, but after fiddling for a bit, we figured out which functions we needed and how we could use them efficiently. The circuitry of the alarm is pretty simple so that wasn’t too hard because we had gone over how to wire up most of these components in class.

In the crit, there was some great input of how we could make this project even better. One specific example was to better implement the snooze button as a “snooze” button – the alarm would go, the person would snooze the alarm and go back to sleep, but the alarm would go off much sooner than the snooze interval because of the sped up time. Another interesting idea was to have the clock be more sneaky with its time jumps – the clock would just skip some numbers every so often instead of visibly running faster.

We liked working on this project because it makes us think about things we take for granted like small appliances – lights, clocks, table, boxes, etc. We purely expect them to work properly because they’re so simple, but when they don’t, then, surprise!

 

]]>
https://courses.ideate.cmu.edu/60-223/f2018/work/surprise-wake-up/feed/ 0
Project 1: Surprise: “High Five!” https://courses.ideate.cmu.edu/60-223/f2018/work/project-1-surprise-high-five/ https://courses.ideate.cmu.edu/60-223/f2018/work/project-1-surprise-high-five/#respond Tue, 25 Sep 2018 15:27:11 +0000 https://courses.ideate.cmu.edu/60-223/f2018/work/?p=4036

High Five Box

Narrative

A wooden cube with a cardboard hand sticking out of one side. When the user tries the “high-five” the hand, the hand swivels back into the cube and a second hand pops up on a different side of the cube. Now, when the user tries to “high-five” the second hand, it swivels back inside the cube and the first hand flips back out again.

Design details

Taped wires inside the box to create turning space for the hand

Well-cut hole to fix the motor at the top of the box

How to Trigger the surprise

Try to “high five” with the hand

The hand refuses your high five and turns away.

Design Process

Testing out the appropriate sensing distance for the distance ranger

We started off testing the appropriate distance we should set for the distance ranger.

Paper Box Prototype

Later, when Roy was lazer-cutting the box, Caroline tried to figure out the turning angle of the hand by testing the motor and sensor in a paper box. We thought about putting the hand and the sensor on the same surface so that we can hide sensor and forces users to approach the sensor if they want to do high-five. This is why the paper box has . It turns out that the sensor can only have a correct detection of distance when it is facing up, so we eventually changed our plan to let both sensors stick out and face up.

Creating the Hand

After testing the sensor and motor, we started cutting the cupboard hand to fit onto the motor. We made several cupboard hands, since the initial design was too  large to fit into the box. .

Box On Top of Shelf

One interesting thing happened before our presentation is that because we set the sensor to be so sensitive that if we placed it in a cube it would turn forever until running out of battery, so we had to place it at the top of the shelf.

Schematic

High Five Box Schematic

LINK TO CODE
#include <NewPing.h>
#include<Servo.h>

boolean isFirstHand = true;

#define TRIGGER_PIN1  12  // Arduino pin tied to trigger pin on the ultrasonic sensor.
#define ECHO_PIN1     11  // Arduino pin tied to echo pin on the ultrasonic sensor.
#define MAX_DISTANCE1 200 // Maximum distance we want to ping for (in centimeters). Maximum sensor distance is rated at 400-500cm.

#define TRIGGER_PIN2  8  // Arduino pin tied to trigger pin on the ultrasonic sensor.
#define ECHO_PIN2     9  // Arduino pin tied to echo pin on the ultrasonic sensor.
#define MAX_DISTANCE2 200 // Maximum distance we want to ping for (in centimeters). Maximum sensor distance is rated at 400-500cm.
#define TOOCLOSE 20

#define HANDSPIN 6
NewPing sonar1(TRIGGER_PIN1, ECHO_PIN1, MAX_DISTANCE1); // NewPing setup of pins and maximum distance.
NewPing sonar2(TRIGGER_PIN2, ECHO_PIN2, MAX_DISTANCE2);
Servo hands;


void setup() {
  Serial.begin(115200); // Open serial monitor at 115200 baud to see ping results.
  hands.attach(HANDSPIN);
}

void loop() {
  int dataNum = 5;
  int distance1[dataNum];
  int distance2[dataNum];

  //Collect some data from each sensor
  for(int i = 0;i<dataNum;i++){
    delay(20);
    distance1[i] = sonar1.ping_cm();
    distance2[i] = sonar2.ping_cm();
  }

  //Get rid of the highest and lowest data for each sensor
  //and get the average of the remaining data
  int distanceSum1 = 0;
  int distanceSum2 = 0;
  int distancemax1 = -1;
  int distancemax2 = -1;
  int distancemin1 = 10000;
  int distancemin2 = 10000;
  for(int i = 0; i<dataNum;i++){
    distanceSum1 = distanceSum1 + distance1[i];
    distanceSum2 = distanceSum2 + distance2[i];
    if(distance1[i]<distancemin1){
      distancemin1 = distance1[i];
    }
    if(distance2[i]<distancemin2){
      distancemin2 = distance2[i];
    }
    if(distance1[i]>distancemax1){
      distancemax1 = distance1[i];
    }
    if(distance2[i]>distancemax2){
      distancemax2 = distance2[i];
    }
  }
  double distanceAvg1 = (double)(distanceSum1 - distancemin1 - distancemax1)/(double)(dataNum-2);
  double distanceAvg2 = (double)(distanceSum2 - distancemin2 - distancemax2)/(double)(dataNum-2);

  //Print out the data 
  Serial.print("Ping1: ");
  Serial.print(distanceAvg1); // Send ping, get distance in cm and print result (0 = outside set distance range)
  Serial.println("cm");
  Serial.print("Ping2: ");
  Serial.print(distanceAvg2); // Send ping, get distance in cm and print result (0 = outside set distance range)
  Serial.println("cm");

  //If something approaches sensor to a certain distance,
  //the motor would be turned
  if(distanceAvg1<= TOOCLOSE){
    if(isFirstHand){
      isFirstHand = false;
      hands.write(0);
      delay(500);
    }
  }
  if(distanceAvg2<=TOOCLOSE){
      if(!isFirstHand){
        isFirstHand = true;
        hands.write(80);
        delay(500);
      }
  }

  
}

 

Discussion

. So wiring the circuit was rather quick and simple. We predicted that writing the code would be easy as well, however, it was more complex than we anticipated because of the unreliability of the ultrasonic sensors. The sensors would read erratic distances so we had to implement a filtering function so that the distances the Arduino was receiving were more accurate. Essentially, we took the median of every five distance readings and this helped the accuracy of the ultrasonic sensors.

Another process that turned out to be more difficult than we thought it would be was the fabrication of the final setup. Designing the cube so that the servo and sensors would be in the right locations required a lot of measuring and relatively tight tolerances. The process of laser cutting the wood was also more difficult than it should have been because the laser cutter we first used didn’t perform reliably to our inputs.

From doing this project we learned that we can’t assume everything we use is going to function perfectly. The ultrasonic sensors’ unreliability and the malfunctioning laser cutter added a lot of complications that we didn’t originally account for. If we were to do the project again, we would probably add a feature to the box that hid the ultrasonic sensors to increase the element of surprise. Or we might even have considered different sensors that could operate from inside the cube. There are some other small things that could have be done to increase the surprise factor so if we had spent less time in the idea generation phase and more time in making the actual project then we could have made a more surprising device. One thing we could have done to trick the user is add a phony functionality that the user could see but it didn’t actually do anything. For example, we could have put the cube on wheels so the user would think that the cube would move at some point but we would keep the motors completely passive. We had a lot of fun doing this project and it made us realize all the devices you can create with relatively simple circuits and hardware.

 

]]>
https://courses.ideate.cmu.edu/60-223/f2018/work/project-1-surprise-high-five/feed/ 0
The Birdhouse with a Security System https://courses.ideate.cmu.edu/60-223/f2018/work/the-birdhouse-with-a-security-system/ https://courses.ideate.cmu.edu/60-223/f2018/work/the-birdhouse-with-a-security-system/#respond Tue, 25 Sep 2018 06:59:01 +0000 https://courses.ideate.cmu.edu/60-223/f2018/work/?p=4001 Our birdhouse has two doors, and the project has a series of surprises. When a user comes close enough to the birdhouse,  the “bird” in the birdhouse starts singing. Then when the user interacts with the bird vocally, the lower door opens to reveal an egg. Then if the user tries to reach for the egg, the upper doors open, the lower door closes, and a “scare bird” appears.

Functionalities and design are depicted as follows:

A front view of the birdhouse.

Side and base detailing of the birdhouse.

A front view of the birdhouse with all doors open at the same time (this doesn’t actually happen, but is instead set up here for demonstration’s sake)

Interior detailing of our birdhouse (the bird lives downstairs).

The magic in our doors was in these cardboard hinges (and the servos, but more on that later).

Below is a 2-part demo of each of the surprises in succession:

The design phase of our project took the longest, but gave us the clearest idea on how to proceed. During this time, we planned out the overall layout of our house, including dimensions for laser cutting, wiring, and placement of each of our surprises.

Whiteboarding the birdhouse- surprisingly for us, the ideation wasn’t nearly as tough as the execution.

One of the biggest challenges we ran into was opening the doors. While we knew servo motors were the best way to go about this, the actual placement and execution required a great deal of thought. Eventually, we decided on the top door’s opening to be a combination of a cardboard hinge, some carefully planned degree measurements for opening, and a servo mounting right next to the door.

Our initial door opening idea- we used a very similar concept for the final version, but made slight modifications to how the servo motor was mounted to maintain stability.

The size of the egg proved to be a large impediment in trying to open the bottom door. Since both the egg and the door’s radius were too large, it was not feasible to open the bottom door in the same way as the top door. One idea we tried was a revolving door with the egg on the other side, but the servo motor’s range and the egg’s size made this difficult. Hence, we decided on a simpler approach: that the egg itself would have a dowel attached to it, which would push aside a curtain every time the egg was to reveal itself.

The egg-door design before the curtains.

Overall, this project challenged our design skills, creativity, and technical knowledge on multiple fronts. While it was fairly easy to design the schematic, and put wires up (we had 3 inputs- switch, sound sensor, ultrasonic ranger- and 4 outputs- speaker and 3 servo motors), it was much tougher to find the right angles to open the door while ensuring it wouldn’t stick to the door frames, causing the glue to come off, as well as connect the servo motor to the door at the correct angle. 

We learned that mechanics (especially opening the door) should be considered more thoroughly while designing any moving parts in a project, and that a sound threshold is typically hard to set considering the development and production environments are very different. 

Given more time, we would have used an ultrasonic ranger better than the ones we had on hand, especially since it would have saved time trying to optimize the distance thresholds. In addition, if the lower door had been laser cut into two pieces, the servomotors could have been attached the same way as the upper doors, which may have reduced the difficulty involved with the mechanics of the lower door, though the egg may have still posed a very similar problem.

Arduino code:

#include<Servo.h>
#include <Chirp.h>

Servo topLeft;
Servo topRight;
Servo bot;

const int TOPLEFTPIN = 7;
const int TOPRIGHTPIN = 8;
const int BOTPIN = 9;
const int SOUNDSENSORPIN = A0;
const int SPEAKERPIN = 3;
const int CHIRPERTRIGGERPIN = A1;
const int CHIRPERECHOPIN = A2;
const int SWITCHERPIN = 2;
const int SOUNDTHRESHOLD = 40;
Chirp chirp;

void setup() {
  topLeft.attach(TOPLEFTPIN);
  topRight.attach(TOPRIGHTPIN);
  bot.attach(BOTPIN);
  pinMode(CHIRPERTRIGGERPIN, OUTPUT);
  pinMode(CHIRPERECHOPIN, INPUT);
  pinMode(SOUNDSENSORPIN, INPUT); //analog
  pinMode(SPEAKERPIN, OUTPUT); //digital
  pinMode(SWITCHERPIN,INPUT); //digital
  Serial.begin(9600);
  bot.write(170);
  topLeft.write(45);
  topRight.write(100);
}

bool within5m = false;
bool soundSensed = false;
bool within10cm = false;

int get_distance(){
  Serial.print("calling&returing: ");
  unsigned long duration;
  int distance;
  digitalWrite(CHIRPERTRIGGERPIN, HIGH);
  delay(1);
  digitalWrite(CHIRPERTRIGGERPIN, LOW);
  duration = pulseIn(CHIRPERECHOPIN, HIGH, 20000);
  distance = duration / 57;  // Divide by round-trip microseconds per cm to get cm
  return distance;
}


void loop() {
  if(digitalRead(SWITCHERPIN)==0){
    int distance = get_distance();
    int soundLevel = analogRead(SOUNDSENSORPIN);
    Serial.print(soundLevel>=SOUNDTHRESHOLD);
    Serial.print("loop: within5m:");
    Serial.print(within5m);
    Serial.print(" ,soundSensed:");
    Serial.print(soundSensed);
    Serial.print(" ,within10cm:");
    Serial.print(soundSensed);
    Serial.print(" distance:");
    Serial.print(distance);
    Serial.print(" SoundLevel:");
    Serial.println(soundLevel);
    //within5m: bird sings
    if(within5m && soundSensed && within10cm){
      /*two resetting states:
        1. when chirper no longer within 5m
        2. end of cycle(all triggers are triggered)*/
      Serial.print("Resetting due to: ");
      if(distance> 40){
        Serial.println("distance greater than 5m; ");
      }
      else{
        Serial.println("end of cycle; ");
      }
      within5m = false;
      soundSensed = false;
      within10cm = false;
      bot.write(180);
      topLeft.write(45);
      topRight.write(100);
    }
    else if(distance<=40 && distance>15 && !within5m && !within10cm && !soundSensed){
      /*Bird starts singing when chirper detecte within 5m*/
      /*NOTE: WE REQUIRE THE DISTANCE TO BE BETWEEN 10CM AND 5M*/
      //TODO: singing
      Serial.println("Within 5m");
      chirp.chirp("parrotbilllllahcm4");
      delay(500);  
      within5m = true;
    }
    else if(within5m && !soundSensed && soundLevel>=SOUNDTHRESHOLD && !within10cm){
      /*After bird starts singing, when sound is sensed, lower doors open*/
      Serial.println("Sound triggered");
      bot.write(100);
      soundSensed = true;
    }
    //within10cm: top doors open and bird yells
    else if(within5m && soundSensed && distance<=15){
       /*after sound triggered, when chirper detects within10cm: top doors open and bird yells*/
      //TODO: yelling
      Serial.println("Within 10cm");
      topLeft.write(160);
      topRight.write(45);
      bot.write(180);
      //chirp.chirp("parrotbilllllahcm4");
      chirp.chirp("birdhouseplzworkty");
      within10cm = true;
      delay(3000);
    }
  }

A schematic is available here.

]]>
https://courses.ideate.cmu.edu/60-223/f2018/work/the-birdhouse-with-a-security-system/feed/ 0
Project 01: Needy Wearable https://courses.ideate.cmu.edu/60-223/f2018/work/project-01-needy-wearable/ https://courses.ideate.cmu.edu/60-223/f2018/work/project-01-needy-wearable/#respond Tue, 25 Sep 2018 03:40:07 +0000 https://courses.ideate.cmu.edu/60-223/f2018/work/?p=3988 Needy Wearable is a shirt that reacts heavily when no one is close/when someone is far away, and only calms down the closer one gets. The shirt moves with the help of two servomotors and an ultrasonic ranger positioned on the chest. The wearable goes to a full stop once person2 is within 20cm of the individual wearing the shirt (i.e. way too close).

 

Process 

We noticed from the start that we had a shared interest in making reactive wearables. One of us being a costume designer in the school of drama, and the other being a media artist, we decided to create a wearable at the intersection of beauty and humor. Our concept was to design a jacket from scratch and include roughly 10 servomotors into it. These servomotors, sewn into the fabric in bunched up areas, would make our coat dynamic and eternally changing.

For the design of the coat itself, we opted to include folds and knots over the length of the sleeves. This would allow for the draping to move freely and elegantly once the servomotors were included underneath them.

 

Original wearable design inspiration (cloth draping). The final design was meant to take the form of a coat or jacket, with the knots along the length of the sleeves. 

 

After discussing the concept further, we decided that making the wearable more reactive when people are far away from it, and calmer when closer, would be more unusual and humorous. M took on the task of designing and creating the coat, while C worked on the hardware and software. C started with the implementation of the interaction in two servomotors (as seen below) before moving on to a larger number.

 

Setup with the ultrasonic range sensor and two servomotors.

 

Fastest servomotor reaction, i.e. when no one is near the wearable.

 

Slowest servomotor reaction, i.e. when it calms down as someone stays close.

 

C spent a significant amount of time working on the subtle differences in servomotor movements and speeds to try and depict the emotion of “neediness” through mechanics.

 

Unfortunately, the wearable itself was never created according to the common plan, and was sewn into a t-shirt instead. C changed the code last minute in order to include only two servomotors, which were placed on the chest area by M. An inside pocket which was supposed to include battery, arduino and breadboard had not been created in advance either, so electronics were placed within a pencil pouch, sewn to the inside of the shirt.

 

Test sewing of the ultrasonic range sensor to verify its functionality.

 

Final Documentation

 

Full electronic setup over the shirt used for the demonstration.

 

Internal mechanics of the reactive shirt.

 

The shirt as it is seen from the outside.

 

 

 

Gif of functioning wearable.

 

Discussion

This week had been very busy for M in particular, and our project unfortunately suffered from the lack of wearable. In the future, we would spend a significant amount of time working on the wearable creation and design, in addition to the software and hardware. We would also work on better group communication and time management, in order to bring a well executed product to the table. Both of us could have been more satisfied with the outcome of this project and will keep this is mind for future endeavors.

 

 

Schematic

 

 

Code

// Needy Wearable: Project I
// by Mohan Yeh (menghany) and Chloé Desaulles (cdesaull)
// Intro to Physical Computing, Fall 2018

// A shirt worn by person1 which moves due to the active state of servomotors
// if a person2 is far away from it. The Needy Wearble calms down
// as the person2 gets closer. 
// This project was built upon the NewPing library sketch.
// ---------------------------------------------------------------------------

#include &lt;NewPing.h&gt;
#include&lt;Servo.h&gt; // Object oriented programming 

#define TRIGGER_PIN  12  // Arduino pin tied to trigger pin on the ultrasonic sensor.
#define ECHO_PIN     11  // Arduino pin tied to echo pin on the ultrasonic sensor.
#define MAX_DISTANCE 200 // Maximum distance we want to ping for (in centimeters). Maximum sensor distance is rated at 400-500cm.

int pingVal; 

Servo charlie;
const int CHARLIE = 6;

Servo june;
const int JUNE = 9;


NewPing sonar(TRIGGER_PIN, ECHO_PIN, MAX_DISTANCE); // NewPing setup of pins and maximum distance.

void setup() {
  
  Serial.begin(115200); // Open serial monitor at 115200 baud to see ping results.
  charlie.attach(CHARLIE);
  june.attach(JUNE);
}

void loop() {

  //__________________________________ ULTRASONIC RANGER _____________________________________________
  
  delay(50);                     // Wait 50ms between pings (about 20 pings/sec). 29ms should be the shortest delay between pings.
  Serial.print("Ping: ");
  Serial.print(sonar.ping_cm()); // Send ping, get distance in cm and print result (0 = outside set distance range)
  Serial.println("cm");

  pingVal = sonar.ping_cm();
  
  //__________________________________ SERVOMOTORS __________________________________________________


//LARGE DISTANCE
  if (pingVal &gt; 100 || pingVal == 0){
  charlie.write(10);
  june.write(10);
  delay(450);
  
  charlie.write(179);
  june.write(179);
  delay(450);

  charlie.write(10);
  june.write(10);
  delay(450);
  
  charlie.write(179);
  june.write(179);
  delay(450);

  charlie.write(10);
  june.write(10);
  delay(450);
  
  charlie.write(179);
  june.write(179);
  delay(450);
    }

//MEDIUM DISTANCE
 else if (50 &lt; pingVal &amp;&amp; pingVal &lt;100){

  Serial.println("WORKING?");
  
  charlie.write(10);
  june.write(10);
  delay(600);

  june.write(120);
  charlie.write(120);
  delay(600);

  charlie.write(10);
  june.write(10);
  delay(600);

  june.write(120);
  charlie.write(120);
  delay(600);

  charlie.write(10);
  june.write(10);
  delay(600);

  june.write(120);
  charlie.write(120);
  delay(600);
 }

//TINY DISTANCE
  else if (20 &lt; pingVal &amp;&amp; pingVal &lt; 50){

  charlie.write(10);
  june.write(10);
  delay(2000);

  charlie.write(30);
  june.write(30);
  delay(2000);

    
  charlie.write(10);
  june.write(10);
  delay(2000);

  charlie.write(30);
  june.write(30);
  delay(2000);

    
  charlie.write(10);
  june.write(10);
  delay(2000);

  charlie.write(30);
  june.write(30);
  delay(2000);

 }


 //WEARABLE CALM (CLOSE ENOUGH)
  else if (1 &lt; pingVal &amp;&amp; pingVal &lt; 19){
    
  //charlie.detach();
  //june.detach();
  charlie.write(10);
  june.write(10);
  delay(2000);
  charlie.write(10);
  june.write(10);
  delay(2000);
 }

}

 

]]>
https://courses.ideate.cmu.edu/60-223/f2018/work/project-01-needy-wearable/feed/ 0
Surprise: Moving Courier Box ! https://courses.ideate.cmu.edu/60-223/f2018/work/surprise-moving-courier-box/ https://courses.ideate.cmu.edu/60-223/f2018/work/surprise-moving-courier-box/#respond Mon, 24 Sep 2018 07:02:39 +0000 https://courses.ideate.cmu.edu/60-223/f2018/work/?p=3921

The appearance of moving courier box.

The appearance of moving courier box.

The internal structure of moving courier box.

The internal structure of moving courier box.

The top view of moving courier box.

Bottom of moving courier box.

The driving motors and wheels of the moving courier box.

Surprise: Moving Courier Box !
Narrative Description

The project was inspired by an Arduino project found online where a prank was done to people who were trying to get tissue from a tissue box. The tissue box would sense a hand is getting close and the box would move away from the approaching hand, not letting the person get the tissue. The aim of this project was similar, which was producing an object that would sense a human approaching and run away.

The object was intentionally chosen as an object that would be an everyday-item that people would expect to see at any place instead of an item specially made for this project. This induces the surprise of the project by making an object that people would not expect to move. Original ideas included chairs or tables in the lab, but because of physical constraints, the object was chosen to be a courier box.

progress images

An ultrasonic ranger was used in our first attempt. However, it didn’t work well.

After several attempts, the IR sensor was selected since its good performance. The code and circuit parts were basically completed.

The power output of the motors was not enough to support the movement of the large box. Also, the bottom cardboard was bent due to the weight of the battery and other stuff. Therefore, we decided to change the size of the box.

Having learned the lesson for the first time, we made the underside support structure out of wood to make sure the motors and wheels could work properly.

Discussion

Our initial concept was that once a hand approaches above the box in an attempt to open it, the box would sense the hand and run away from it in a random direction with random speed, using the random numbers that were generated by the Arduino.

Instead of the ultrasonic ranger that was introduced in class, an IR sensor has been used due to the instability of the data that the ultrasonic ranger gave and the smaller size of the IR sensor.

After the completion of the code and circuit parts, we tried to put it in a large cardboard box, but the power output of the motor was not enough to support the movement of the box. What’s more, the bottom cardboard was bent due to the weight of the battery and other stuff. Therefore, we had to choose a smaller courier box to achieve our initial goal.

The IR sensor’s unstable data and the physical installation of the electronics into the box resulted in a wobbly irregular movement of the box. It was not behaving perfectly as originally planned, but the mere appearance of a package box with a label moving around on a table still had a surprising element of an ordinary item moving as intended.

Schematic

Schematic of the moving courier box

Code
//pin numbers

const int MOTORR1 = 6; //first pin for motor on the right

const int MOTORR2 = 5; //second pin for motor on the right

const int MOTORL1 = 10; //first pin for motor on the left

const int MOTORL2 = 11; //second pin for motor on the left

const int IRSENSOR = A0;

const int SWITCHPIN = 2;

const int DRIVERPIN = 13;

int direc;

int speedR;

int speedL;




void setup() {

  //Initialize pins

  pinMode(MOTORR1, OUTPUT);

  pinMode(MOTORR2, OUTPUT);

  pinMode(MOTORL1, OUTPUT);

  pinMode(MOTORL2, OUTPUT);

  pinMode(IRSENSOR, INPUT); //sensing distance

  pinMode(SWITCHPIN, INPUT); //decides whether to turn the driver on or off

  pinMode(DRIVERPIN, OUTPUT); //on/off will be delivered to driver

  //box will start not moving

  digitalWrite(MOTORR1, LOW);

  digitalWrite(MOTORR2, LOW);

  digitalWrite(MOTORL1, LOW);

  digitalWrite(MOTORL2, LOW);

  randomSeed(analogRead(0)); //don't plug anything into 0

  //Serial.begin(9600);

}




void loop() {

  //box will check if anything is too close

  int distance = analogRead(IRSENSOR);

  //Serial.println(distance);

  direc = random(2);

  speedR = random(255);

  speedL = random(255);

  int switchVal = digitalRead(SWITCHPIN);

  //driver turned on

  if (switchVal == HIGH) {

    digitalWrite(DRIVERPIN, HIGH);

    //maximum distance below is 50 for now, but it can be adjusted by wiggling the potentiometer

    //IR sensor will give low number when nothing is nearby and high number when something is close

    if (distance > 50 ) { //people are too close, so it wants to run away 🙁

      if (direc == 0) { //box moves forward

        //speed for motors will be different from each other

        //speed for each motor will be random so that the box will move at a random direction

        analogWrite(MOTORR1, speedR);

        analogWrite(MOTORR2, 0);

        analogWrite(MOTORL1, speedL);

        analogWrite(MOTORL2, 0);

        //Serial.println("forward,"+ String(speedR));

        delay(3000);

      }

      if (direc == 1) { //box moves backward

        analogWrite(MOTORR1, 0);

        analogWrite(MOTORR2, speedR);

        analogWrite(MOTORL1, 0);

        analogWrite(MOTORL2, speedL);

        //Serial.println("backward");

        delay(3000);

      }

    }

    else {

      digitalWrite(MOTORR1, LOW);

      digitalWrite(MOTORR2, LOW);

      digitalWrite(MOTORL1, LOW);

      digitalWrite(MOTORL2, LOW);

    }

  }

  else {

    digitalWrite(DRIVERPIN, LOW);

    //Serial.println("driver off");

  }

}

 

Author

]]>
https://courses.ideate.cmu.edu/60-223/f2018/work/surprise-moving-courier-box/feed/ 0