Tea Timer

Author: Yiming Jiao

This Picture is a photo of the this project in prot view. It counstruct with plywood and has screen, 4 botton, moveable part.

Front view of the Tea Timer, without power on, and all the components are positing at off position. 

This project helps me to keep the time to make a cup of tea, and detecting the temperature of the tea. I will be able to set a time between 1 second to 99 minute 59 second. After time set, it will start to counting down, while I can still change the time when it counting down. Once the time count down to 0, the filter will be lift accompany with a beeping. Then it will stay untill the tea temperature cooling below 70 celcies degree. Once it hit 70 celcies degree, it will beeping every 5 second to alarm me to drink the tea. If I press any bottom after the fillter lifted, it will be drop the fillter back to its beginning position.

This image show back of the project. There's not a back close of this, and showing all wires and components out. It is quite mess from back side.

This photo showing the wire connection of this tea timer. It include a DC motor, a speaker, a LCD Screen, 4 bottom, a waterproof thermometer, an arduino, a breadboard, and jump lines.

This picture also shows the back side of it, and also include back side of control board.

Another backview photo of tea timer, showing a clear vision of motor, LCD screen, and bottoms.

This picture is a front view of it, showing tea cup get involve in this machine.

A front view, showing how it attached with tea cup and filter.

Tis picture is a line drawing and redering of the model.

This drawing shows how does the model  built. Constructed in rhino to get to the fabrication.

TeaTimerScreen.mp4

In this video, I show operation of Tea Timer, press left or right botton to switch the digit, press "+" or "-" botton to increase or decrease 1 from current digit. After time set for 10 seconds, it will start to count down. When time reached 0, filter will be lifted with beeping. Then press a button, the fillter will be droped to its original position.

TeaTimerFrontDemo.mp4

In this video, I show operation of Tea Timer in a front view.

TeaTimerSideDemo.mp4

In this video, I show operation of Tea Timer in a side view.

Process

This is a photo showing progress. The arduino connecting the labtop, and connecting to a breadboard.

This photo shows how does the electronic circuit work in a process. It was started using potentialmeter to set the time. However using potentialmeter as a control is not as smooth as I expect, and it is also hard to change after the count down stage.

This image is a line drawing of a early model of the mechanic system.

It was a early stage model of the mechanic system. It originally proposed lifted by lead screw and a set of gears. But due to the complex and hard to work on those material, finally switch to a string pull up system.

This photo is a inner view of top panel. Showing dc motor with modified gear tool.

This photo shows how does the motor sticked on the plywood. Before this arrangement, I experiment some different layout of the motor, and as a result find the most effective layout.

This photo is shoiwng a progressing of wire connection.

After assembly, everthing a hidden behind the sheel, but due to the pin lenght, the back broad is not able to installed.

A image show how this project considered as state machine. There're 6 states, and difference operation will lead to difference states.

The whole system is using an idea of state. The machine should be a a state, and move to another state once it fullfill some prerequest to move.

Discussion

Technical information

/***************************************************************

* Project name: Tea Timer

* Project author: Yiming Jiao

* Project discription:

*     - This project is worked for CMU 60-223 Physical Computing project2

*     - This machine is aiming to help me make tea.

*     1. When it start, I will be able to set a time by using 4 bottons.

*     2. After time seted, it will counting down.

*     3. when time up, the motor will rotate to rise the filter, then a beeping will happen.

*     4. When filter is rised, if temperature of tea gets cooling, beeping will continuing untill any botton pressed.

*     5. Then the motor will down the fillter and back to the beginning.

* Project Pin map:

*    A0: Botton0

*    A1: Botton1

*    A2: Botton2

*    A3: Botton3

*     4: Thermometer

*     8: Buzzer

*     9: H-bridge Enable

*    10: H-bridge IN1

*    11: H-bridge IN2

*

* Reference:

*     H-bridge and DC motor: https://learn.adafruit.com/adafruit-arduino-lesson-15-dc-motor-reversing/arduino-code

****************************************************************/

#include <Key.h>

#include <Keypad.h>

#include <OneWire.h>

#include <DallasTemperature.h>

#include <Servo.h>

#include <Wire.h>

#include <LiquidCrystal_I2C.h>

using namespace std;


LiquidCrystal_I2C screen(0x27, 16, 2);


const int BOTTOMPIN0 = A0;

const int BOTTOMPIN1 = A1;

const int BOTTOMPIN2 = A2;

const int BOTTOMPIN3 = A3;

const int THERMOPIN = 4;

const int MOTOR0 = 9;

const int MOTOR1 = 10;

const int MOTOR2 = 11;


const int THERMPDETECTTIME = 10000;  // thermometer will detect every 10 second

const int PRESSDETECT = 100;

const int MOTORTIME = 1200;

const int TIMESETTING = 10000;

const int TIMESTATE1 = 10000;


int speakerPin = 8;    // define the speaker pin

int frequency = 1000;  // set the frequency in Hertz

int duration = 500;   // set the duration in milliseconds



double temperature;

int setTime[4] = { 0, 0, 0, 0 };

int timePosition = 3;

bool isPress0 = false;

bool isPress1 = false;

bool isPress2 = false;

bool isPress3 = false;

long timeSetting;

bool timeSetted = false;

int timeReduce;

bool teaTime = false;

bool isLift = false;

bool isDown = false;

int state = 0;

unsigned long stateTime;


OneWire oneWire(THERMOPIN);

DallasTemperature sensors(&oneWire);


void setup(void) {

  sensors.begin();

  screen.init();

  screen.backlight();

  screen.home();

  screen.print("Welcome to TEATIMER!");

  delay(1000);

  screen.clear();

  pinMode(BOTTOMPIN0, INPUT);

  pinMode(BOTTOMPIN1, INPUT);

  pinMode(BOTTOMPIN2, INPUT);

  pinMode(BOTTOMPIN3, INPUT);

  pinMode(MOTOR1, OUTPUT);

  pinMode(MOTOR2, OUTPUT);

  pinMode(speakerPin, OUTPUT);

}


// For state need to read botton input

bool readBotton(void) {

  isPress0 = digitalRead(BOTTOMPIN0);

  isPress1 = digitalRead(BOTTOMPIN1);

  isPress2 = digitalRead(BOTTOMPIN2);

  isPress3 = digitalRead(BOTTOMPIN3);

  return ((isPress0 + isPress1 + isPress2 + isPress3) > 0);

}


// For state1, chance time based on press

// I finally decide to keep the setTime array of four ints.

// The reason is if I use second represent time, it will also change its left digit when a carry or borrow happen.

// But I don't want a such influence happen, because it not fit what I expect on interacting with it.

void settingTime(void) {

  if (isPress0) {

    setTime[timePosition] += 1;

    if (timePosition == 2) {

      setTime[timePosition] = setTime[timePosition] % 6;

    } else {

      setTime[timePosition] = setTime[timePosition] % 10;

    }

  }

  if (isPress1) {

    if (timePosition == 2) {

      setTime[timePosition] += 5;

      setTime[timePosition] = setTime[timePosition] % 6;

    } else {

      setTime[timePosition] += 9;

      setTime[timePosition] = setTime[timePosition] % 10;

    }

  }

  if (isPress2) {

    timePosition += 1;

    timePosition = timePosition % 4;

  }

  if (isPress3) {

    timePosition += 3;

    timePosition = timePosition % 4;

  }

}


// include all screen display codes

void screenDisplay(void) {

  screen.setCursor(0, 0);

  screen.print("Current Temp: ");

  screen.setCursor(14, 0);

  screen.print(temperature);

  screen.setCursor(0, 1);

  screen.print("Set Time: ");

  screen.setCursor(10, 1);

  screen.print("          ");

  screen.setCursor(10, 1);

  screen.print(setTime[0]);

  screen.setCursor(11, 1);

  screen.print(setTime[1]);

  screen.setCursor(12, 1);

  screen.print(":");

  screen.setCursor(13, 1);

  screen.print(setTime[2]);

  screen.setCursor(14, 1);

  screen.print(setTime[3]);

  screen.setCursor(0, 2);

  screen.print("              ");

  screen.setCursor(0, 2);

  switch(state){

    case 0:

    case 1:

      screen.print("Set the time");

      break;

    case 2:

      screen.print("Tea is making");

      break;

    default:

      screen.print("Tea is ready");

      break;

  }


  if (timePosition < 2) {

    screen.setCursor(10 + timePosition, 1);

  } else {

    screen.setCursor(11 + timePosition, 1);

  }

  screen.cursor();

}


// For state3, counting down the time

void timeReducing(void) {

  if (millis() - timeReduce > 1000) {

    setTime[3] -= 1;

    if (setTime[3] == -1) {

      setTime[3] = 9;

      setTime[2] -= 1;

      if (setTime[2] == -1) {

        setTime[2] = 5;

        setTime[1] -= 1;

        if (setTime[1] == -1) {

          setTime[1] = 9;

          setTime[0] -= 1;

        }

      }

    }

    timeReduce = millis();

  }

  if (setTime[0] == 0 && setTime[1] == 0 && setTime[2] == 0 && setTime[3] == 0) {

    analogWrite(MOTOR2, 255);

    digitalWrite(MOTOR1, HIGH);

    digitalWrite(MOTOR0, LOW);

    stateTime = millis();

    state = 3;

  }

}


// state0 - start state, waiting for user to set time

void state0(void) {

  if(readBotton()) {

    settingTime();

    stateTime = millis();

    state = 1;

  }

}


// State1 - user is setting the time, recording time after last press. If time is long enough, move to next state.

void state1(void) {

  if(readBotton()) {

    settingTime();

    stateTime = millis();

  } else {

    if (millis() - stateTime >= TIMESTATE1) {

      stateTime = millis();

      state = 2;

    }

  }

}


// state2 - couting down the time. If any press happened, move back. If time up, active the motor and move next.

void state2(void) {

  if(readBotton()) {

    settingTime();

    stateTime = millis();

    state = 1;

  } else {

    timeReducing();

  }

}


// state3 - counting the motor move time. If reached MOTORTIME, stop motor and move next.

void state3(void) {

  if (millis() - stateTime >= MOTORTIME) {

    analogWrite(MOTOR2, 255);

    digitalWrite(MOTOR1, LOW);

    digitalWrite(MOTOR0, LOW);

    tone(speakerPin, frequency, duration);

    stateTime = millis();

    state = 4;

  }

}


// state4 - detecting temperature of tea. If any press happen, act motor down, and move to state 6. If temperature lower than 70C, move to state5.

void state4(void) {

  if(readBotton()) {

    stateTime = millis();

    analogWrite(MOTOR2, 255);

    digitalWrite(MOTOR0, HIGH);

    digitalWrite(MOTOR1, LOW);

    state = 6;

  } else {

    if (temperature <= 70) {

      tone(speakerPin, frequency, duration);

      stateTime = millis();

      state = 5;

    }

  }

}


// state5 - alarming the user. If any press happen, act motor down, and move to state 6.

void state5(void) {

  if(readBotton()) {

    stateTime = millis();

    analogWrite(MOTOR2, 255);

    digitalWrite(MOTOR0, HIGH);

    digitalWrite(MOTOR1, LOW);

    state = 6;

  } else {

    if (millis() - stateTime >= TIMESTATE1) {

      tone(speakerPin, frequency, duration);

      stateTime = millis();

    }

  }

}


// state6 - counting the motor move time. If reached MOTORTIME - 210, stop motor and move to start.

void state6(void) {

  if (millis() - stateTime >= MOTORTIME - 210) {

    analogWrite(MOTOR2, 255);

    digitalWrite(MOTOR1, LOW);

    digitalWrite(MOTOR0, LOW);

    stateTime = millis();

    state = 0;

  }

}


//Identify wich state is now, and move to the state.

void stateIdentify(void) {

  switch (state) {

    case 0:

      state0();

      break;

    case 1:

      state1();

      break;

    case 2:

      state2();

      break;

    case 3:

      state3();

      break;

    case 4:

      state4();

      break;

    case 5:

      state5();

      break;

    case 6:

      state6();

      break;

  }

}


void loop(void) {

  sensors.requestTemperatures();

  temperature = sensors.getTempCByIndex(0);

  stateIdentify();

  screenDisplay();

}