49713 Designing for the Internet of Things
· 18 members
A hands-on introductory course exploring the Internet of Things and connected product experiences.
Found in Diot 2019: Social Objects - Part 3
Create a feeling of togetherness for a couple who is living apart through the experience of watching a scary movie together using the power of connected social devices.
Because a growing number of friends and couples spend time living far apart, we intend to change the experience of having to watch a movie alone to a shared experience for pairs who enjoy horror movies so they can feel closer together. We did this by developing a social device that allows one member of the couple to signal to the other when they are ready to watch a movie and when they feel scared.
Brainstorming
To begin the project, each member created three different ideas and storyboarded the possible interactions. We shared these ideas online and discussed them- we riffed on a number of them but it was clear that we all wanted to create something for couples or friends that live apart since we all had experience with that situation. Our inspiration became the GoodNight Lamp, which enables couples to let each other know when they are awake and asleep.
It was a quick jump from identifying our target audience to our value opportunity- improving connectedness while watching a scary movie. Watching movies simultaneously is a growing trend. But couples and friends do not have many choices that help them feel a connection beyond pressing play and texting or FaceTime-ing as the movie progresses.
In order to create a new level of connectedness for our target our device requirements were:
Must: Fit in with the existing environment, not require wearing, be opt-in, enable 1-way sharing via cloud particle function, be safe
Should: Use touch as input and output, augment existing plans so that both parties would consent to use the device
Could: Enable two-way sharing
Components & User Experience
In storyboarding the experience, we focused on using pillows for the interaction, since most people have pillows in their home. Initially, we planned to use two throw pillows, however, after discussing the user experience and wanting it to be as natural as possible, we decided to use a husband pillow for the "sender" end of the experience. This would enable the user to hold the "arms" of the pillow when they felt scared during the movie, similar to how they would hold their partner's arm or hand. This would send a message to the "receiver" end of the experience in the form of a short vibration.
During planning, we decided that it would be more appealing if we added a second interaction to start the movie. We added a sensor to the back of the husband pillow that would activate an LED on the partner's pillow to let them know to start the movie.
We were also concerned with unintended consequences. We decided that it is very important that this not create anxiety for either member of the couple, so the device would augment existing plans that the pair would make to watch a movie. This would also take care of the need for consent. Otherwise, the pillows would serve their normal purpose and not require explanation or use.
Building the Prototype
The first prototype was a working prototype that consisted of three breadboards. The first breadboard had three sensors: two FSRs and one flex/bend that would serve as the publishing events. We established that it worked, by having it publish events to the Particle cloud and monitoring it on the console and via the Particle Serial Monitor. We established the range of values to trigger the events by tracking the values in the serial monitor when the events were triggered.
The second breadboard had the LED light and the third one had the solenoid, both outputs. Once we established each board was working using a push-button, we set up each device to subscribe to the published events.
After we successfully tested the working prototype and received feedback on it, we begin to build the functional prototype. This included purchasing two pillows: a husband pillow and a throw pillow. We made some changes based on the feedback: we switched from a solenoid to a vibrating disc as it was more appropriate for sewing into a pillow, constructed a trigger pressure switch for the back of the pillow, and switched to bend sensors for each side of the "arms."
We also consolidated into two breadboards- one for each pillow. We lengthened the leads to enable us to embed the sensors and the outputs in the pillows. We did this methodically, testing each lead as we added it and adding each output incrementally. Once all of the parts were working, we embedded them into the pillows and brought our device to life.
For Sensor Pillow:
For Vibration and LED on Receiver Pillow:
//This is the code for the "Sensing Pillow"
// This value will store the last time we published an event
long lastPublishedAt = 0;
// this is the time delay before we should publish a new event
// from this device
int publishAfter = 20000;
//setup pins
int bendPin1 = A1;
int bendPin2 = A2;
int bendPin3 = A4;
int bendPin4 = A5;
bool backPin = false;
int bendReading;
int bendReading2;
int bendReading3;
int bendReading4;
void setup(void)
{
Serial.begin(9600); // We'll send debugging information via the Serial monitor
pinMode(bendPin1 , INPUT);
pinMode(bendPin2 , INPUT);
pinMode(bendPin3 , INPUT);
pinMode(bendPin4 , INPUT);
pinMode(backPin , INPUT);
Particle.subscribe( "hugIt/imReady" , handleSharedEvent );
Particle.subscribe( "hugIt/imScared" , handleSharedEvent );
}
void loop(void)
{
int bendReading1 = analogRead(bendPin1);
Serial.print("Bend1 Analog reading = ");
Serial.println(bendReading1);
int bendReading2 = analogRead(bendPin2);
Serial.print("Bend2 Analog reading = ");
Serial.println(bendReading2);
int bendReading3 = analogRead(bendPin3);
Serial.print("Bend3 Analog reading = ");
Serial.println(bendReading3);
int bendReading4 = analogRead(bendPin4);
Serial.print("Bend4 Analog reading = ");
Serial.println(bendReading4);
if(bendReading1 > 1000 || bendReading2 > 1000 || bendReading3 > 1000 || bendReading4 > 1000 )
{
publishImScared();//sends "ready" signal
delay(100);// delay for a bit
}
if(backPin = TRUE)
{
publishImReady();//sends signal that you are scared
delay(30000);
}
}
void publishImReady()
{
// Remember that a device can publish at rate of about 1 event/sec,
// with bursts of up to 4 allowed in 1 second.
// Back to back burst of 4 messages will take 4 seconds to recover.
// So we want to limit the amount of publish events that happen.
// check that it's been 10 secondds since our last publish
if( lastPublishedAt + publishAfter < millis() )
{
// Remember our subscribe is matching "db2018/paired/"
// We'll append the device id to get more specific
// about where the event came from
// System.deviceID() provides an easy way to extract the device
// ID of your device. It returns a String object of the device ID,
// which is used to identify your device.
String eventName = "hugIt/imReady" + System.deviceID();
// now we have something like "diot/2019/paired/0123456789abcdef"
// and that corresponds to this devices info
// then we share it out
Particle.publish( eventName, "I'm READY" );
// And this will get shared out to all devices using this code
// we just pubished so capture this.
lastPublishedAt = millis();
}
}
void publishImScared()
{
// Remember that a device can publish at rate of about 1 event/sec,
// with bursts of up to 4 allowed in 1 second.
// Back to back burst of 4 messages will take 4 seconds to recover.
// So we want to limit the amount of publish events that happen.
// check that it's been 10 secondds since our last publish
if( lastPublishedAt + publishAfter < millis() )
{
// Remember our subscribe is matching "db2018/paired/"
// We'll append the device id to get more specific
// about where the event came from
// System.deviceID() provides an easy way to extract the device
// ID of your device. It returns a String object of the device ID,
// which is used to identify your device.
String eventName = "hugIt/imScared" + System.deviceID();
// now we have something like "diot/2019/paired/0123456789abcdef"
// and that corresponds to this devices info
// then we share it out
Particle.publish( eventName, "I'm SCARED" );
// And this will get shared out to all devices using this code
// we just pubished so capture this.
lastPublishedAt = millis();
}
}
// Our event handlde requires two bits of information
// This gives us:
// A character array that consists of the event name
// A character array that contains the data published in the event we're responding to.
void handleSharedEvent(const char *event, const char *data)
{
// Now we're getting ALL events published using "db2018/paired/"
// 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();
// device id = 0123456789abcdef
// event = "diot/2019/paired/0123456789abcdef"
if( eventName.indexOf( deviceID ) != -1 ){
// if we get anything other than -1
// the event came from this device.
// so stop doing stuff
return;
}
}
Click to Expand
//This code is for the "Receiving Pillow"
// This #include statement was automatically added by the Particle IDE.
#include <adafruit-drv2605-photon.h>
// This #include statement was automatically added by the Particle IDE.
#include <neopixel.h>
// This #include statement was automatically added by the Particle IDE.
#include <neopixel.h>
#define PIXEL_PIN D3
#define PIXEL_COUNT 14
#define PIXEL_TYPE WS2812
Adafruit_NeoPixel strip = Adafruit_NeoPixel(PIXEL_COUNT, PIXEL_PIN, PIXEL_TYPE);
int vibrator=D2;
int button= D3;
int buttonState = true;
#include <Wire.h>
//#include "Adafruit_DRV2605.h"
Adafruit_DRV2605 drv;
uint8_t effect = 7;
uint32_t wait = 10;
// This value will store the last time we published an event
// This value will store the last time we published an event
long lastPublishedAt = 0;
// this is the time delay before we should publish a new event
// from this device
int publishAfter = 10000;
void setup()
{
strip.begin();
strip.show(); // Initialize all pixels to 'off'
// pinMode( buttonPin , INPUT_PULLUP); // sets pin as input
Particle.subscribe( "hugIt/imReady" , handleSharedEvent1 );
Particle.subscribe("hugIt/imScared", handleSharedEvent2);
pinMode( vibrator, OUTPUT);
Serial.begin(9600);
drv.begin();
drv.selectLibrary(1);
// I2C trigger by sending 'go' command
// default, internal trigger when sending GO command
drv.setMode(DRV2605_MODE_INTTRIG);
}
void loop()
{
uint16_t i;
uint32_t c = strip.Color(219, 101, 255);
uint32_t c_off = strip.Color(0, 0, 0);
// publish my event
// you'll want some more complex stuff here
// buttonState = digitalRead( buttonPin );
// if(buttonState == LOW) {
// publishMyEvent();
// }
}
void publishMyEvent()
{
// Remember that a device can publish at rate of about 1 event/sec,
// with bursts of up to 4 allowed in 1 second.
// Back to back burst of 4 messages will take 4 seconds to recover.
// So we want to limit the amount of publish events that happen.
// check that it's been 10 secondds since our last publish
if( lastPublishedAt + publishAfter < millis() )
{
// Remember our subscribe is matching "db2018/paired/"
// We'll append the device id to get more specific
// about where the event came from
// System.deviceID() provides an easy way to extract the device
// ID of your device. It returns a String object of the device ID,
// which is used to identify your device.
String eventName1 = "hugIt/imReady" + System.deviceID();
String eventName2 = "hugIt/imScared" + System.deviceID();
Particle.publish( eventName1, "I'm SCARED" );
Particle.publish( eventName2, "Ehhhhh" );
//Publish event to all devices
lastPublishedAt = millis();
}
}
// Our event handlde requires two bits of information
// This gives us:
// A character array that consists of the event name
// A character array that contains the data published in the event we're responding to.
void handleSharedEvent1(const char *event, const char *data)
{
uint16_t i;
uint32_t c = strip.Color(219, 101, 255);
uint32_t c_off = strip.Color(0, 0, 0);
// Now we're getting ALL events published using "db2018/paired/"
// 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
String deviceID = System.deviceID();
// device id = 0123456789abcdef
// event = "diot/2019/paired/0123456789abcdef"
if( eventName.indexOf( deviceID ) != -1 ){
// 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
for (i=0; i< strip.numPixels() ; i++ ){
strip.setPixelColor(i,c);
delay(500);
}
strip.show();
delay(5000);
for (i=0; i< strip.numPixels() ; i++ ){
strip.setPixelColor(i,c_off);
}
strip.show();
delay(100);
}
void handleSharedEvent2(const char *event, const char *data)
{
// Now we're getting ALL events published using "db2018/paired/"
// 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();
// device id = 0123456789abcdef
// event = "diot/2019/paired/0123456789abcdef"
if( eventName.indexOf( deviceID ) != -1 ){
// if we get anything other than -1
// the event came from this device.
// so stop doing stuff
return;
}
digitalWrite( vibrator, HIGH );
delay(100);
Serial.print("Effect #"); Serial.println(effect);
// set the effect to play
drv.setWaveform(0, effect); // play effect
drv.setWaveform(1, 0); // end waveform
// play the effect!
drv.go();
for( int i = 0; i < 3; i++ )
{
digitalWrite(vibrator, HIGH);
delay( 1000 ) ;
}
digitalWrite( vibrator, LOW );
// delay(wait * 60 * 1000);
}
Click to Expand
A hands-on introductory course exploring the Internet of Things and connected product experiences.
Create a feeling of togetherness for a couple who is living apart through the experience of watching a scary movie together using the power of connected social devices.
February 17th, 2019