49-713 Designing for the Internet of Things
· 26 members
A hands-on introductory course exploring the Internet of Things and connected product experiences.
Found in Connected Cuisine
By incorporating smell into our memory recipe system, we aim to create an enhanced recollection of those cherished moments.
The device enhances the recipe selection experience by allowing users to receive an olfactory preview of the prepared dish.
When cooking, smell is a powerful preview of how a dish might taste. Photos in a cookbook are very apealing but they can't capture that smell of last year's thanksgiving turkey, the family barbecue on the fourth of July, or Grandma's homemade bread and apple pie. By incorporating smell into our memory recipe system, we aim to create an enhanced recollection of those cherished moments.
Future concepts, could also push and share smells with family members in their own homes.
Where would such as device be located in the kitchen?
We bagan considering existing object inside the kitchen space that already are associated with fumes and smells. In addition we desired to find an object that was noticeable when in use, yet almost completely unnoticed when not in use. The product should not impose on the kitchen space. After much thought, the smoke detector was the strongest candidate as the integrated housing for our device.
Next step, creating scents...
////////////////////////////////////
// ARTICULATE SMELL CODE //
// this is part of an integrated //
// system where a cookbook creates//
// an event that actuates a smell //
// on the photon with this code //
// //
// Date: 5 March 2017 //
// Original Author: BZ //
////////////////////////////////////
//neopixel setup
#include "neopixel.h"
#include <math.h>
// IMPORTANT: Set pixel COUNT, PIN and TYPE
#define PIXEL_PIN D3
#define PIXEL_COUNT 24
#define PIXEL_TYPE WS2812
Adafruit_NeoPixel strip = Adafruit_NeoPixel(PIXEL_COUNT, PIXEL_PIN, PIXEL_TYPE);
//Troubleshooting Variables
int a1=0;
int a2=0;
int a3=0;
int a4=0;
int loop_count = 0;
int event_count = 0;
// Pin Variables
int ledPin;
int controlpin = A5;
int smellPin1 = D0;
int smellPin2 = D1;
int smellPin3 = D2;
// Logic Variables
int a=0; //scheduling variable
int blink_delay; //the time between blinks for the blinking function
int reps; //the amount of blinks in the blinking function
int pwr_off = 0; //the analog value for power off
int fan_time = 10; //the default time the fan turns on (seconds)
int cmd_speed = 100; //the amount of fan speed required (% out of 100)
int last_a = 5; //the number of tasks in the code, this ensure off mode
int numb_pulse = 10; //number of breathing pulses for neopixel
//happens once
void setup()
{
pinMode( ledPin, OUTPUT); //sets pin for blinking
pinMode(controlpin, OUTPUT); //sets pin for the fans
pinMode(smellPin1, OUTPUT); //smell number 1 control pin
pinMode(smellPin2, OUTPUT); //smell number 1 control pin
pinMode(smellPin3, OUTPUT); //smell number 1 control pin
//Setup Neopixel
strip.begin();
strip.show(); // Initialize all pixels to 'off'
//this is the event that will trigeger the smell articulation
Particle.subscribe("bz/articulate_smell", articulate_smell); //test events sent via ifttt text message #1, #2, #3
Particle.subscribe("doit2017/cookbook/pagenumber/preview", articulate_smell); //Preview: event sent from Peter's cookbook
//Particle.subscribe("doit2017/cookbook/pagenumber/cook", articulate_smell); //Cook: event sent from Peter's cookbook
//variable for troubleshooting
Particle.variable("a", &a, INT);
Particle.variable("a1", &a1, INT);
Particle.variable("a2", &a2, INT);
Particle.variable("a3", &a3, INT);
Particle.variable("loop_count", &loop_count, INT);
Particle.variable("event_count", &event_count, INT);
Particle.variable("fan_time", &fan_time, INT);
Particle.variable("fan_speed", &cmd_speed, INT);
Particle.variable("breath_pulse", &numb_pulse, INT);
//this function can be used to force setting for photon
Particle.function("fan_speed", fan_speed);
Particle.function("fan_time", change_fan_time);
Particle.function("restart", restart); //this will reset the "a" to desired value
Particle.function("change_pulse", change_pulse);
}
//repeats
void loop()
{
//This is for troubleshooting, it counts and prints the number of times the loop is run
loop_count=loop_count+1;
screen_print(loop_count);
if (a==0) //this runs upon initializaiton and is only meant to run once
{
blinking(D7, 125, 6);
a= a + last_a;
a1=0;
a2=0;
a3=0;
delay(500);
}
else if (a==1) //this runs when the first receipe is chosen
{
blinking(D7, 250, a); //blinks for the number corresponding to the receipe chosen
digitalWrite(D7, HIGH); //turns the light on during the smell release
digitalWrite(smellPin1, HIGH); //turns smell 1 on the smell release
//fan_control( cmd_speed, fan_time); //turns fans on //fan may not be necessary
//breathing of the neopixel
for( int k = 1; k <= numb_pulse; k++)
{
ledOn();
ledOff();
}
digitalWrite(smellPin1, LOW); //turns smell 1 off
digitalWrite(D7, LOW); //turns the light off after smell
a = a+last_a; //send the code to the else portion of the loop
//Troubleshooting
a1=1;
a2=0;
a3=0;
}
else if (a==2) //this runs when the second receipe is chosen
{
blinking(D7, 250, a);
digitalWrite(D7, HIGH);
digitalWrite(smellPin2, HIGH); //turns smell 2 on the smell release
//fan_control( cmd_speed, fan_time);
//breathing of the neopixel
for( int j = 1; j <= numb_pulse; j++)
{
ledOn();
ledOff();
}
digitalWrite(smellPin2, LOW); //turns smell 1 off
digitalWrite(D7, LOW);
a = a+last_a;
a1=1;
a2=0;
a3=0;
}
else if (a==3) //this runs when the third receipe is chosen
{
blinking(D7, 250, a);
digitalWrite(D7, HIGH);
digitalWrite(smellPin3, HIGH); //turns smell 3 off
//fan_control( cmd_speed, fan_time);
//breathing of the neopixel
for( int m = 1; m <= numb_pulse; m++)
{
ledOn();
ledOff();
}
digitalWrite(smellPin3, LOW); //turns smell 3 off
digitalWrite(D7, LOW);
a = a+last_a;
a1=0;
a2=0;
a3=1;
}
else //this is the default state where the particle waits for a receipe
{
a1=1;
a2=1;
a3=1;
}
}
//Commonly Used Functions
void blinking(int ledPin, int blink_delay, int reps)
{
pinMode( ledPin, OUTPUT);
for (int i =1; i <= reps; i++)
{
digitalWrite( ledPin, HIGH);
delay(blink_delay);
digitalWrite( ledPin, LOW);
delay(blink_delay);
}
}
void fan_control(int pwr_lvl, int duration)
{
pwr_lvl = constrain(pwr_lvl, 0, 100);
int pwr_cmd = map(pwr_lvl, 0, 100, 0, 255); //maps the 0-100% to the analog values required
analogWrite(controlpin, pwr_cmd); // Writes the power of the fan
delay(duration*1000); // How long will the fan will be turned on
analogWrite(controlpin, pwr_off); // Turns off the fan
}
//neopixel Functions
void ledOn(){
int i;
strip.show();
for (int ii = 10 ; ii <100 ; ii = ii + 1){
for(i=0; i< strip.numPixels(); i++) {
strip.setPixelColor(i, 0, ii, 0.8*ii);
}
strip.show();
delay(15);
}
}
// for switch off
void ledOff(){
int i;
strip.show();
for (int ii = 100 ; ii >= 0 ; ii = ii - 1){
for(i=0; i< strip.numPixels(); i++) {
strip.setPixelColor(i, 0, ii, 0.8*ii);
}
strip.show();
delay(15);
}
}
void heartbeat() {
int i;
strip.show();
delay (20);
float n = 0.2;
int x = 3;
for (int ii = 1 ; ii <200 ; ii = ii + x){
for(i=0; i< strip.numPixels(); i++) {
strip.setPixelColor(i, ii, n*ii, 0);
}
strip.show();
delay(3);
}
x = 3;
for (int ii = 200 ; ii > 100 ; ii = ii - x){
for(i=0; i< strip.numPixels(); i++) {
strip.setPixelColor(i, ii, n*ii, 0);
}
strip.show();
delay(3);
}
delay(30);
x = 6;
for (int ii = 1 ; ii <255 ; ii = ii + x){
for(i=0; i< strip.numPixels(); i++) {
strip.setPixelColor(i, ii, n*ii, 0);
}
strip.show();
delay(3);
}
delay (20);
x = 6;
for (int ii = 255 ; ii > 1 ; ii = ii - x){
for(i=0; i< strip.numPixels(); i++) {
strip.setPixelColor(i, ii, n*ii, 0);
}
strip.show();
delay(6);
}
delay (200);
}
void breath( ){
float n = 0.4;
float val = (exp(sin(millis()/1300.0*M_PI)) - 0.36787944)*108.0;
//Serial.println( val );
uint16_t i;
uint32_t c = strip.Color(val, n*val, 0);
for(i=0; i< strip.numPixels(); i++) {
strip.setPixelColor(i, c );
}
strip.show();
delay (10);
}
//Print to Serial Example
void screen_print(int var1)
{
Serial.print("---"); Serial.print(var1); Serial.print("---");
}
//Event Function Example
void articulate_smell(const char *event, const char *data)
{
//This gets the event name and event data and transforms it into integers so
//we can work with them.
String generic_event = event;
int event_name = generic_event.toInt();
String generic_data = data;
String f = String(generic_data);
int event_data = generic_data.toInt();
blinking(D7, 30, 5); //this flashes to show that an event was received
//Logic for Function
event_count = event_count + 1; //counts the number of event performed for troubleshooting
//This check the last character of the string passed in the event data
//and will trigger different portions of the may loop code
if( f.endsWith("1") )
{
a = 1;
Particle.publish("bz/test_plz", "1"); //troubleshooting
}
else if( f.endsWith("2"))
{
a = 2;
Particle.publish("bz/test_plz", "2");
}
else if( f.endsWith("3"))
{
a = 3;
Particle.publish("bz/test_plz", "3");
}
else
{
a = 4;
Particle.publish("bz/test_plz", "4");
}
}
//Particle Function Example
int restart( String command)
{
a = command.toInt();
return 1;
}
int change_fan_time( String command)
{
fan_time = command.toInt();
return 1;
}
int fan_speed( String speed ) //must return type int, and take an argument type string
{
int cmd_speed = speed.toInt();
return 1;
}
int change_pulse( String command)
{
numb_pulse = command.toInt();
return 1;
}
Click to Expand
A hands-on introductory course exploring the Internet of Things and connected product experiences.
By incorporating smell into our memory recipe system, we aim to create an enhanced recollection of those cherished moments.
March 6th, 2017