//Date - 03/06/2019 - Feel-o-Meter. Contributors: Ranveer Katyal, Lama Al Flauji, and Shawn Koid
//Idea: The follwoing code was written to implement Feel-o-meter. Features:
//1. Stores the mood of the user through a button press
//2. Provides the feedback to the user through breathing neopixels
//3. Calculates the average mood of the cohort and lights up the neopixels in the gradient range from Red(very stressed) to purple(neutral) to blue (very happy)
//4. The Particle device publishes: 1. the average mood data, 2. RGB Values of the neopixel
//5. Actions: 1. triggers an SMS to the admin if the 80% of the cohort is Sad or Very Sad; 2. Stores the avergae mood data changes in a Google Sheet
// This #include statement was automatically added by the Particle IDE.
#include <neopixel.h>
// IMPORTANT: Set pixel COUNT, PIN and TYPE
#define PIXEL_PIN D7
#define PIXEL_TYPE WS2812
#define PIXEL_COUNT 150
long lastPublishedAt = 0;
int publishAfter = 10000;
int pushVHappyButton = D2;
int pushHappyButton = D3;
int pushNeutralButton = D4;
int pushSadButton = D5;
int pushVSadButton = D6;
int vHStateOld = HIGH;
int HStateOld = HIGH;
int NStateOld = HIGH;
int sStateOld = HIGH;
int vSStateOld = HIGH;
int feelState[5] = {0,0,0,0,0};
uint16_t i = 0;
uint32_t c;
int red[3] = {255,0,0};
int redPurple[3] = {187,0,62};
int purple[3] = {125,0,125};
int bluePurple[3] = {62,0,187};
int blue[3] = {0,0,255};
int Pxcolor[3];
int totalPress;
float feelAvg;
float lastAvg=0;
int totalStressCount;
int emailFlag = 0;
String moodColor;
Adafruit_NeoPixel strip = Adafruit_NeoPixel(PIXEL_COUNT, PIXEL_PIN, PIXEL_TYPE);
String sharedEventName = "diot/2019/smartstudio/";
String drivePublishEvent = "feelometer_drive/";
String emailPublishEvent = "feelometer_email/";
void setup() {
Particle.subscribe( sharedEventName , handleSharedEvent );
pinMode(pushVHappyButton, INPUT_PULLUP);
pinMode(pushHappyButton, INPUT_PULLUP);
pinMode(pushNeutralButton, INPUT_PULLUP);
pinMode(pushSadButton, INPUT_PULLUP);
pinMode(pushVSadButton, INPUT_PULLUP);
strip.begin();
strip.show(); // Initialize all pixels to 'off'
}
void loop() {
int vHState = digitalRead(pushVHappyButton);
int HState = digitalRead(pushHappyButton);
int NState = digitalRead(pushNeutralButton);
int sState = digitalRead(pushSadButton);
int vSState = digitalRead(pushVSadButton);
//Detect which button was pressed
if (vHState != vHStateOld){
if(vHState == LOW){
feelState[0] = feelState[0] + 1; //updates the count of the feeling state
pixelBreath(c);
delay(50);
}
else{
vHState = HIGH;
}
} else if (HState != HStateOld){
if(HState == LOW){
feelState[1] = feelState[1] + 1; //updates the count of the feeling state
pixelBreath(c);
delay(50);
}
else{
HState = HIGH;
}
} else if (NState != NStateOld){
if(NState == LOW){
feelState[2] = feelState[2] + 1; //updates the count of the feeling state
pixelBreath(c);
delay(50);
}
else{
NState = HIGH;
}
}else if (sState != sStateOld){
if(sState == LOW){
feelState[3] = feelState[3] + 1; //updates the count of the feeling state
pixelBreath(c);
delay(50);
}
else{
sState = HIGH;
}
} else if (vSState != vSStateOld){
if(vSState == LOW){
feelState[4] = feelState[4] + 1; //updates the count of the feeling state
pixelBreath(c);
delay(50);
}
else{
sState = HIGH;
}
}
vHStateOld = vHState;
HStateOld = HState;
NStateOld = NState;
sStateOld = sState;
vSStateOld = vSState;
//calculate the weighted average to determine the average mood
lastAvg = feelAvg;
feelAvg = ((1*feelState[0]) + (2*feelState[1])+ (3*feelState[2]) + (4*feelState[3]) + (5*feelState[4]))/(feelState[0]+feelState[1]+feelState[2]+feelState[3]+feelState[4]);
//calculate the gradient hue RGB values scaled based on the average mood for neopixel
Pxcolor[0]=(blue[0]*feelState[0]+bluePurple[0]*feelState[1]+purple[0]*feelState[2]+redPurple[0]*feelState[3]+red[0]*feelState[4])/(feelState[0]+feelState[1]+feelState[2]+feelState[3]+feelState[4]);
Pxcolor[1]=(blue[1]*feelState[0]+bluePurple[1]*feelState[1]+purple[1]*feelState[2]+redPurple[1]*feelState[3]+red[1]*feelState[4])/(feelState[0]+feelState[1]+feelState[2]+feelState[3]+feelState[4]);
Pxcolor[2]=(blue[2]*feelState[0]+bluePurple[2]*feelState[1]+purple[2]*feelState[2]+redPurple[2]*feelState[3]+red[2]*feelState[4])/(feelState[0]+feelState[1]+feelState[2]+feelState[3]+feelState[4]);
//light up neopixel
c=strip.Color(Pxcolor[0], Pxcolor[1], Pxcolor[2]);
strip.show();
delay( 50 );
totalPress = (feelState[0]+feelState[1]+feelState[2]+feelState[3]+feelState[4]);
//Publish event to trigger SMS if 80% of class is feeling Sad or Very sad
totalStressCount = feelState[3]+feelState[4];
if(totalStressCount>10 && emailFlag!=1){
publishEmail( String(totalStressCount));
emailFlag=1;
}
//Reset counters after 50 preses
if(totalPress>50){
feelState[0] = 0;
feelState[1] = 0;
feelState[2] = 0;
feelState[3] = 0;
feelState[4] = 0;
emailFlag=0;
}
//publish RGB values of the neo pixel
moodColor = "R"+ String(Pxcolor[0]) + "G" + String(Pxcolor[1]) + "B" + String(Pxcolor[2]);
publishMyEvent(String(feelAvg), moodColor);
if (feelAvg != lastAvg)
publishDriveEvent(String(feelAvg));
delay(500);
}
void publishMyEvent(String avgMood, String pxMoodColor)
{
// 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.
// This will build 'diot/2019/smartstudio/myEvent/A13231245345A078'
String eventName = sharedEventName + "feelometer_avg/" + System.deviceID();
String eventNamePxColor = sharedEventName + "feelometer_PxColor/" + 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, avgMood );
// And this will get shared out to all devices using this code
Particle.publish( eventNamePxColor, pxMoodColor );
// we just pubished so capture this.
lastPublishedAt = millis();
}
}
void publishDriveEvent( String avgMood)
{
// 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.
// 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.
// This will build 'diot/2019/smartstudio/myEvent/A13231245345A078'
String eventName = sharedEventName + drivePublishEvent + 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, avgMood );
// And this will get shared out to all devices using this code
// we just pubished so capture this.
//lastPublishedAt = millis();
}
void publishEmail( String totalStressC)
{
// 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.
// 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.
// This will build 'diot/2019/smartstudio/myEvent/A13231245345A078'
String eventName = sharedEventName + emailPublishEvent + 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, "Email Sent & " + totalStressC);
// 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)
{
String eventName = String( event ); // convert to a string object
String deviceID = System.deviceID();
if( eventName.indexOf( deviceID ) != -1 ){
return;
} else {
//pixelLit(count); // Lights up the Pixel sent byt the other device
}
}
//for the breathing feedback of neopixel
void pixelBreath(int c){
for(int j=0;j<3;j++){
for(int i=0;i<strip.numPixels();i++){
strip.setPixelColor(i, 0,0,0 );
}
strip.show();
delay(150);
for(int k=0;k<strip.numPixels();k++){
strip.setPixelColor(k, c );
}
strip.show();
delay(150);
}
}
Click to Expand
Content Rating
Is this a good/useful/informative piece of content to include in the project? Have your say!
You must login before you can post a comment. .