Found in Connected Cuisine
We've designed a smart door that welcomes front of house staff back in the kitchen only when it's not too busy. If the kitchen is experiencing a back log (more orders coming in than going out), the shutter window on the door will shut providing a subtle cue to LEAVE THE COOKS ALONE. Because afterall, the waiters and waitresses don't need to come back to tell the cooks when it's busy. We assure you, they already know.
When the back log is cleared, the shutter window opens up and the front of the house is again welcome back into the kitchen if they so please.
/*
* Project: Lullz
* Description: An aperture retracts based on restaurant traffic
* Author: Nicholas Stone
* Date: 3/1/2017
* Version: 4
*/
//Timers and Thresholds
bool lullzStatus = false;
int kitchenTraffic = 0;
int prevKitchenTraffic = 0;
const int kitchenTrafficThreshold = 3;
const int lullzKitchenTrafficThreshold = 0;
int trafficTimer = 0;
int antiTrafficTimer = 0;
int publishTimer = 0;
const int timerThresholdMillis = 5000; //5 seconds
const int lullzTimerThresholdMillis = 10000; //10 seconds
const int publishThresholdMillis = 30000; //30 seconds
// Stepper Motor for the aperture
int stepDelay = 100;
int currStepperPos = 0;
int maxStepperPos = 180;
int stepperStepSize = 30;
const int stepperDirPin = D2;
const int stepperStepPin = D1;
const int stepperEnablePin = D3;
// Door Magnet
const int doorMagnetPin = A0;
int doorMagnetReading = 0;
const int doorMagnetThreshold = 700;
const int doorDeBounceMillis = 3000;
const int doorMagnetSampleRateMillis = 300;
// Manual Switch
const int systemSwitchPin = D0;
int systemSwitchValue = 0;
const int systemSwitchSampleRateMillis = 500;
void setup() {
Serial.begin(9600);
pinMode(doorMagnetPin,INPUT);
pinMode(systemSwitchPin,INPUT_PULLUP);
pinMode(stepperStepPin,OUTPUT);
pinMode(stepperDirPin,OUTPUT);
pinMode(stepperEnablePin,OUTPUT);
// Restaurant Subscription
Particle.subscribe("cmu/diot17/StressedOut", kitchenStatus);
//disable stepper
digitalWrite(stepperEnablePin,HIGH);
}
void loop() {
//set timer on 1st iteration
if(trafficTimer == 0) {
antiTrafficTimer = millis();
}
//zero out value for intermediate
if(systemSwitchValue != digitalRead(systemSwitchPin && systemSwitchValue > 0)) {
kitchenTraffic = 0; //zero out the traffic
antiTrafficTimer = millis();
trafficTimer = millis();
}
//monitor switch
systemSwitchValue = digitalRead(systemSwitchPin);
if(systemSwitchValue > 0) { //on
readDoorMagnet();
checkLullz();
delay(doorMagnetSampleRateMillis);
} else {
Serial.println("System Off");
delay(systemSwitchSampleRateMillis);
}
}
void readDoorMagnet() {
doorMagnetReading = analogRead(doorMagnetPin);
//Serial.println(doorMagnetReading);
//door removed from frame, and has been sufficient time since last count
if(doorMagnetReading > doorMagnetThreshold && (kitchenTraffic == 0 || trafficTimer + doorDeBounceMillis < millis())) {
kitchenTraffic++;
//reset traffic timers
trafficTimer = millis();
antiTrafficTimer = millis();
Serial.println("Traffic Increased");
}
//reset if it has been enough time since the last one
if(kitchenTraffic > 0 && trafficTimer + timerThresholdMillis < millis()) {
kitchenTraffic = kitchenTraffic - 1;
prevKitchenTraffic = prevKitchenTraffic - 1;
trafficTimer = millis();
antiTrafficTimer = millis();
Serial.println("Traffic Decreased");
if(currStepperPos > 0) {
//calculate remaining clearance
if(currStepperPos < stepperStepSize)
{
rotateStepper(currStepperPos,0,10);
} else {
rotateStepper(stepperStepSize,0,10);
}
}
}
//if over threshold, and value increased from previous rotation
if(kitchenTraffic >= kitchenTrafficThreshold && kitchenTraffic > prevKitchenTraffic) {
//if still clearance
if(currStepperPos < maxStepperPos) {
//calculate remaining clearance
if(currStepperPos + stepperStepSize > maxStepperPos)
{
rotateStepper(maxStepperPos - currStepperPos,1,10);
} else {
rotateStepper(stepperStepSize,1,10);
}
}
prevKitchenTraffic = kitchenTraffic;
}
return;
}
void checkLullz() {
// publish lullz if below threshold (amound & time) and hasn't published in past ThresholdMillis time period
if(kitchenTraffic <= lullzKitchenTrafficThreshold && antiTrafficTimer + lullzTimerThresholdMillis < millis()
&& publishTimer + publishThresholdMillis < millis())
{
Particle.publish("cmu/diot17/FirstBreather",true);
Serial.println("Published Lullz");
//reset timers
publishTimer = millis();
antiTrafficTimer = millis();
// retract aperture completely
if(currStepperPos !=0) {
rotateStepper(currStepperPos,0,5);
}
}
}
//trigger presence of veggie from event publish by other photon
void kitchenStatus(const char *event,const char *data) {
//completely close aperature
if(currStepperPos < maxStepperPos) {
rotateStepper(maxStepperPos - currStepperPos,1,10);
currStepperPos = maxStepperPos;
}
return;
}
//direction: 0 -- CCW , 1 -- CW
//speed: 1 (fastest) - 10 (slowest)
void rotateStepper(int degrees,int direction,int speed) {
//enable motor
digitalWrite(stepperEnablePin,LOW);
Serial.println("Rotate Stepper");
delay(500);
//handle direction
if(direction == 1) {//CW
digitalWrite(stepperDirPin,LOW);
} else {
digitalWrite(stepperDirPin,HIGH); //CCW
}
int degreeTransform = degrees / 1.8;
//handle speed
if(speed > 10) {
speed = 10;
}
if(speed < 1) {
speed = 1;
}
//create i number of pulses at speed
for(int i = 0; i < degreeTransform; i++) {
digitalWrite(stepperStepPin,HIGH);
delay(speed);
digitalWrite(stepperStepPin,LOW);
delay(speed);
}
//disable motor
digitalWrite(stepperEnablePin,HIGH);
if(direction == 1) {
currStepperPos = currStepperPos + degrees;
} else {
currStepperPos = currStepperPos - degrees;
}
}
Click to Expand
A hands-on introductory course exploring the Internet of Things and connected product experiences.
~
March 5th, 2017