Plant Water Tracker

By Carmyn Talento

Overview

A blue acrylic box with a rectangular screen on the face displaying two lines: "Moisture: 0" and "Minutes: 1". Below the screen is etched words saying "Plant Water Tracker". On the top of the box is three small LED lights from left to right the colors are red, yellow, green. The red light is glowing and the other two are off. There are two black wires coming out of the back of the box, one plugged into the wall for power and one with a two pronged gold sensor on the other end for detecting moisture. The sensor is resting in front of the box.

A plant water tracking device with a screen to display the moisture level on a scale of 0-100 and how many minutes for the demo mode/days for the regular mode since the last watering. Three lights on the top correspond to the plant's need for water similar to a stop light.  

This project helps me to keep track of the moisture level in the soil of one of my orchids and lights up to remind me when I need to water them again. The display both gives me a reading of the most current moisture level on a scale of 0-100 and how many days it has been since the last watering. The sensor takes a reading once per hour. Additionally, the tracker has a three light system on the top that lights up a red LED when the moisture level is below 25, a yellow light when the moisture level is between 26 and 50, and a green light when the moisture level is above 50. 

A blue box device with an LCD display reading two lines of text. Line 1 says "Moisture:0" and line 2 says "Days:0". The front of the box has "Plant Water Tracker" etched into the surface just under the LCD display. On top of the box are three lights in a row, the rightmost is lit red. The box is on a shelf next to a small orchid. On the shelf below is a slightly larger orchid. A wire goes form the back of the blue box to the pot of the lower, larger orchid.
A blue box device with an LCD display reading two lines of text. Line 1 says "Moisture:60" and line 2 says "Days:0". The front of the box has "Plant Water Tracker" etched into the surface just under the LCD display. On top of the box are three lights in a row, the leftmost is lit green. The box is on a shelf next to a small orchid. On the shelf below is a slightly larger orchid. A wire goes form the back of the blue box to the pot of the lower, larger orchid.

A side by side comparison of the Plant Water Tracker with its final (non-demo) code being used with a real plant. The soil moisture sensor is placed in the pot of the plant on the shelf directly below the device. In the left image, the red LED indicator light is on, and the moisture level is noted as zero, meaning the plant desperately needs to be watered. In the right image, the green LED indicator light is on, and the moisture level is reading at 60, meaning the plant has recently been watered and is doing well. 

Features

A small blue LCD screen with white text in two lines. The top line reads "Moisture: 0" and the bottom line reads "Minutes: 0". The screen is bolted onto blue acrylic with 4 silver bolts, one in each corner.

LCD Display Screen - a small screen that displays two lines. The top line reads the moisture level on a scale of 0-100. The bottom line is a time counter, reading minutes for the demo mode or days for the real mode since the last watering.

The top of a blue acrylic box is being shown. In the middle of the top are three LED lights, left to right are red, yellow, green. The red light is currently glowing.

LED Lights - Three LED lights on the top of the device are used similar to a stop light. The red light glows when the moisture level reading is below 25, the yellow light when the moisture is between 25 and 50, and the green when the moisture is above 50.

The back side of a blue acrylic box is being shown. There is a panel that has a small handle on the top and a silver hinge on the bottom so the panel can open up. In the bottom right corner of the back side of the box (not on the panel) is a metal piece of hardware that has a black chord coming out of it.
The same image as the one to the left of this one, except now the panel is open, revealing the Arduino Uno and other colorful wires and electrical components inside of the box.

Hinged Back Panel - A hinged back panel allows for easy access to the internal electrical components of the device. This is necessary because this allows me to make small changes to the code and update the Arduino based on the needs of the specific plant I am using the device for. Additionally, this allows me to change the battery on the Real Time Clock (RTC) module. 

A piece of silver hardware with two black chords is attached to the bottom right corner of the back side of a blue acrylic box. This piece of hardware is called a panel mount connector and allows for connections to be made from the external wires to the components inside of the box.

Panel Mount Connector - A panel mount connector is being used for the two wires that are necessary to pertrude from the box. This is a piece of hardware that is designed to have a clean and organized connection of wires from one side of a wall to another. This is a necessary part because there are two wires that need to be external: the sensor and the power.

Functionality

Carmyn Talento Project 2 Video.mov

In this video, I show the functionality of the Planet Water Tracker device in its demo mode. I use my hand to grip and cover the moisture sensor so the sensor shows a high reading of 98 and the green LED lights up in the beginning. Prior to the video start, I had allowed for a few minutes to pass by to show that the minute (or day for the real mode) counter was updating. Once I let go of the sensor and a reading takes place, the display updates to show that the moisture level dropped to 0, the green light turned off, and the red light turned on. The minute (or day) counter resets when the moisture level increases significantly between readings. 

Process

An Arduino Uno is connected with three wires to a soil moisture sensor, then connected via USB to a computer.

Seeing how to wire, program, and test the moisture sensor, as this is a component I was unfamiliar with before this project. 

An Arduino Uno is connected to a soil moisture sensor, an LCD screen, three LED (red, yellow, green) lights on a protoboard, and a real time clock module on a different protoboard.

Starting to put together all the different aspects of the overall circuitry. This did not end up being the most efficient use of boards, but was a good middle step in figuring out how to get everything to work together. 

Six sides of a rectangular box separated and laid out flat. The pieces are made of blue acrylic and some sides have holes and engravings to allow for the other components of the device to be implemented easily.

The parts of the device's box just after being laser cut. The parts are made of 3mm thick blue acrylic. The front panel needed to be recut because the holes for the bolts were too small and slightly off from where they needed to be. I also made the text slightly larger. The top also needed to be recut to make the holes for the LED lights slightly larger to fit more comfortably. 

The same sides of the same box as the previous image, this time loosely assembled and held together with blue painters' tape.

The final pieces of the box put together loosely and held together with tape to make sure all the pieces fit correctly and all electrical components that need mounted onto the box directly get mounted on the correct side with the correct orientation. 

The back side of the box is isolated and shows the inside where there are two bolts with nuts attaching the hinge to the side and the panel. A small part of the metal hinge is showing in the hole for the panel mount connector.

Hinges were cut to size and added to the back panel. One small part of the hinges slightly blocks the hole for the panel mount connector, so I made another small cut to the hinges before the final assembly. 

A behind view of the box where the back side is removed and the electrical components are now soldered and mounted in the necessary locations to the inside of the box. The hinges and back panel are missing.

The electrical components of the circuitry were soldered and mounted as necessary to the sides of the box before the box was completely glued together. 

A back view from slightly above of the completed device after putting together all the sides of the blue rectangular acrylic box. The box has three LEDs on the top, and the back panel closed. The hinges and panel mount connector are clearly visible.
A front/above view of the blue acrylic box device after its final assembly. Three LED lights are visible in the center of the top, an LCD screen and the etched words "Plant Water Tracker" are on the front side. Two black wires come out of the back: one with an adapter for a 5V power supply, and one longer one connected to the soil moisture sensor.

The device after its final assembly of all the electrical and fabricated components. 

An aspect of the process that does not have associated images is the programming progress. This was notably difficult, particularly for the real time clock (RTC) module because it was hard to find good working libraries, and the good libraries did not have a lot of useful examples for how to use them. It took longer, but I did get it to work. Additionally, there was something weird going on with the screen not updating properly, which had me move where the screen updates are placed within the code. The placement of the screen before and after based on code tracing did not (and still doesn't) seem like it would make a difference, but it does. Other than these two things, the rest of the programming went fairly smooth.

Discussion

Overall, I am satisfied with the outcome of my Plant Water Tracker device. Throughout the development process, I confronted and overcame a lot of self doubt, particularly in programming and fabrication. One significant obstacle was the design of the hinged back panel, which presented several complexities such as the hinge obstructing the panel mount connector initially, the need for a mechanism to open it, and ensuring it did not fall into the body of the device.


Reflecting on the project, I acknowledge areas for potential improvement, notably in the final wiring. I wish I had more considerations for the final wiring, possibly using stranded wires instead of solid to allow for more flexibility, as well as choosing to use longer wires for the internal circuitry so it can easily be pulled out if the RTC battery needs changed or a repair is necessary.


Looking ahead, I see a possibility of creating a new version of this device. If I do, I would like to create a more adaptable design capable of accommodating a wider range of plant types. I would do this by “considering a simple interface with three values (low, medium, high) of water needs for different plants” as suggested during the final critique of the project. This would involve having a few preset settings of mapped values of the soil moisture sensor to the moisture levels that trigger the light indicators instead of the current method of having to manually adjust the code and re-upload it to the Arduino. 


Furthermore, if I were to make an improved edition of the Plant Water Tracker, I would also like to explore the suggestion of enabling the device to monitor multiple plants simultaneously, as proposed during the critique. Particularly, I liked the idea of having “one LED per plant to make it user friendly where each light maps to a wire.” This would allow for multiple plants to have their own sensors, indicator lights, and day counters at the same time. As a plant person owning well over one plant, I would find this feature incredibly useful.


These proposed improvements really stuck with me, and I am interested in the possibility of incorporating them into a future iteration of the Plant Water Tracker device some day. However, I am proud of the product that I was able to produce in the short period of time allotted and the large learning curve surrounding the software and equipment involved in the making of this device.

Technical Information

Block Diagram

Electrical Schematic

Programming

Real Final Code

/* 


 Physical Computing Project 2: Plant Water Tracker

 Carmyn Talento


 A soil moisture sensor is placed in the soil of a plant. Every so often, the soil moisture sensor checks the

 moisture level and sends a reading to the LCD screen to show the user how well watered the plant is at that

 time (maybe mapped on a 1-100% scale). A green LED will stay on when the plant is sufficiently watered, a yellow

 LED will stay on when the plant needs to be watered soon, and a red LED will stay on when the plant DESPERATELY

 needs to be watered. The LCD screen will also display how many days have passed since the most recent watering,

 which is updated automatically when the moisture level spikes.


 Sources:

 https://learn.sparkfun.com/tutorials/soil-moisture-sensor-hookup-guide?_gl=1*szrgra*_ga*MTQ2NjE3ODAwNC4xNzA3OTI3NTk1*_ga_T369JS7J9N*MTcwNzkyNzU5NC4xLjAuMTcwNzkyNzU5NC42MC4wLjA.&_ga=2.70253269.439661174.1707927595-1466178004.1707927595#hardware-overview-and-assembly

 Also referenced the ds3231 example code from the RTCLib by NeiroN library for the real time clock


   Pin mapping:


   Arduino pin | role  | details

   ------------------------------

   A0            input     soil moisture sensor reader

   7             output    soil moisture sensor power

   13            output    green LED

   12            output    yellow LED

   8             output    red LED


*/


// insert library and set up values for screen display


#include <LiquidCrystal_I2C.h>

LiquidCrystal_I2C screen(0x27, 16, 2);

int x = 123;


// insert library and set up real time clock


#include <RTClib.h>

DS3231 rtc;


// set up soil moisture sensor values and pins


int soilPin = A0;                // soil moisture sensor pin

int soilPower = 7;               // soil moisture sensor power pin, can't be powered all the time or risk of corrosion

int days = 0;                    // starting value for days since watering

bool moistureIncreased = false;  // check if the moisture level increased (use to reset day timer)

int oldSoilVal = 0;              // previous soil moisture initial value

int newSoilVal = 0;              // new soil moisture initial value


// buffer for DateTime.tostr

char buf[20];



// set up system


void setup() {


 // turn on serial library

 Serial.begin(9600);


 // check soil moisture

 newSoilVal = readSoil();


 // initialize real time clock

 Wire.begin();

 rtc.begin();


 if (!rtc.isrunning()) {

   Serial.println("RTC is NOT running!");

   // following line sets the RTC to the date & time this sketch was compiled

   rtc.adjust(DateTime(__DATE__, __TIME__));

 }


 // set up pins

 pinMode(soilPower, OUTPUT);  // soil moisture sensor power

 pinMode(13, OUTPUT);         // green LED

 pinMode(12, OUTPUT);         // yellow LED

 pinMode(8, OUTPUT);          // red LED


 // write to serial reader

 digitalWrite(soilPower, LOW);  //Set to LOW so no power is flowing through the sensor


 // LCD screen set up

 screen.init();

 screen.backlight();

 screen.home();

}



// loop through the commands of taking measurement from soil moisture sensor, send signal to LED, update LCD, updating day counter if necessary


void loop() {


 DateTime now = rtc.now();


 // check if moisture level has increased at the start of each hour

 if (now.minute() == 0 && now.second() == 0) { // run this if statement every hour on the hour

   oldSoilVal = newSoilVal;  // loading previous new value into old value

   newSoilVal = readSoil();  // current soil moisture reading


   // compare old and new to update day tracker if new is much larger than old soil moisture values

   if (newSoilVal > (oldSoilVal + 10)) {

     moistureIncreased = true;

   } else {

     moistureIncreased = false;

   }


   // update day counter

   if (moistureIncreased == false) {

     days = days + 1;

   }

   else {

     days = 0;

   }


   delay(1500);

 }


 // print soil moisture values and time in serial monitor

 Serial.print("Mapped Soil Moisture = ");

 Serial.println(readSoil());  // get soil moisture value from the function below and print it

 Serial.print("Real Soil Moisture = ");

 Serial.println(map(readSoil(), 0, 100, 0, 900));

 Serial.print("Time = ");

 Serial.println(now.tostr(buf)); // get current time

 delay(1000);  // wait one second before repeating


// update the LEDs based on soil moisture level


 // if the moisture level is high, turn on green LED, turn off any other LEDs

 if (newSoilVal >= 50) {

   digitalWrite(8, LOW);

   digitalWrite(12, LOW);

   digitalWrite(13, HIGH);

 }


 // if the moisture level is low, turn on the yellow LED

 else if (newSoilVal >= 25) {

   digitalWrite(8, LOW);

   digitalWrite(13, LOW);

   digitalWrite(12, HIGH);

 }


 // if the moisture level is REALLY low, turn on the red LED

 else {

   digitalWrite(13, LOW);

   digitalWrite(12, LOW);

   digitalWrite(8, HIGH);

 }


 // clear the LCD screen to update properly

 screen.clear();


 // write to LCD screen - moisture level and how many days it has been since the last watering

 screen.print("Moisture:");

 screen.print(newSoilVal);

 screen.setCursor(0, 1);

 screen.print("Days:"); // change to minutes for demo mode

 screen.print(days); // change to minutes for demo mode


 delay(1000);  // delay for safety, might not be necessary

}



// function used to get the soil moisture content (taken from website for soil moisture sensor Sparkfun website in sources)

int readSoil() {


 int soilVal = 0;

 digitalWrite(soilPower, HIGH);         // turn pin 7 (soil moisture power) "On"

 delay(10);                             // wait 10 milliseconds

 soilVal = analogRead(soilPin);         // Read the SIG value form sensor

 digitalWrite(soilPower, LOW);          // turn pin 7 (soil moisture power) "Off"

 return map(soilVal, 0, 900, 0, 100);  // send current moisture value, map to a percentage scale

 Serial.print(soilVal);

 Serial.print(map(soilVal, 0, 900, 0, 100));

}

Demo Mode Code

/* 


 Physical Computing Project 2: Planet Water Tracker - Demo Mode

 Carmyn Talento


 A soil moisture sensor is placed in the soil of a plant. Every so often, the soil moisture sensor checks the

 moisture level and sends a reading to the LCD screen to show the user how well watered the plant is at that

 time (maybe mapped on a 1-100% scale). A green LED will stay on when the plant is sufficiently watered, a yellow

 LED will stay on when the plant needs to be watered soon, and a red LED will stay on when the plant DESPERATELY

 needs to be watered. The LCD screen will also display how many minutes have passed since the most recent watering,

 which is updated automatically when the moisture level spikes.


 Sources:

 https://learn.sparkfun.com/tutorials/soil-moisture-sensor-hookup-guide?_gl=1*szrgra*_ga*MTQ2NjE3ODAwNC4xNzA3OTI3NTk1*_ga_T369JS7J9N*MTcwNzkyNzU5NC4xLjAuMTcwNzkyNzU5NC42MC4wLjA.&_ga=2.70253269.439661174.1707927595-1466178004.1707927595#hardware-overview-and-assembly

 Also referenced the ds3231 example code from the RTCLib by NeiroN library for the real time clock


   Pin mapping:


   Arduino pin | role  | details

   ------------------------------

   A0            input     soil moisture sensor reader

   7             output    soil moisture sensor power

   13            output    green LED

   12            output    yellow LED

   8             output    red LED


*/


// insert library and set up values for screen display


#include <LiquidCrystal_I2C.h>

LiquidCrystal_I2C screen(0x27, 16, 2);

int x = 123;


// insert library and set up real time clock


#include <RTClib.h>

DS3231 rtc;


// set up soil moisture sensor values and pins


int soilPin = A0;                // soil moisture sensor pin

int soilPower = 7;               // soil moisture sensor power pin, can't be powered all the time or risk of corrosion

int minutes = 0;                 // starting value for minutes since watering

bool moistureIncreased = false;  // check if the moisture level increased (use to reset minute timer)

int oldSoilVal = 0;              // previous soil moisture initial value

int newSoilVal = 0;              // new soil moisture initial value


// buffer for DateTime.tostr

char buf[20];



// set up system


void setup() {


 // turn on serial library

 Serial.begin(9600);


 // check soil moisture

 newSoilVal = readSoil();


 // initialize real time clock

 Wire.begin();

 rtc.begin();

 if (!rtc.isrunning()) {

   Serial.println("RTC is NOT running!");

   // following line sets the RTC to the date & time this sketch was compiled

   rtc.adjust(DateTime(__DATE__, __TIME__));

 }


 // set up pins

 pinMode(soilPower, OUTPUT);  // soil moisture sensor power

 pinMode(13, OUTPUT);         // green LED

 pinMode(12, OUTPUT);         // yellow LED

 pinMode(8, OUTPUT);          // red LED


 // write to serial reader

 digitalWrite(soilPower, LOW);  //Set to LOW so no power is flowing through the sensor


 // LCD screen set up

 screen.init();

 screen.backlight();

 screen.home();

}



// loop through the commands of taking measurement from soil moisture sensor, send signal to LED, update LCD, updating minute counter if necessary


void loop() {


 DateTime now = rtc.now();


 // check if moisture level has increased at the start of each hour

 if (now.second() == 0) { // run this if statement every minute on the minute

   oldSoilVal = newSoilVal;  // loading previous new value into old value

   newSoilVal = readSoil();  // current soil moisture reading


   // compare old and new to update minute tracker if new is much larger than old soil moisture values

   if (newSoilVal > (oldSoilVal + 10)) {

     moistureIncreased = true;

   }

   else {

     moistureIncreased = false;

   }


   // update minute counter

   if (moistureIncreased == false) {

     minutes = minutes + 1;

   }

   else {

     minutes = 0;

   }

  

   delay(100);

 }


 // print soil moisture values and time in serial monitor

 Serial.print("Mapped Soil Moisture = ");

 Serial.println(readSoil());  // get soil moisture value from the function below and print it

 Serial.print("Real Soil Moisture = ");

 Serial.println(map(readSoil(), 0, 100, 0, 900));

 Serial.print("Time = ");

 Serial.println(now.tostr(buf)); // get current time

 delay(1000);  // wait one second before repeating


// update the LEDs based on soil moisture level


 // if the moisture level is high, turn on green LED, turn off any other LEDs

 if (newSoilVal >= 50) {

   digitalWrite(8, LOW);

   digitalWrite(12, LOW);

   digitalWrite(13, HIGH);

 }


 // if the moisture level is low, turn on the yellow LED

 else if (newSoilVal >= 25) {

   digitalWrite(8, LOW);

   digitalWrite(13, LOW);

   digitalWrite(12, HIGH);

 }


 // if the moisture level is REALLY low, turn on the red LED

 else {

   digitalWrite(13, LOW);

   digitalWrite(12, LOW);

   digitalWrite(8, HIGH);

 }


 // clear the LCD screen to update properly

 screen.clear();


 // write to LCD screen - moisture level and how many minutes it has been since the last watering

 screen.print("Moisture:");

 screen.print(newSoilVal);

 screen.setCursor(0, 1);

 screen.print("Minutes:");

 screen.print(minutes);


 delay(1000);  // delay for safety, might not be necessary

}



// function used to get the soil moisture content (taken from website for soil moisture sensor Sparkfun website in sources)

int readSoil() {


 int soilVal = 0;

 digitalWrite(soilPower, HIGH);         // turn pin 7 (soil moisture power) "On"

 delay(10);                             // wait 10 milliseconds

 soilVal = analogRead(soilPin);         // Read the SIG value form sensor

 digitalWrite(soilPower, LOW);          // turn pin 7 (soil moisture power) "Off"

 return map(soilVal, 0, 900, 0, 100);  // send current moisture value, map to a percentage scale

 Serial.print(soilVal);

 Serial.print(map(soilVal, 0, 900, 0, 100));

}