Humidity Monitor


Plotted plants are great choice for indoor decoration offering a sense of liveliness. However, the humidity in people’s rooms may be too low or too high. For example, some tropical plants typically require relatively higher humidity. In addition, it may get very dry during winter, making it difficult for the plotted plants to thrive.


The set-up of the device.

The solution I came up with is a system that monitors the humidity at the proximity of the plant. The system is composed of two separate device. The device on the left is hung on the wall with a fan and a servo arm that holds a spray bottle. The device on the right is a humidifier with a humidity sensor on it.

To demonstrate how the system work, suppose we have a delicate plant that requires misting if the average humidity is below 60% for the past 4 hours. The humidity cannot be over 90% because the plant can be suffocated or harmed by pests. Therefore, every 4 hours the system will check the average humidity and if  it is below 60%, the servo-arm will swing up and down to remind the person in the room to mist the plant. If the humidity level does not change in 5 minutes, the servo-arm will stop and the humidifier will be turned on to increase the humidity and sustain it for a specific period. If the humidity level is over 90%, the fan will work until the humidity is below 90%.

When higher humidity is required, the servo-arm comes in first because manual misting is preferred, which gives the person more awareness of the condition of the  plant. A night mode can be selected and the humidity is regulated autonomously by the system. Data and commands are sent between the two devices through IR transmitter and receiver.

Proof of Concept

The prototype includes a servo motor, a dc motor, a humidity sensor, a red LED, and a power module on the right.


#include <dht.h>
#include <Servo.h>

// Analog Pin sensor is connected to
#define dht_apin A0
#define SERVO_PIN 2
#define LED_PIN 13
#define ENABLE 5
#define DIRA 3
#define DIRB 4

dht DHT;
Servo servo;

//The vairables that define time-flow
const int hour = 8000; //In this time-scale 4 sec represent 1 hour

const int ideal_humid = 60;

//The array that store the humidities
int humidity_Data[48];
int record_digit; //The digit for inputing data into the array
int check_digit; // The digit for checkingg every 2-hour
int check_points = 8; // How many datapoints to check for the checking period

String plant_status;

unsigned long clock_record = 0; // The clock for recording humidity
const int INTERVAL1 = 2000; // milliseconds between each recroding


//Universal clock
bool Universal_clock(String type) {
  if (type == "record") {
    if (millis() >= clock_record) {

      clock_record = millis() + INTERVAL1;

      return true;
    return false;


//Check if the plant need to be mist
void need_mist() {
  int sum = 0;
  int average_humidity;

  for (int i = 0; i < check_points; i ++ ) {
    int d = check_digit + i;
    int humid = humidity_Data[d];
    sum = sum + humid;



  check_digit += check_points;

  //Serial.println("humidity checked");
  average_humidity = sum / check_points;

  if (average_humidity < ideal_humid) {

    plant_status = "dry";


void setup() {
  pinMode(LED_PIN, OUTPUT);

  pinMode(ENABLE, OUTPUT);
  pinMode(DIRA, OUTPUT);
  pinMode(DIRB, OUTPUT);


  Serial.println("DHT11 Humidity & temperature Sensor\n\n");
  delay(200);//Wait before accessing Sensor


void loop() {

  //Record the humidity
  if (Universal_clock("record") == true) {
    humidity_Data[record_digit] = DHT.humidity ;


    if (DHT.humidity >= 90) {
      plant_status = "wet";
      digitalWrite(ENABLE, HIGH);
      digitalWrite(DIRA, HIGH); //one way
      digitalWrite(DIRB, LOW);

    if (plant_status == "wet") {
      //check if it is still wet
      if (DHT.humidity < 90) {
        plant_status = "fine";
         digitalWrite(ENABLE, LOW);
         check_digit = record_digit;


    if (plant_status == "dry") {
      //check if it is still dry
      if (DHT.humidity >= ideal_humid) {
        plant_status = "fine";
        digitalWrite(LED_PIN, LOW);
        check_digit = record_digit;

      else {
        digitalWrite(LED_PIN, HIGH);

    if (record_digit - check_digit == 7) {

    record_digit += 1;


  //Check if the plant is too dry in the past 2 hours

  //Serial.print("Current humidity = ");
  //Serial.print("%  ");
  //Serial.print("temperature = ");
  //Serial.println("C  ");

  //delay(5000);//Wait 5 seconds before accessing sensor again.

  //Fastest should be once every two seconds.



Work, but not too long

With WFH and remote learning, I find it either really hard to focus and keep on getting distracted, or sitting too long in front of my laptop until my back hurts.

Work, but not too long “rewards” you when you sit in front of your laptop for a short period of time, and “warns” you when you sit in front of your laptop for too long.

Consider this example scenario: You tried to get some work done, but you keep going to the kitchen or lying on the couch. And when you finally stayed in front of your laptop for a short period of time, you are rewarded! Now that you got into the momentum, you keep working and working. Hours went by, and by the time you realized that you’ve been sitting too long, your back already hurts.

In my system, the “reward” is a colorful light sequence, and the “warning” is blinking red lights. It uses a button to set the background distance to maximize its portability, and uses ultrasonic to measure the distance.



For demoing purpose, the “reward” period is set to be 5s, and the “warning” period is set to be 15s. But in reality, a 30min “reward” period and a 2h “warning” period are practical.

Before I sit down, I hit the button to get the background distance. Then I sit, there is a “reward” for every “reward” period until I hit the warning period. If I stand up and move away from the laptop, then the timer/cycle restarts.

What’s missing in this video is that warning is only on for a short period of time. Like how you can snooze an alarm, you are snoozing the system when you stay seated, and after another reward period, the system will warn you again.

One flaw of the system is that it requires manually setting the background distance, and it can be easily solved using computer vision to detect whether a face is present. Such solution would require a lot more computing power and much more sophisticated software.


Sometimes we need an animal for emotional support; however, not everyone can afford to have pets! Therefore, I introduce a (part) of my robocat.

For cats, tail is one of the biggest indicator/langauge for how they feel right now.

Unlike dogs, cats wagging their tail indicate that they are agitated. The more they are annoyed, the more they wag their tails. So I created a module of correlation between petting and a tail overtime.

The button stands for a body part. When it is pressed, it. means that the cat is being pet. The LCD monitor shows the state of the cat literally.
The cat is pet for twice (button is pressed twice). The tail wags a little bit.
The cat is pet four times. The tails wags more, but still slowly.
The cat is pet for multiple times now. The cat is now starting to get annoyed.
You pet the cat for too many times! The tails wags rampantly, and now the cat hates you.

But cats, unlike humans, they are fast at forgetting.

After 10 seconds of being mad at you, the cat is now back to where she was.

(in the video, for convinience I set the timer as 3 seconds)

Video demonstration:

Intuitive TV (Volume) Remote


When watching something on TV, the volume we want it to be at is highly dependent on what is on the screen. If there is an action scene, the volume is usually way too loud and needs to be lowered. If the scene is dialogue with some background music, the volume often needs to be raised to understand what is being said. This is something that myself, my family, and my housemates have often faced and leads to us button smashing the remote after certain scene changes.

Proposed Solution:

After raising and lowering the volume three times, the volume automatically goes to the average of the low/high by simply holding the corresponding button for a second thereafter. The volume could still be adjusted from there by pressing the buttons, but being able to consistently go back and forth to a value would make things much more convenient. I chose three times of going back and forth because that leads to a pretty good average which would be quite close to the volume actually wanted each time as well as because three times is when I want to just hold the button down and go back to the previous low/high.

Proof of Concept:

Here I used two tactile push buttons to represent the up and down volume button respectively. I chose not to take too high or low volumes so that the video could be relatively short, but still make the point. As can be seen after cycling up and down the volume a few times, I long hold the up button and it goes to the average high. I then adjust it a bit lower to a medium volume followed by going back to the high. Finally, I skip to the low volume. I chose to start at volume 30 arbitrarily here, but for an actual TV, it would start at whatever the last volume was.

Assignment 6: Translate data in to motion

Take physical input collected over time, turn that in to an interactive movement related to the input data.  Interaction has emotional meaning, can you create an emotional data feed?

My doorbell example:  If someone presses my doorbell button multiple times, should the doorbell ring multiple times?  Or should it text me with a photo of who’s at the door?  If it’s a neighbor’s kid, should it text their parents and ask them to cut it out?  If it’s someone in my house and they have bags of groceries, and it’s raining outside, should it text/email me and flash all the lights in the house to let me know to let them in?