0

Project Goal

Our project goal is to enhance the user experience of ordering and delivering DimSum in a Chinese brunch context.  


0

Design Concept

Dim Sum restaurant is a traditional place for Chinese elder people to spend hours hanging out with friends or families. The way ordering food works is there are food carts that keep moving around the restaurant with variety of Dim Sums and the customers pick what they want. Our mission was to make this ordering experience enjoyable and playful.  So we decided to use two panda dolls to mimic the interaction between the customers and cart. Each customer is provided with a table panda, that upon pressing the belly, will raise its arm and turn on the electromagnet. This signifies the customer needs more food, and the cart panda points to the closest table panda that has the arm raised. 

0
Concept Sketch
Pandatalk concept design Menghui Hu (2017)
0

Design Process

0
Problem Definition and ideation
Pandatalk problem description Daksh, Sanjay and Menghui (2017)
0
Final Concept and Materials required
File 002 Sanjay, Daksh and Menghui (2017)
0

Input and Output

Input:

Table panda belly button press

Electromagnetic waves to magnetometer

Output:

Cart panda box led indicator

Table panda arm raise

Table panda head nod

0

Bill of Materials

Photons - x 2

Breadboard - x 2

Electromagnet - x 1

Panda stuffed dolls - x 2

Magnetometer - x 1

Wooden box - x 2

Servo motor - x 3

PN2222 Transistor - x 1

1N4001 diode - x 1

270 Ω Resistor (red, purple, brown stripes) - x 1

Led - x 1

Push button - x 1

Lever button - x 1

Lego arm and head assembly



0

Output

0

Table Panda Components

0
Circuit diagram for Table Panda
2017 03 08 12 41 55 tablepanda.fzz    fritzing    breadboard view Sanjay (2017)
0
Code for Table Panda
int armServoPin = D2;
int headServoPin = D3;
//int ledPin = D2;
int buttonPin = D0;
int electroMagPin = D1;
//int buttonPinArmDown = D1 ;
Servo pandaArmServo;
Servo pandaHeadServo;
int buttonState = LOW;
int servoPos = 50;
int magstrength = 255;
//
bool shouldDoNod = false;
bool isArmUp = false;

void setup(){
  Serial.begin(9600);
  pandaArmServo.attach(armServoPin); //Attaching Arm servo pin to Arm servo
  pandaHeadServo.attach(headServoPin); // Attaching Head servo pin to Head servo
  pinMode(buttonPin , INPUT_PULLUP); //defining pin Mode
  pinMode(electroMagPin, OUTPUT); // defining electro mag output pin
  /*Particle.function("servo", servoControl);*/
  /*Particle.variable( "Nod" , &Nod , INT );*/
  Particle.subscribe( "diot2017/mashedpotatoes/panda/nod", Nodding );
}

void loop(){

  if( shouldDoNod )
  {
    doNod( );
    shouldDoNod = false;
  }

  int currentButtonState = digitalRead( buttonPin );

  if( buttonState == HIGH && buttonState != currentButtonState ) // Enter only if the button is pushed
  {
      Serial.println("Pressed");
      isArmUp = !isArmUp;
  }

  buttonState = currentButtonState;

  if( isArmUp && servoPos < 100 ){
    // Check if arm is up or down
    servoPos = 100 ; // if arm down, make the new servo position 150 (up)
    pandaArmServo.write( servoPos ); // update servo position
    Serial.println("Arm DOWN");
    analogWrite(electroMagPin, magstrength); // switch the electro magnet ON

    delay( 1000 );
  }else if( !isArmUp && servoPos > 50 ){
    servoPos = 50 ; // if arm up, make the new servo position 50 (down)
    pandaArmServo.write( servoPos ); // update servo position
    Serial.println("Arm UP");
    Particle.publish("diot2017/mashedpotatoes/panda/LedOn");
    digitalWrite(electroMagPin, 0); // switch OFF the electro magnet
    delay( 1000 );


  }

  delay( 50 );
}

void doNod( )
{
  for (int i=0; i< 5; i++ ) // loop to nod head 5 times
  {
    Serial.println("Head UP");
    pandaHeadServo.write(50);
    delay(200);
    Serial.println("Head DOWN");
    pandaHeadServo.write (15);
    delay(200);
  }
}

/*int servoControl( String command ) // Panda head nodding function
{
  int n = command.toInt();
  Serial.println("DO NOD");
  if (n == 1){
    for (int i=0; i< 5; i++ ) // loop to nod head 5 times
    {
      Serial.println("Head UP");
      pandaHeadServo.write (90);
      delay(2000);
      Serial.println("Head DOWN");
      pandaHeadServo.write (15);
      delay(1000);
    }
  }
  return 1;
}*/

int Nodding( const char *event, const char *data ) // Panda head nodding function
{
  Serial.println("DO NOD");
  shouldDoNod = true;
  return 1;
}
Sanjay (2017) Click to Expand
0

Cart Panda Components

0
Circuit diagram for Cart Panda
2017 03 08 17 40 36 cart panda.fzz    fritzing    breadboard view Daksh (2017)
0
Code for Cart Panda
/*
 * MotorKnob
 *
 * A stepper motor follows the turns of a potentiometer
 * (or other sensor) on analog input 0.
 *
 * http://www.arduino.cc/en/Reference/Stepper
 * This example code is in the public domain.
 */
 /*
 VIN - this is the power in pin, give it 3-5VDC. It is reverse-polarity protected. Use the same voltage as you do for the controlling microcontroller's logic. For an Arduino, 5V is best.
 GND - this is the common power and data ground pin
 3vo - This is the 3.3V output from the onboard regulator. It will be at 3.3V and you can grab up to 100mA from this to power other items
 SDA and SCL - these are the I2C data and clock pins used to send and receive data from the module to your microcontroller. There are 10K pullups on these pins to the VIN pin. You can connect these pins to 5V I2C lines, there are level shifters on board to safely bring the pins down to 3V
 RDY - this it the 'data ready' pin output. If you want to stream data at high speed (higher than 100 times a second) you may want to listen to this pin for when data is ready to be read. Check the datasheet for more details about using the RDY pin, we don't use it because we don't read that fast!
 */
 /*
 WIRING FOR PHOTON
 VIN -> 3V3 (regulated)
 GND -> GND
 3v0 -> NONE
 SDA -> D0 - YOU MUST USE THIS PIN
 SCL -> D1 - YOU MUST USE THIS PIN
 RDY -> NONE
 */
#include <Adafruit_Sensor.h>
#include <Adafruit_HMC5883.h>
Adafruit_HMC5883_Unified mag = Adafruit_HMC5883_Unified(12345);
int sPin = D2;
Servo myServo;
float angle = 0;
int ledPin = A1;
int switchPin = D3;
bool shouldToggleLed = false;
void setup() {
  Serial.begin(9600);
  myServo.attach(sPin);
  Serial.println("HMC5883 Magnetometer Test"); Serial.println("");
  /* Initialise the sensor */
  if(!mag.begin())
  {
    /* There was a problem detecting the HMC5883 ... check your connections */
    Serial.println("Ooops, no HMC5883 detected ... Check your wiring!");
    while(1);
  }
  /* Display some basic information on this sensor */
  displaySensorDetails();
  pinMode( switchPin , INPUT_PULLUP); // sets pin as input for switch
  pinMode( ledPin , OUTPUT ); // sets pin as output for LED
  Particle.subscribe("diot2017/mashedpotatoes/panda/LedOn", Led);
}
void loop() {
  if( shouldToggleLed )
  {
     digitalWrite( ledPin, HIGH );
     shouldToggleLed = false;
  }
  else
  {
     digitalWrite( ledPin, LOW );
  }
  /* Get a new sensor event */
   sensors_event_t event;
   mag.getEvent(&event);
   /* Display the results (magnetic vector values are in micro-Tesla (uT)) */
   Serial.print("X: "); Serial.print(event.magnetic.x); Serial.print("  ");
   Serial.print("Y: "); Serial.print(event.magnetic.y); Serial.print("  ");
   Serial.print("Z: "); Serial.print(event.magnetic.z); Serial.print("  ");Serial.println("uT");
   // Hold the module so that Z is pointing 'up' and you can measure the heading with x&y
   // Calculate heading when the magnetometer is level, then correct for signs of axis.
   float heading = atan2(event.magnetic.y, event.magnetic.x);
   // Once you have your heading, you must then add your 'Declination Angle', which is the 'Error' of the magnetic field in your location.
   // Find yours here: http://www.magnetic-declination.com/
   // Mine is: -13* 2' W, which is ~13 Degrees, or (which we need) 0.22 radians
   // If you cannot find your Declination, comment out these two lines, your compass will be slightly off.
   float declinationAngle = 0.22;
   heading += declinationAngle;
   // Correct for when signs are reversed.
   if(heading < 0)
     heading += 2*PI;
   // Check for wrap due to addition of declination.
   if(heading > 2*PI)
     heading -= 2*PI;
   // Convert radians to degrees for readability.
   float headingDegrees = heading * 180/M_PI;
   Serial.print("Heading (degrees): "); Serial.println(headingDegrees);
   delay(500);
   //Panda Rotation
   if ( headingDegrees > 180) {
     angle = 360 - headingDegrees;
     }
   else {
     angle = headingDegrees;
     }
  myServo.write (angle);
  Serial.print("Rotation Angle (degrees): "); Serial.println(angle);
  delay(1000);
  //20 and 60 for arm
  //acknowledgement
  int buttonState = digitalRead(switchPin);
  if( buttonState == LOW )
  {
     Particle.publish("diot2017/mashedpotatoes/panda/nod");
     Serial.println ("It should nod");
  }
}
void displaySensorDetails(void)
{
  sensor_t sensor;
  mag.getSensor(&sensor);
  Serial.println("------------------------------------");
  Serial.print  ("Sensor:       "); Serial.println(sensor.name);
  Serial.print  ("Driver Ver:   "); Serial.println(sensor.version);
  Serial.print  ("Unique ID:    "); Serial.println(sensor.sensor_id);
  Serial.print  ("Max Value:    "); Serial.print(sensor.max_value); Serial.println(" uT");
  Serial.print  ("Min Value:    "); Serial.print(sensor.min_value); Serial.println(" uT");
  Serial.print  ("Resolution:   "); Serial.print(sensor.resolution); Serial.println(" uT");
  Serial.println("------------------------------------");
  Serial.println("");
  delay(500);
}
void Led (const char *event,  const char *data)
{
  Serial.println(  "LED Event triggered");
    // turn the LED On
  //  analogWrite( ledPin, HIGH);
  shouldToggleLed = true;
}
/*void Rotate()
{
  delay()
}*/
Daksh (2017) Click to Expand
0
Introducing DimSum Pandas
Sanjay, Daksh and Menghui (2017)
0

Reflection

We as a group had difficulty to get the magnetometer sensor to detect the electromagnet as it was very noisy and hard to triangulate the source of the magnetic field accurately. 

If we had more time we would explored IR sensor and triangulation as shown in this Cornell project https://people.ece.cornell.edu/land/courses/ece4760/FinalProjects/s2004/rd73/476finalpro.htm 

or hack a indoor navigation systems like;

https://www.infsoft.com/solutions/indoor-navigationlike

http://www.wifarer.com/

It was hard to get the nodding and panda arm raise as we expected. Couple of reasons was the torque of the servo motor was not enough and the stuffed doll form factor was resisting as we repurposed it for the proof of concept. If we could have built the panda doll from scratch factoring in the arm and nodding structure we could have got the working more as we wanted. 


0

Next Steps

Make the Panda location and pointing by the cart panda more robust

Make the form factor of the panda movement more robust

Explore how the we can expand this idea to restaurants other than dim sum diners. 

We could also explore ways for the customers to specify the type of food along with the panda belly push. 

Explore ways to predict or communicate demand in real time based on Dim Sums being ordered by customers to the kitchen.

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

~

Created

March 6th, 2017