Kitche.Net of Things: Connected Scent

Made by Macarena Tabilo, ssakhalk, Brandon Zepeda, Dan Porter and Pengyuan Huang

Found in Connected Cuisine

By incorporating smell into our memory recipe system, we aim to create an enhanced recollection of those cherished moments.

0

Functionality Objective

The device enhances the recipe selection experience by allowing users to receive an olfactory preview of the prepared dish. 

Why Scent?

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.

0
0

Design Process

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...

0

Exploring Scent Generation Methods


0

Method 1. Boiling

0

Method 2. Fanning Scented Oils

0

Method 3 (Selected Method). Aromatic Misting

0

Integrating an Aromatic Mister into a Smoke Detector-styled Body

0
0

Housing Design and Prototyping

0

Material and Physical Design: MDF > Acrylic                     

Interactive Design: Light Feedback

0
0

Bill of Materials

Final Prototype included the following materials:

  • 3x Portable Humidifiers with USB connection
  • Neopixel Ring
  • 3x Fragrance Oils & bottles
  • 4 Batteries (summing between 4.8-6V)
  • Another Power Source (battery pack)
  • TIP 120 Transistors
  • 3 1N4001 diode
  • 3x 10K resistors 
  • Jumping Wires


0

Breadboard Wiring

0

Particle Code

0
////////////////////////////////////
//      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
x
Share this Project

Courses

49-713 Designing for the Internet of Things

· 26 members

A hands-on introductory course exploring the Internet of Things and connected product experiences.


Focused on
About

By incorporating smell into our memory recipe system, we aim to create an enhanced recollection of those cherished moments.

Created

March 6th, 2017