Plant survival: Preventing cats and low soil moisture level

Made by Eileen Wang

Found in DioT 2019: Internet of Plants

Goal is to help plant owners successfully monitor their plant. Specifically, when 1) the cat knocks over their plant, and 2) when soil moisture level is low.



When I approached the problem, I realized that a plant's ability to survive is dependent on how the owner takes care of the plant and also the environmental conditions within the house. Water is a basic and necessary component to any plant survival, so I decided that a soil moisture sensor is a must. Next, I noticed that many cats like to knock over plants for fun. In the environment of a home, they are an enemy for the plant. If the pot is tipped over, then it might not be able to absorb as much sunlight as it does in its original upright position. 



The solution is in two folds: 

1)  Implement a tilt switch sensor to detect when the plant is knocked over. When a new orientation of the pot is detected, a red LED light will turn on. For cat owners, they may suspect that their cat knocks over the plant multiple times while they are not home. By logging whenever the pot is tilted in a Google spreadsheet, the owner can have more insight into whether their cat misbehaved, and how many treats it deserves. 

2) Implement a soil moisture sensor to monitor whether the plant has water. If there is water detected in the soil, a green LED light will turn on.



In order to build my solution, I decided to incorporate 2 sensors: a Soil Moisture Sensor HL-69 and a Tilt Sensor AT407. Since I have never worked with these two sensors before, it was necessary to do some research to learn they work in practice and in code.  

I reviewed different code samples of how the 2 sensors worked. Then, I incorporated and combined snippets of code I found (in resources below) into my own code, to execute my desired actions. It was challenging to decide which snippets of code to incorporate, since I had to look up every syntax to understand what the code is doing first.

In the beginning, I didn't have a systematic way to format my code, so whenever my code did not work it was hard to troubleshoot. To make sure I could narrow down on what was not working in my code, I decided to write a pseudo code first. Then, every time an action executed successfully I checked it off and moved in. This helped me troubleshoot much faster. 

After I was able to get the code and circuit board working, I logged every time the plant was tilted on Google Spreadsheet through IFTTT.



List of parts used: 

  • Particle Argon
  • AT 404 Tilt Sensor
  • Moisture Sensor YL-69
  • Red LED
  • Green LED
  • 2 of 1k-ohm resistors
  • 1 of 10k-ohm resistor
  • a cup of water (for testing)

Video of "Plant survival: Preventing cats and low soil moisture level" IoT project in action
Eileen Wang -
In order to figure out the structure of my code, I wrote a pseudo code first. I worked from top to bottom, checking off along the way actions I am able to complete successfully.
Img 7264
// define variable to hold tiltPin reading
int tiltpinReading = 0; 

// tilt pen 
int tiltPin = D4;

// Define a pin we'll place a red LED on
int tiltledPin = D2;

// Create a variable to store the red LED brightness.
int tiltledBrightness = 0;

int tiltledState = LOW;       // variable used to store the last LED status, to toggle the light
int tiltpinState;            // the current reading from the input pin
int lasttiltpinState = HIGH; // the previous reading from the input pin

long lastDebounceTime = 0;  // the last time the output pin was toggled
long debounceDelay = 50;    // the debounce time; increase if the output flickers

//below are for the soil moisture sensor 
int rainPin = A0;
int greenLED = D6;

// you can adjust the threshold value
int thresholdValue = 2500;

int sensorValue = 0;

void setup() {

    // set up tiltpin as input
    pinMode(tiltPin, INPUT);
    // Set up the LED for tilt led cell output
    pinMode( tiltledPin, OUTPUT );
    //below is for the soil moisture sensor 
    pinMode(rainPin, INPUT);
    // set up green light as an output
    pinMode(greenLED, OUTPUT);
    //green led light should be off if moisture is detected;
    digitalWrite(greenLED, LOW);
    // defining 'tiltDirection' and 'rain' so I can see feedback in the console 
    Particle.variable("tiltDirection", &tiltpinReading, INT);
     Particle.variable("rain", &sensorValue, INT); 


void loop() {
 // check to see if the sensor was tilted and you've waited 
  // long enough since the last change to ignore any noise:  

  // If the tilt changed, due to noise or tilting: 
  if (tiltpinReading != lasttiltpinState) {
    // reset the debouncing timer
    lastDebounceTime = millis();
  if ((millis() - lastDebounceTime) > debounceDelay) {
    // whatever the reading is at, it's been there for longer
    // than the debounce delay, so take it as the actual current state:
    // if the button state has changed:
    if (tiltpinReading != tiltpinState){
      tiltpinState = tiltpinReading;
    // if the sensor reading is low
      if (tiltpinReading == LOW) {
        // make the status of the ledPin to go on:
        tiltledState = HIGH;   
        // update the LED pin itself:        
        digitalWrite(tiltledPin, tiltledState);
        // dalay the LED on for one second:
      // otherwise if it is high
      else if (tiltpinReading == HIGH){
        // make the status of the ledPin to stay off:
        tiltledState = LOW;
        // update the LED pin itself:
        digitalWrite(tiltledPin, tiltledState);
  // save the reading.  Next time through the loop,
  // it'll be the lasttiltpinState:
  lasttiltpinState = tiltpinReading; 
  // delay to avoid overloading the serial port buffer:
   //below is for the soil moisture sensor 
   sensorValue = analogRead(rainPin);
    tiltpinReading = digitalRead(tiltPin);

  if(sensorValue < thresholdValue){
       // green LED goes on, meaning plant is hydrated
        digitalWrite(greenLED, HIGH);
        // digitalWrite(redLED, HIGH);
        digitalWrite(greenLED, LOW);

// store the time when you last published
int last_published = -1;

void log_to_spreadsheet(  ){

  // check if 1 minute has elapsed
	if( last_published + 6000 < millis() && tiltpinReading == HIGH ){
		Particle.publish( "log_to_spreadsheet", String(tiltpinReading) );

		last_published = millis();

Click to Expand
Screenshot of logging each time a cat knocks over the plant in Google Spreadsheet
Screenshot of events 1 google sheet

Next Steps

For the next step, I would like add more sensors to better protect the plant against a household cat. I suspect that the one sensor I have incorporated specifically to defend against a cat (a tilt sensor) is not enough for this purpose. For example, maybe the cat needs to hear a scary sound to be discouraged from approaching the plant. 



I am new to coding and working with hardware. This project allowed me to learn how to navigate components I am unfamiliar with, complete a circuit, and practice writing code. Before this project, I did not even know how to structure my code (e.g. set up variables and functions). 

Reading sample codes and dissecting what each line does was immensely helpful for developing the logic and language to put together my own code. 



  • I learned how to work with the Soil Moisture Sensor from the sample code in Random Nerd Tutorials.  
  • I learned how to work with the tilt sensor from the sample code in Github.
  • I used Arduino language reference to learn what different syntax means in the above tutorials, as well as understand how I can create loops where I have multiple variables. 

Share this Project


49713 Designing for the Internet of Things

· 16 members

A hands-on introductory course exploring the Internet of Things and connected product experiences.

Focused on

Goal is to help plant owners successfully monitor their plant. Specifically, when 1) the cat knocks over their plant, and 2) when soil moisture level is low.


November 5th, 2019