0

Problem Statement

Students living away from home often feel disconnected from the experiences and important events that take place in their family's home and in their home towns. These events range from intimate family dinners and holiday celebrations to more public events like festivals and sports matches.

0

Project Goal

Our concept aims to bridge the connection gap between a student's new place of residence and their homes, in essence bringing their home life into their new lives away. We aimed to create an experience that is powerful, comforting, and non-interruptive so that enhances connection while not distracting from one's day-to-day experience. We wanted the interaction to feel authentic and to coordinate well as a system with our two other products.

0

Process

We set out to build a picture frame with an LED strip behind the image. The image would show a view outside the windows of the student's home, and the LED light would change its intensity/color based on the weather of the student's hometown. By looking at the picture frame, the student would know what the weather is like in their hometown while they are living away from their home. Through our design and circuit building process, we created a number of iterations, keeping with the original intent of the project while changing the form and some functionality.

Form Progression

As pictured below, our initial concept was in the form of a picture frame, backlit with an LED light. Upon getting feedback and considering the impact of the design, we brainstormed around creating a form that was more representative of 'home' for the user and that had a stronger design element and more dynamic functionality. Our first prototype incorporated motion (a spinning cylinder), different colored light (using plastic colored film), and projection. These additional components made for a higher impact product; however, we still wanted to improve upon the form from an aesthetic and functional perspective. Aesthetically, we wanted the form to be clean while incorporating art from our student's country of origin. We explored doing this through painting and through laser cutting wood and ultimately found that the laser cut wood created a cleaner aesthetic. For our form, we changed the stepper motor rotation axis from a z-axis rotation to a y-axis rotation in order to create a simpler mechanism by which to support the light above the stepper motor.

Building The Circuit

Starting with the breadboard, we added an LED and then the stepper motor and driver. From that point, the team tested the light and realized that it was not strong enough to project onto a wall. We then replaced the LED with a neopixel; however, this solution did not work either. We considered using an 8x8 LED matrix but realized that given our desired functionality, a light that was consistently on would work just as well. We opted to use a flashlight that was not connected to the circuit. From this point, we removed all lighting components from the circuit. We initially had a button in the circuit to activate the stepper motor; however, for the purposes of the system and demo we opted to control the circuit through a computer instead of a physical button. We tested the functionality of the circuit intermittently to ensure that it worked well in conjunction with the physical prototype.

0
Initial, low-fidelity prototype (close-up of weather cut out)
Screen shot 2018 03 03 at 10.55.44 am
0
Initial, low-fidelity prototype (top view)
Screen shot 2018 03 03 at 10.56.01 am
0
Initial, low-fidelity prototype (bottom and side)
Screen shot 2018 03 03 at 10.56.16 am
0
Exploring new forms and functionality for the final prototype.
Img 20180303 104303426
0
Final circuit in progress.
Img 20180305 131748552
0
Mid-fidelity prototype, second iteration. Includes first version of laser-cut body.
Img 20180305 224843762
0

Outcome

The team's final prototype included an external light and power source. The motion was created by a stepper motor. As described above, the team iterated, each time ensuring that the design and engineering choices were as simple as possible while still providing the desired functionality. The following summarizes the bill of parts for the circuit and physical prototype, the circuit configuration, and the final code used.

Circuit - Bill of Materials:

  • Particle Photon (x1)
  • Breadboard (x1)
  • Jumper Wires as needed
  • Battery Pack (4 AA batteries)
  • Diode (6V to 4.7V reduction for remote battery to use with Photon Vin pin) (x1)
  • Stepper motor (x1)
  • Stepper motor driver - A4988 (x1)
  • Shaft collar

Physical Prototype - Bill of Materials:

  • Stepper motor platform
  • Side (paper)
  • Small flashlight
  • Back (wood, lasercut)
  • Front (wood, lasercut)
  • Disc with four sections + laser cut images (sun, rain, cloud, fog) (wood, lasercut)
0
Final prototype shell (detail).
Img 20180307 172758395
0
Final prototype shell.
Img 4036lamp2
0
Light projections of different weather conditions.
A toast night
0
Final Code
/*
 * Project aHome_Sight
 * Description:  Requires integration with aHome_Sound
 * Author:  Ben Fisher
 * Date:
 */

// stepper
// defines pin numbers
int stepPin = D5;
int dirPin = D6;
int whereIsTheStepperNow = 0;
int numSteps = 0;  // number of steps to travel (currently unused)
int stepsPerRev = 200; // stepper motor steps per revolution of the spindle
int numberOfDrawings=4; // number of possible "outcomes" represented in 360 deg.

// stepper-related variables
int degreeChangeRequired = 0;
int currentPicture = 0; // ranges from 0 to (numberOfDrawings-1)
int desiredPicture = 0; // ranges from 0 to (numberOfDrawings-1)

// weather
String weatherIcon = "";
double temperature = 0;
double precipProbability = 0;
double precipIntensity = 0;

// setup() runs once, when the device is first turned on.
void setup() {
  // Put initialization like pinMode and begin functions here.

  //stepper
  pinMode(stepPin,OUTPUT);
  pinMode(dirPin,OUTPUT);

  // make the temperature values visible online
  Particle.variable("weatherIcon", &weatherIcon, STRING );

  // debug motor
  Particle.variable("currentPos", &currentPicture, INT );
  Particle.variable("desiredPos", &desiredPicture, INT );

  // connect to other devices
  Particle.subscribe(  "diot/2018/connected/atHome" , handleSharedEvent );

  // opens serial port for LCD shield
  Serial.begin(9600);
}

void getData() // For weather
{
    // Publish an event to trigger the webhook
 Particle.publish("forecast", "19.0896,72.8656", PRIVATE);
}

// loop() runs over and over again, as quickly as it can execute.
void loop() {

}

void moveStepper( int steps ){

    if (steps > 0){
      // Enables the motor to move in a particular direction
      digitalWrite(dirPin, HIGH);
      // Makes "steps" number of steps (200 = full revolution)
      for(int x = 0; x < abs(steps); x++) {
        digitalWrite(stepPin, HIGH);
        delayMicroseconds(5000);
        digitalWrite(stepPin, LOW);
        delayMicroseconds(5000);
      }
    }else{
      // Enables the motor to move in the opposite direction
      digitalWrite(dirPin, LOW);
      // Makes "steps" number of steps (200 = full revolution)
      for(int x = 0; x < abs(steps); x++) { //abs() in case steps is negative
                              // alternatively, for(int x = 0; x > steps; x--){
        digitalWrite(stepPin, HIGH);
        delayMicroseconds(5000);
        digitalWrite(stepPin, LOW);
        delayMicroseconds(5000);
      }
    }

    // Either way, update whereIsTheStepperNow
    whereIsTheStepperNow = whereIsTheStepperNow + steps;
    if( whereIsTheStepperNow >= 200 ){ // we passed the 0 point moving cw
      whereIsTheStepperNow = whereIsTheStepperNow - 200;
    }
    if( whereIsTheStepperNow < 0 ){ // we passed the 0 point moving ccw
      whereIsTheStepperNow = whereIsTheStepperNow + 200;
    }

    delay(1000); // One second delay
    Serial.print( "Current number of steps from 0 is " );
    Serial.println( whereIsTheStepperNow );

}

void handleSharedEvent(const char *event, const char *data)
{
    // Now we're getting ALL events published using "diot/2018/connected/atHome"
    // This includes events from this device.
    // So we need to ignore any events that we sent.

    // Let's check the event name
    String eventName = String( event ); // convert to a string object
    // This gives us access to a bunch of built in methods
    // Like indexOf()
    // Locates a character or String within another String.
    // By default, searches from the beginning of the String,
    // but can also start from a given index,
    // allowing for the locating of all instances of the character or String.
    // It Returns: The index of val within the String, or -1 if not found.

    // We can use this to check if our event name contains the
    // id of this device

    String deviceID = System.deviceID();
    weatherIcon = String(data);

    if( eventName.indexOf( deviceID ) != -1 ) //is mark publishing anything
    {
      // if we get anything other than -1
      // the event came from this device.
      // so stop doing stuff
      return;
    }

    // otherwise do your stuff to respond to
    // the paired device here

    Serial.print("weather icon is ");
    Serial.println(weatherIcon);

    // move the stepper motor accordingly
    /*
    note that these are based on the event published by other devices,
    not getting it from forecast.io using a webhook
    */
    if (weatherIcon == "cloud") {
      desiredPicture = 1;
    }
    else if (weatherIcon == "wind") {
      desiredPicture = 2;
    }
    else if (weatherIcon == "clear"){
      desiredPicture = 3;
    }
    else if (weatherIcon == "rain"){
      desiredPicture = 0;
    } //otherwise it's none of these, and no motion is required
    Serial.print("desiredPicture is");
    Serial.println(desiredPicture);

    // reminder:  need {} if using 2+ lines in the "then" statements
    int picDifference = desiredPicture - currentPicture;

    // reset from previous iteration of looo
    degreeChangeRequired = 0;

    if (picDifference == 1 || picDifference == (1 - numberOfDrawings))
      degreeChangeRequired=(360 / numberOfDrawings);
    if (picDifference == -1 || picDifference == (numberOfDrawings - 1))
      degreeChangeRequired=(-360 / numberOfDrawings);
    if (picDifference == 2 || picDifference == (2 - numberOfDrawings))
      degreeChangeRequired=(-2 * 360 / numberOfDrawings);
    // otherwise, no motion is required

    numSteps = degreeChangeRequired*stepsPerRev/360;
    moveStepper( numSteps );
        // update currentPicture
        currentPicture = desiredPicture;
}
Click to Expand
0

Code Used & Referenced

Code lines 101-130 provided by Daragh Byrne in 'Designing for the Internet of Things" course at CMU, February 2018.

0

Reflection

Integrating with different teams was difficult because we all had different visions and ideas. As we designed, tested, and iterated, it was important to keep communication open between groups to ensure that our updated designs and functionalities worked well in concert with the other prototypes. We found it helpful to create a specific use case and target user that we could reference as we designed to ensure we were solving for the right pain points. We also learned how to integrate a number of new components and processes into our design process.

Learnings

  • How to use a stepper motor and stepper motor driver
  • How to use a battery pack as an external power source
  • Learned how to use eeproms to store data on the photo when unplugged. Was not used in the final prototype but initially planned to use so that the motor could 'remember' it's last location
  • We learned how to use laser cutting to quickly create a polished form and to add design elements to our prototype

    Challenges

    • Mounting the stepper motor and attaching it to the disc
    • LED light was initially meant to be our light source; however, the LEDs were not strong enough to project onto the wall and we had to substitute with a flashlight
    • Wires often became frayed and were difficult to fit into the terminal box
    • Attaching the paper side was difficult and did not come out as cleanly and seamlessly as we would have liked
    • We struggled with designing for a demo (showing full functionality in a short period of time) versus designing for a final product which might show full functionality over time. 
    • Internal components were difficult to secure, causing challenges with demoing 

    Future Iterations

    • Would like to find an alternative to using the flashlight as our light source, potentially a light which can change colors
    • Use a smaller, quieter motor in order to make the prototype more ambient and less intrusive
    • Add more weather options so we can create a more accurate and descriptive representation of the weather.
    • Add more design and potentially color to the outer casing to add impact. Potential for larger projection with more detail
    • Build in a place to hold the internal components
    x
    Share this Project

    Courses

    49713 Designing for the Internet of Things

    · 25 members

    A hands-on introductory course exploring the Internet of Things and connected product experiences.


    About

    ~

    Created

    February 24th, 2018