49713 Designing for the Internet of Things
· 16 members
A hands-on introductory course exploring the Internet of Things and connected product experiences.
Found in DIoT - Augmented Objects
An ambient device that not only helps you prepare food just like your mom but also enables you to cook with your mom while staying thousands of miles away!
Our stakeholder is a Ph.D. student, Sruthi. She's an extrovert and enjoys having friends over. When Sruthi is cooking she is usually on the phone with her mother who guides her through the process. Her mother will often say “Sruthi now put in a pinch of chilly powder and some salt”. Sruthi is left confused. She doesn't know the quantity that represents a pinch. She often ends up using too much or too little and the food tastes very different from the way her mother makes it. This makes her feel frustrated and disappointed.
How might we enhance Sruthi's cooking experience?
Our goal for this project was to create a way for a mother to teach her daughter how to cook while providing them with a connected, ambient experience across a long distance. We planned to do this by targetting the issue of measuring spices, which Sruthi stated were the most essential aspect of her mothers' food.
We conceptualized an enchanted spice spoon that would -
At first, we planned on using an FSR sensor to detect the amount of spice based on the weight. However, when prototyping we soon realized that the FSR is not sensitive enough for the weight of the spices. This made us pause and evaluate our requirements of what the device must be able to do and the available resources. Based on this evaluation the photoresistor seemed like the perfect fit. We did a quick test and it proved successful.
One of the challenges we faced with the photoresistor was identifying the different types. The studio had two different types of photoresistors with different sensitivities, and we needed to make sure we used the same type of photoresistor for the comparison to work. Another challenge we faced with the photoresistor was the code. We identified specific value ranges to set the conditions for the two spoons. However, once we changed rooms we had to change these ranges in the code to adapt to the lighting conditions of the new room. We fixed this issue by incorporating the feedback we received - first establishing the baseline reading by detecting current lighting, and then setting the conditions algebraically.
Initially, we had planned to use the spice jar itself as a way for the mom to signal her daughter. Some feedback led us in the direction of having a separate stand for the spoon that could be used for this purpose, as it would make that one spoon usable with a broad range of ingredients rather than just the spice in the jar. Further, it would make the spoon a standalone product rather than having to purchase the jar as well.
We created an ambient device that helps Sruthi (our user) prepare food just like her mother. It also allows her to cook with her mother while living thousands of miles apart. Our device aims at connecting people over distances through a shared activity. The device - a set of spoon and stand, is connected over wi-fi and displays information through ambient light
Both mother and daughter have a set. When her mother starts putting the spices in the food i.e. by lifting up the spoon, Sruthi’s enchanted stand changes color. Once Sruthi has lifted the spoon both stands stay at a constant color. This informs her mother that Sruthi is ready to use the spices.
Her mother then intuitively measures out the spices in her spoon. Sruthi follows by scooping up the spices in her spoon. Sruthi’s spoon glows blue if the spice level in the spoon is too low, red if the spice level is too high and green if it’s just right. Once Sruthi has the correct amount of spices in her spoon, her mother’s spoon will glow. This informs her mother that she can now proceed to the next spice. One by one they cook the whole meal together which acts as bonding as well as a teaching exercise.
One particle board was assigned to each of the mother and the daughter. These interacted which each other and lit up in rainbow colours when either the mother or the daughter lifted their spoon to indicate they were ready to cook. In an ideal scenario, the two photocells (one for the mothers' spoon, one for the daughters' spoon) would be on separate particle boards as well, but the limitations associated with publishing events every second would create a delay in transmitting one photocell reading to the other, which would, in turn, affect the functionality of the prototype. So, although particle connectivity has been implemented for the neopixels, the photocells are on a common board for the experience prototype.
//this is code for the Mom.
#include <neopixel.h>
#define PIXEL_PIN D5
#define PIXEL_COUNT 16
#define PIXEL_TYPE WS2812
Adafruit_NeoPixel stripmom = Adafruit_NeoPixel(PIXEL_COUNT, PIXEL_PIN, PIXEL_TYPE); //neopixel initialisation
//initialising photocell
int photopinmom = A1;
int photoreadingmom =0;
//initializing RGB
int ledPin = D3;
String wanttocookmom = "0";
String wanttocookchild = "0";
//initializing FSR
int fsrmom = A0;
int fsrreadingmom =0;
uint32_t n = stripmom.Color(0, 0, 0);
uint32_t w = stripmom.Color(255, 255, 255);
long lastPublishedAt = 0;
// this is the time delay before we should publish a new event
// from this device
int publishAfter = 5000;
int rainbow =0;
int rainbowmomPosition = 0;
void setup() {
pinMode(ledPin, OUTPUT);
Particle.variable("fsrmom", &fsrreadingmom, INT);
Particle.variable("photomom", &photoreadingmom, INT);
Particle.subscribe( "iot/timetocookchild" , handleTimeToCook);
//Particle.subscribe( "iot/stopchild" , handleStopChild);
}
void loop() {
// stripmom.setBrightness(60);
fsrreadingmom = analogRead(fsrmom); //checking whether moms spoon is on the stand or not
photoreadingmom = analogRead(photopinmom);
if(fsrreadingmom<2000) //mom is ready to cook
{ //rainbowmom(30);
wanttocookchild = "1";
publishWantToMom();
digitalWrite(ledPin,HIGH);
}
else if(fsrreadingmom>2000) //mom is not ready to cook
{
wanttocookchild = "0";
publishStopMom();
digitalWrite(ledPin,LOW);
}
if(rainbow==1)
{
rainbowmom(30);
delay(10);
}
}
void publishWantToMom() //publishing "want to cook" to child
{
if( lastPublishedAt + publishAfter < millis() )
{
String eventName = "iot/timetocookmom" + System.deviceID();
Particle.publish( eventName, "wanttocook" );
lastPublishedAt = millis();
}
}
void publishStopMom() //publishing to child if mom doesnt want to cook
{
if( lastPublishedAt + publishAfter < millis() )
{
String eventName = "iot/stopmom" + System.deviceID();
Particle.publish( eventName, "wanttocook" );
lastPublishedAt = millis();
}
}
void handleTimeToCook(const char *event, const char *data) //if daughter is signalling that its time to cook
{ String eventName = String( event ); // convert to a string object
// int value = int(data);
String deviceID = System.deviceID();
if(fsrreadingmom>1000)
{ rainbow=1;
wanttocookmom="0";
}
else
{rainbow=0;
for(int i=0; i<stripmom.numPixels(); i++) {
stripmom.setPixelColor(i,w);
stripmom.show();
}
wanttocookmom="1";
}
if( eventName.indexOf( deviceID ) != -1 ){
return;
}
}
void rainbowmom(uint8_t wait) { //rainbow wheel cycle
uint16_t i;
for(i=0; i<stripmom.numPixels(); i++) {
stripmom.setPixelColor(i, Wheel((i*1+rainbowmomPosition) & 255));
}
stripmom.show();
rainbowmomPosition++;
if( rainbowmomPosition > 255 ){
rainbowmomPosition = 0;
}
}
uint32_t Wheel(byte WheelPos) { //picking colours for the rainbow wheel
if(WheelPos < 85) {
return stripmom.Color(WheelPos * 3, 255 - WheelPos * 3, 0);
}
else if(WheelPos < 170) {
WheelPos -= 85;
return stripmom.Color(255 - WheelPos * 3, 0, WheelPos * 3);
}
else {
WheelPos -= 170;
return stripmom.Color(0, WheelPos * 3, 255 - WheelPos * 3);
}
}
Click to Expand
// This #include statement was automatically added by the Particle IDE.
//This code is for the child
#include <neopixel.h>
#define PIXEL_PIN D5
#define PIXEL_COUNT 16
#define PIXEL_TYPE WS2812
Adafruit_NeoPixel stripchild = Adafruit_NeoPixel(PIXEL_COUNT, PIXEL_PIN, PIXEL_TYPE); //neopixel initialisation
//initialising photocell
int photopinchild = A1;
int photoreadingchild =0;
int photopinmom = A2;
int photoreadingmom = 0;
int momLed = D7;
int momnormal =0;
int childnormal=0;
int momblock=0;
int childblock=0;
//initializing RGB
int redPin = D4;
int greenPin = D3;
int bluePin = D2;
String wanttocookmom = "0";
String wanttocookchild = "0";
#define COMMON_ANODE
//initializing FSR
int fsrchild = A0;
int fsrreadingchild =0;
uint32_t n = stripchild.Color(0, 0, 0);
uint32_t w = stripchild.Color(255, 255, 255);
long lastPublishedAt = 0;
// this is the time delay before we should publish a new event
// from this device
int publishAfter = 5000;
int rainbow =0;
int rainbowchildPosition = 0;
void setup() {
pinMode(redPin, OUTPUT);
pinMode(greenPin, OUTPUT);
pinMode(bluePin, OUTPUT);
pinMode(momLed,OUTPUT);
pinMode(photopinchild,INPUT);
pinMode(photopinmom,INPUT);
Particle.variable("fsrchild", &fsrreadingchild, INT);
Particle.variable("photochild", &photoreadingchild, INT);
Particle.variable("photomom", &photoreadingmom, INT);
Particle.subscribe( "iot/timetocookmom" , handleTimeToCook);//subscribing to function from mom
momnormal = analogRead(photopinmom); //establishing baseline reading for photocell
childnormal = analogRead(photopinchild);
// Particle.subscribe( "iot/stopmom" , handleStopChild);
}
void loop() {
//stripchild.setBrightness(60);
fsrreadingchild = analogRead(fsrchild);
photoreadingchild = analogRead(photopinchild);
photoreadingmom= analogRead(photopinmom);
//setting limits for the photocell
int mn = momnormal;
int mh = momnormal + 300;
int ml = momnormal - 1000;
int cn = childnormal;
int ch = childnormal + 300;
int cl = childnormal - 1000;
if(photoreadingmom>mh)
{
momblock=3;
}
else if(photoreadingmom<ml)
{
momblock =1;
}
else
{
momblock=2;
}
if(photoreadingchild>ch)
{
childblock=3;
}
else if(photoreadingchild<cl)
{
childblock =1;
}
else
{
childblock=2;
}
if(fsrchild<2500) //checking for equal measurements of spice if the spoons are lifted
{
if(childblock == momblock) //just right
{
analogWrite(redPin,255);
analogWrite(bluePin,255);
analogWrite(greenPin,0);
digitalWrite(momLed,HIGH);
}
else if(childblock<momblock)
{
analogWrite(redPin,255);
analogWrite(bluePin,0);
analogWrite(greenPin,255);
digitalWrite(momLed,LOW);
}
else if(momblock<childblock)
{
analogWrite(redPin,0);
analogWrite(bluePin,255);
analogWrite(greenPin,255);
digitalWrite(momLed,LOW);
}
}
if(fsrreadingchild<2500) //checking if child wants to cook
{ //rainbowmom(30);
wanttocookchild = "1";
publishWantToChild();
// analogWrite(redPin,255);
// analogWrite(bluePin,255);
// analogWrite(greenPin,0);
}
else if(fsrreadingchild>2500)
{
wanttocookchild = "0";
publishStopChild();
// analogWrite(redPin,0);
// analogWrite(bluePin,255);
// analogWrite(greenPin,255);
}
if(rainbow==1)
{
rainbowchild(30);
delay(10);
}
}
void publishWantToChild() //publishing to mom if child wants to cook
{
if( lastPublishedAt + publishAfter < millis() )
{
String eventName = "iot/timetocookchild" + System.deviceID();
Particle.publish( eventName, "wanttocook" );
lastPublishedAt = millis();
}
}
void publishStopChild()
{
if( lastPublishedAt + publishAfter < millis() )
{
String eventName = "iot/stopchild" + System.deviceID();
Particle.publish( eventName, "wanttocook" );
lastPublishedAt = millis();
}
}
void handleTimeToCook(const char *event, const char *data) //if daughter is signalling that its time to cook
{ String eventName = String( event ); // convert to a string object
// int value = int(data);
String deviceID = System.deviceID();
if(fsrreadingchild>2500)
{ rainbow=1;
wanttocookchild="0";
}
else
{rainbow=0;
for(int i=0; i<stripchild.numPixels(); i++) {
stripchild.setPixelColor(i,w);
stripchild.show();
}
wanttocookchild="1";
}
if( eventName.indexOf( deviceID ) != -1 ){
return;
}
}
void rainbowchild(uint8_t wait) { //rainbow wheel cycles
uint16_t i;
for(i=0; i<stripchild.numPixels(); i++) {
stripchild.setPixelColor(i, Wheel((i*1+rainbowchildPosition) & 255));
}
stripchild.show();
rainbowchildPosition++;
if( rainbowchildPosition > 255 ){
rainbowchildPosition = 0;
}
}
uint32_t Wheel(byte WheelPos) {
if(WheelPos < 85) {
return stripchild.Color(WheelPos * 3, 255 - WheelPos * 3, 0);
}
else if(WheelPos < 170) {
WheelPos -= 85;
return stripchild.Color(255 - WheelPos * 3, 0, WheelPos * 3);
}
else {
WheelPos -= 170;
return stripchild.Color(0, WheelPos * 3, 255 - WheelPos * 3);
}
}
Click to Expand
Our device at the moment works as a teaching/ interactive device only when both participants are using it at the same time. The user is restricted to using the device/ cook only when the mother is available to cook. The next step would be to have the device remember the different species based on the recipe. This would allow the daughter (user) to cook at any given time.
Our current product is two sets of a spoon and stand. One for the mother and one for the daughter. The mother's spoon is designed to teach/ lead the process and the daughter's spoon is designed to follow the mother's instructions. Taking this project forward it would be interesting to have the teaching process flow both ways - as the daughter learns new recipes, she can teach her mom too.
The feedback we received also stated that this product posed the potential to have an entire suite of similar products.
How to control RGB LED: https://learn.adafruit.com/adafruit-arduino-lesson-3-rgb-leds/arduino-sketch
Some illustrations sources: Freepik.com
Rainbow cycles on a Neopixel: https://codebender.cc/sketch:80438
Circuit diagram: Fritzing
General reference: https://diotlabs.daraghbyrne.me/
As described under the 'Process' section we encountered challenges while figuring out how to measure the spice in the spoon. We first tried with an FSR which wasn't sensitive enough, and then decided to use a photocell instead. After using the photocell, we used feedback provided by our classmates to make them function correctly in any lighting.
We also had an issue while deciding how to detect whether the spoon was on the stand or not. We solved this by using a magnet under an FSR and on the spoon. When the two magnets attract, they put enough force on the FSR to obtain a substantial reading - We got this idea from the team that made the mailbox.
A hands-on introductory course exploring the Internet of Things and connected product experiences.
An ambient device that not only helps you prepare food just like your mom but also enables you to cook with your mom while staying thousands of miles away!
November 24th, 2019