49713 Designing for the Internet of Things
· 18 members
A hands-on introductory course exploring the Internet of Things and connected product experiences.
To facilitate a supportive studio environment.
In studio, we often see people gets stressed out over homework, exams, projects. Sometimes it looks like there's a dark cloud above their head when they are sitting at the corner with an upset face. We want to comfort and support them but we don't want to go straight to them and interrupt what they are doing. We want to remind them that "every cloud has a silver lining" in an ambient way.
We believe that language is the strongest way of communication in the world. Instead of conveying the message verbally, we can display the message in an interactive and unobtrusive way. We decided to do it with a RGB LED matrix since a lot of fun animations can be made and there are no sounds to interrupt them. And here is a storyboard to show the basic concept:
We successfully implemented our ideas of the device and connected it with two other groups. When someone wants to cheer up another person in the studio, he/she can send a text message to our device (the phone number connected to IFTTT), the message will show on our device as well as be printed in the Surprise printer in that person's locker. Feel-o-meter will detect the the emotions in the studio everyday and share the data with us. When there are more negative emotions, our device will show a message that "Our studio needs some love today". When there are more positive emotions, it will show that "it's a good day today" with bouncing balls in the background.
Connecting the circuit
After getting our materials, we followed the hookup guide on Sparkfun to connect the LED matrix. We encountered a lot of technical difficulties here. The connection wasn't stable at first so we replaced jumper wires to ribbon cables to improve the connection. We also tested the outcome with the sample code. We also connected it with a servo to add one more interactive component to the device.
Programming the device
We started our code with the RGB matrix library but soon figured that it's only compatible with a Photon instead of an Argon. So we had to switch to a Photon and programmed the animations of scrolling text and bouncing balls from there. The outputs are triggered by text message to a phone number connected to IFTTT.
int buttonPin = D3;
int servoPin = D2;
Servo myServo;
int servoPos = 0;
long lastPublishedAt = 0;
// this is the time delay before we should publish a new event
// from this device
int publishAfter = 10000;
bool state = false;
void setup()
{
pinMode(buttonPin, INPUT_PULLUP);
myServo.attach( D2 );
Particle.subscribe( "diot/2019/smartstudio/supporter" , handleSharedEventPrint);
Particle.variable( "servoPos" , &servoPos , INT );
}
void loop()
{
}
// A character array that contains the data published in the event we're responding to.
void handleSharedEventPrint(const char *event, const char *data)
{
myServo.write( 0 );
delay(1000);
myServo.write( 180 );
delay(1000);
myServo.write( 0 );
delay(1000);
myServo.write( 180 );
delay(1000);
myServo.write( 0 );
delay(1000);
myServo.write( 180 );
delay(1000);
myServo.write( 0 );
delay(1000);
myServo.write( 180 );
delay(1000);
myServo.write( 0 );
delay(1000);
myServo.write( 180 );
delay(1000);
myServo.write( 0 );
delay(1000);
myServo.write( 180 );
delay(1000);
myServo.write( 0 );
}
Click to Expand
// This #include statement was automatically added by the Particle IDE.
#include <RGBmatrixPanel.h>
// This #include statement was automatically added by the Particle IDE.
#include <Adafruit_mfGFX.h>
// testshapes demo for Adafruit RGBmatrixPanel library.
// Demonstrates the drawing abilities of the RGBmatrixPanel library.
// For 32x32 RGB LED matrix:
// http://www.adafruit.com/products/607
// Written by Limor Fried/Ladyada & Phil Burgess/PaintYourDragon
// for Adafruit Industries.
// BSD license, all text above must be included in any redistribution.
#include <string>
#include "math.h"
// Modify for version of RGBShieldMatrix that you have
// HINT: Maker Faire 2016 Kit and later have shield version 4 (3 prior to that)
//
// NOTE: Version 4 of the RGBMatrix Shield only works with Photon and Electron (not Core)
#define RGBSHIELDVERSION 4
/** Define RGB matrix panel GPIO pins **/
#warning "old shield"
#define CLK D6
#define OE D7
#define LAT A4
#define A A0
#define B A1
#define C A2
#define D A3
/****************************************/
RGBmatrixPanel matrix(A, B, C, D, CLK, LAT, OE, true, 32);
//int buttonPin = D3;
// int servoPin = A3;
// Servo myServo;
// int servoPos = 0;
long lastPublishedAt = 0;
// this is the time delay before we should publish a new event
// from this device
int publishAfter = 10000;
int state = 0; //off mode
String message = "";
int textX = matrix.width();
int textMin = sizeof(message) * -15;
int hue = 0;
int count = 0;
int intdata = 2;
// myServo.write( 180 );
int8_t ball[3][4] = {
{ 3, 0, 1, 1 }, // Initial X,Y pos & velocity for 3 bouncy balls
{ 17, 15, 1, -1 },
{ 27, 4, -1, 1 }
};
static const uint16_t ballcolor[3] = {
0x0080, // Green=1
0x0002, // Blue=1
0x1000 // Red=1
};
void setup() {
matrix.begin();
matrix.setTextWrap(false); // Allow text to run off right edge
matrix.setTextSize(2);
Particle.subscribe( "diot/2019/smartstudio/supporter" , handleSharedEventPrint );
Particle.subscribe( "diot/2019/smartstudio/feelometer" , handleSharedEvent );
}
void loop()
{
if (state == 0)
{
if (intdata >= 1 && intdata <= 3)
{
message = "It's been a good dayyy!!!";
byte i;
// Clear background
matrix.fillScreen(0);
//Bounce three balls around
for(i=0; i<3; i++)
{
// Draw 'ball'
matrix.fillCircle(ball[i][0], ball[i][1], 5, ballcolor[i]);
// Update X, Y position
ball[i][0] += ball[i][2];
ball[i][1] += ball[i][3];
// Bounce off edges
if((ball[i][0] == 0) || (ball[i][0] == (matrix.width() - 1)))
ball[i][2] *= -1;
if((ball[i][1] == 0) || (ball[i][1] == (matrix.height() - 1)))
ball[i][3] *= -1;
}
// Draw big scrolly text on top
matrix.setTextColor(matrix.ColorHSV(hue, 255, 255, true));
// matrix.setTextColor(matrix.Color888(66, 0, 0, true));
matrix.setCursor(textX, 8);
matrix.print(message);
//Move text left (w/wrap), increase hue
if((--textX) < textMin) textX = matrix.width();
hue += 7;
if(hue >= 1536) hue -= 1536;
// Update display
matrix.swapBuffers(false);
delay(50); // Slow down animation
}
else if (intdata > 3)
{
message = "Hey studio needs some love!";
byte i;
// Clear background
matrix.fillRect(0, 0, 32, 32, matrix.Color333(0,0,3));
// //Bounce three balls around
// for(i=0; i<3; i++)
// {
// // Draw 'ball'
// matrix.fillCircle(ball[i][0], ball[i][1], 5, ballcolor[i]);
// // Update X, Y position
// ball[i][0] += ball[i][2];
// ball[i][1] += ball[i][3];
// // Bounce off edges
// if((ball[i][0] == 0) || (ball[i][0] == (matrix.width() - 1)))
// ball[i][2] *= -1;
// if((ball[i][1] == 0) || (ball[i][1] == (matrix.height() - 1)))
// ball[i][3] *= -1;
// }
// Draw big scrolly text on top
matrix.setTextColor(matrix.ColorHSV(151, 151, 151, true));
matrix.setCursor(textX, 8);
matrix.print(message);
//Move text left (w/wrap), increase hue
if((--textX) < textMin) textX = matrix.width();
// hue += 7;
// if(hue >= 1536) hue -= 1536;
// Update display
matrix.swapBuffers(false);
delay(50); // Slow down animation
}
}
}
// A character array that contains the data published in the event we're responding to.
void handleSharedEventPrint(const char *event, const String data)
{
state=1;
message = data;
matrix.fillScreen(0);
for (int ii=0; ii<500; ii++)
{
byte i;
// Clear background
matrix.fillScreen(0);
//Bounce three balls around
for(i=0; i<3; i++)
{
// Draw 'ball'
matrix.fillCircle(ball[i][0], ball[i][1], 5, ballcolor[i]);
// Update X, Y position
ball[i][0] += ball[i][2];
ball[i][1] += ball[i][3];
// Bounce off edges
if((ball[i][0] == 0) || (ball[i][0] == (matrix.width() - 1)))
ball[i][2] *= -1;
if((ball[i][1] == 0) || (ball[i][1] == (matrix.height() - 1)))
ball[i][3] *= -1;
}
// Draw big scrolly text on top
matrix.setTextColor(matrix.ColorHSV(hue, 255, 255, true));
matrix.setCursor(textX, 8);
matrix.print(message);
//Move text left (w/wrap), increase hue
if((--textX) < textMin) textX = matrix.width();
hue += 7;
if(hue >= 1536) hue -= 1536;
// Update display
matrix.swapBuffers(false);
delay(50); // Slow down animation
}
state=0;
}
void handleSharedEvent(const char *event, const char *data)
{
int intdata = data - "0";
}
Click to Expand
In the presentation, we had feedback that sometimes people may not want to be called out when they are upset. In the future, we imagine this device could be something movable and more private instead of a board sitting in the studio. It could be something like the Anki Vector robot when someone sends a message to support another person, the robot can goes to that person and give an interaction, such as a poke or a high five. So that it doesn't require a lot of active attention from the person being supported and it can be more private to them.
For the current device, there are two things we could work on for the next step. First, giving the users the option to choose to send a public message and private message. The public message could be displayed on Silver Lining and the private message could be sent and printed in their lockers. Second, when sending a message to Silver Lining, no matter who the receiver is it will be displayed in one device. But when it comes to printing it in their locker, there should be a way to only print it out in only the receiver's locker.
Throughout the two-week process, we confronted and overcame lots of technical obstacles. We have acknowledged quality of hardware quality is critical in building IoT products. On the other hand of design, we also put a lot of thoughts in designing an interaction that is intuitive and inviting for students to think of supporting each other. Our final idea is to show people's names and support messages on a cloud-shape screen, with a witty animation. After the pitch, we received some insightful feedback of rethinking the idea of displaying names because people's mood is subtle and we might misinterpret other's mood which could end up embracing them. We definitely will keep thinking of what is a more human way to perceive and express feelings in a more ambient way.
A hands-on introductory course exploring the Internet of Things and connected product experiences.
To facilitate a supportive studio environment.
March 8th, 2019