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 2
This project connects people with their loved ones who are living at a distance by subtly augmenting objects in their natural surroundings which then become their enchanted versions and magically convey the message of being missed.
In the interest of education, profession or projects, many people live far away from their loved ones. Often when caught up with life, we tend to get so busy that it seems impossible to take out any time to stay in touch. Moreover, we always think twice before making a phone call so as to not disturb others assuming that everyone is always busy. On numerous occasions, even if there's nothing to talk about, a small gesture of letting someone know that they are being missed is more than enough to communicate the love and affection for them.
Living pictures is a connected social photo frame that augments a regular photo frame placed on a desk or hanging on a wall that enables its users to touch the picture and send a simple message to the ones they love that they miss them and are thinking about them. To the other side of the interaction, a simple breathing light which is glanceable in the periphery works as a reminder that there's someone out there who is missing them.
The concept of this idea was to initiate some kind of social interaction between loved ones which is non-intrusive and does not require urgent attention of the actors. We wanted to create an object that not only facilitates this interaction but also fall back to function as a regular everyday object that is in the natural surrounding of its users.
We chose to augment a photo frame because it has always been an object that stimulates emotions and is associated with memories and nostalgia. It also felt like a suitable tangible medium to connect people with their loved ones whose pictures are already placed in a traditional photo frame.
The interaction with the picture frame is simple yet meaningful. The user can simply touch a part of the photo frame on their desk or make a streak of touch and the same touch would be visible on the photo frame that their loved ones have bu a series of led lights that light up in the same area as the original touch. These lights then slowly fade away indicating the trail that a touch leaves behind it. To the user on the other side, the photo frame which is glanceable in their peripheral vision lights up as if someone is touching it from the other side, and they can choose to retrace the path or create their own gesture which is communicated back indicating that they are missing them and thinking about them too.
To capture the touch of the user in different areas of the frame, we are using five-point capacitive touch sensors that are attached to metal contacts on top of the frame. The sensor can detect different areas of touch and send the signal to particle cloud as input.
int buttonPin = D3;
int capPin = D4;
bool ananas = false; //
void setup() {
pinMode(capPin, INPUT);
pinMode(buttonPin, INPUT);
Particle.variable("bool", ananas);
}
void loop() {
if (digitalRead(capPin) == LOW)
{
ananas= !ananas;
Particle.publish ("Capacitive Touch", "LOW");
delay(2000);
} else
{
Particle.publish ("Capacitive Touch", "HIGH");
delay(2000);
}
}
Click to Expand
// This #include statement was automatically added by the Particle IDE.
#include <neopixel.h>
// 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; //10 s
int buttonPin = D3;
// IMPORTANT: Set pixel COUNT, PIN and TYPE
#define PIXEL_PIN D2
#define PIXEL_COUNT 5
#define PIXEL_TYPE WS2812
Adafruit_NeoPixel strip = Adafruit_NeoPixel(PIXEL_COUNT, PIXEL_PIN, PIXEL_TYPE);
String event = "css19/diot/2019/paired/";
void setup()
{
// We'll want to subscribe to an event thats fairly unique
// From the Particle Docs
// A subscription works like a prefix filter.
// If you subscribe to "foo", you will receive any event
// whose name begins with "foo", including "foo", "fool",
// "foobar", and "food/indian/sweet-curry-beans".
// Basically this will match any event that starts with 'db2018/paired/'
// This is a feature we'll useto figure out if our event comes from
// this device or another (see publishMyEvent below)
pinMode( buttonPin , INPUT_PULLUP);
strip.begin();
Particle.subscribe( event , handleSharedEvent );
}
void loop()
{
int buttonState = digitalRead( buttonPin );
if( buttonState == LOW)
{
// turn the LED On
publishMyEvent();
//doSolenoid();
}else{
// otherwise
// turn the LED Off
}
delay( 100 );
}
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 eventName = event + 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, "Seema" );
// 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();
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
uint32_t i;
uint32_t c = strip.Color(0, 0, 255); // Blue
uint32_t d = strip.Color(0, 0, 0); // no color
// if( buttonReading == HIGH )
// {
for( int i = 0; i < strip.numPixels(); i++ )
{
strip.setPixelColor(i, c); // set a color
strip.show();
delay( 200 );
}
//}
}
Click to Expand
The two pictures frames were installed with capacitive touch sensors and for the purpose of demonstration, one was embedded with Neopixel to show the interaction with the frames.
When a user 1 touches the picture frame it lights up blue in that area, and the light on the picture frame of user 2 lights up red in the same area.
When both the users touch the frame at the same time in the same area, the lights on both frame light up purple indicating a simultaneous touch.
// This #include statement was automatically added by the Particle IDE.
#include <neopixel.h>
#define PIXEL_COUNT 1
#define PIXEL_PIN D2
#define PIXEL_TYPE WS2812B
Adafruit_NeoPixel strip(PIXEL_COUNT, PIXEL_PIN, PIXEL_TYPE);
// COLORS
int red = 0;
int blue = 0;
int green = 0;
// INPUT
int buttonPin = D3;
// PARTICLE CLOUD
long lastPublishedAt = 0;
int publishAfter = 3000;
// EVENT NAME
String event = "css19/diot/2019/paired/";
// TIME KEEPING
unsigned long pressTime = 0;
void setup() {
pinMode(buttonPin , INPUT_PULLUP);
pinMode( PIXEL_PIN, OUTPUT );
Particle.subscribe( event , handleSharedEvent );
}
void loop() {
int buttonState = digitalRead( buttonPin );
if( buttonState == LOW)
{
// turn the LED On
publishMyEvent();
//doSolenoid();
}else{
// otherwise
// turn the LED Off
}
delay( 100 );
if((millis()-pressTime) > 5000) {
setRGBColor(0,0,0);
} else {
int v = int ((millis() - pressTime) / 5000);
setRGBColor(v * red, v * blue,0);
}
}
void setRGBColor( int r, int g, int b ){
red = r;
green = g;
blue = b;
strip.setPixelColor(0, red, green, blue);
strip.show();
}
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 eventName = event + 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, "Satyan" );
// And this will get shared out to all devices using this code
// we just pubished so capture this.
lastPublishedAt = millis();
}
}
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
pressTime = millis();
blue = 255;
setRGBColor(red,blue,0);
return;
}
// otherwise do your stuff to respond to
// the paired device here
//motorOn = true;
pressTime = millis();
red == 255;
setRGBColor(red,blue,0);
}
Click to Expand
// This #include statement was automatically added by the Particle IDE.
#include <neopixel.h>
#define PIXEL_COUNT 1
#define PIXEL_PIN D2
#define PIXEL_TYPE WS2812B
Adafruit_NeoPixel strip(PIXEL_COUNT, PIXEL_PIN, PIXEL_TYPE);
// COLORS
int red = 0;
int blue = 0;
int green = 0;
// INPUT
int buttonPin = D3;
// PARTICLE CLOUD
long lastPublishedAt = 0;
int publishAfter = 3000;
// EVENT NAME
String event = "css19/diot/2019/paired/";
// TIME KEEPING
unsigned long pressTime = 0;
void setup()
{
pinMode(buttonPin , INPUT_PULLUP);
pinMode( PIXEL_PIN, OUTPUT );
Particle.subscribe( event , handleSharedEvent );
}
void loop()
{
int buttonState = digitalRead( buttonPin );
if( buttonState == LOW)
{
// turn the LED On
publishMyEvent();
//doSolenoid();
}
else
{
// otherwise
// turn the LED Off
}
if((millis()-pressTime) > 7000)
{
setRGBColor(0,0,0);
strip.setBrightness(255);
}
unsigned long v = ((millis() - pressTime) / 7000.0);
int k = int(255.0 * (1.0-v));
strip.setBrightness(k);
}
void setRGBColor( int r, int g, int b )
{
red = r;
green = g;
blue = b;
strip.setPixelColor(0, red, green, blue);
strip.show();
}
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 eventName = event + 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, "Seema" );
// And this will get shared out to all devices using this code
// we just pubished so capture this.
lastPublishedAt = millis();
}
}
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
pressTime = millis();
blue = 255;
strip.setBrightness(255);
setRGBColor(red,0,blue);
return;
}
// otherwise do your stuff to respond to
// the paired device here
//motorOn = true;
pressTime = millis();
red = 255;
strip.setBrightness(255);
setRGBColor(red,0,blue);
}
Click to Expand
A hands-on introductory course exploring the Internet of Things and connected product experiences.
This project connects people with their loved ones who are living at a distance by subtly augmenting objects in their natural surroundings which then become their enchanted versions and magically convey the message of being missed.
February 11th, 2019