2023 Group 2 – KEITH Plant Monitor


dESIGN BLOG

November 13, 2023

Today we made our final decision on what our first and back up choices are, “Monitoring your plants” and “Your Own Talking and loving Teddy Bear” respectively. We also did some brainstorming of some ideas for each project:

I also emailed Laurissa to confirm our group members and our first and backup choices. In the evening I received an email confirmation from Laurissa that the “Monitoring your plants” project is ours to work on.
Atanas

November 17, 2023

After it was confirmed that we can start working on the plant monitor project, I came up with a starting idea that we could try and prototype on Monday during the lab. 

A single container that would contain the Arduino board, the sensors/actuators, the water container and pump and that would have a round space in the middle for the user to insert their plastic pot and plant. We will also need to decide how to power Keith, our plant monitor, with a USB cable, AC adapter or batteries.
Atanas

November 20, 2023

During today’s lab, we started to create prototypes based on my starting design to see how it might function and look. I researched the components we will need. We need to add them to our order today so we can get them early and start putting them together.
A list of what we need:

  • an OLED screen
  • a humidity sensor
  • an easier to use potentiometer and button than the one provided with the Arduino kit
  • Velcro tape
  • plant
  • a large selection of wires – male-to-male, male-to-female, female-to-female that come with enough red and black wires for connecting voltage and ground
  • a light sensor(reuse from Arduino kit)
  • soil moisture sensor
  • water pump
  • relay
  • water container
  • tubing
  • resistors (reuse from Arduino kit)

While Bryle was researching for parts and components, Stanley and I started working on prototypes. 

Prototype of the rough physical appearance of the plant monitor:

This gave us an idea of what each part of the casing would be dedicated to. And how the user would interact with the monitor.

OLED screen user interface prototype:

We wanted to provide the users of our monitor to be able to get in depth analysis of the their plant’s immediate surrounding area so they can take better care of it. Different bars on the screen would represent the temperature, light, humidity and soil moisture. Each bar would also have indicators of what the current value of that bar is and what is the optimal condition of the plant. So if there wasn’t enough light in the room, the user would have the move their plant pot and monitor somewhere else. Or if the humidity was really low they would get a humidifier or give their plant a few spritzes with a mister.

The bars would also be accompanied by a flower character that would provide additional indication of how the plant is doing.

We also had the idea that the plant monitor could be adapted by the user so they can take care of any plant with it, by adjusting the optimal levels for each bar through a potentiometer and a button. 

The user would use the potentiometer to go to the setting levels option and press confirm with the button. Then they would scroll through each bar which would be indicated with an icon displayed over the flower character. Pressing the button again would confirm their choice and they will be able to set the relevant bar to the required level and once again press the button to confirm their choice.

After the prototypes were we all collectively started researching components and by the end of the day had found the majority we required and had them ordered. The most difficult one to decide on was the OLED screen because there were so many options, but it was difficult to decide which would work with our Arduino and which library they would require. We also had to consider the number of pixels we would need, as the bigger screens that we originally thought we would use, it turned out would eat up most of our budget as they cost over £40-£50.

Atanas

November 27, 2023

Today, we received our components that we had ordered for Keith, so I tested them to make sure that they worked and how they would work.

First thing I tested was the light sensor.

The light sensor used one analog pin to work, outputting a value representing the ambient light level. It has a LDR soldered on at the end of the circuit board to read the light level.

The temperature and humidity sensor needed one digital pin along with the two pins for voltage and ground to work. Using the DHT11 library for the Arduino, I was able to get readings for both the humidity and temperature.

These two sensors will be recording the ambient factors surrounding the plant, so they needed to be exposed to correctly record values.

The next sensor I tested was the soil moisture sensor.

This came with the components for the irrigation system (water pump, relay etc). This didn’t need any libraries so I could use standard Arduino code to get readings from the sensor. The readings for this sensor worked where the drier the soil, the higher the reading which would be important to keep in mid when coding. It uses one analog pin for reading the value into the code.

This sensor would be placed in the soil of our plant to get its readings.

The next component I tested was the OLED screen. It has a 128×64 resolution and is 2.42 inches.

The Driver IC (Intergrated Circuit Chip) in the OLED screen is 1309, so I used the ‘u8g2’ library to run code that would display images on the screen. The image above is the standard coding test of outputting ‘Hello World’ using example code that came with the library. Using an example code file called ‘Graphics Test’, I tested what kind of shapes the screen could output. Below is a bitmap example from the code.

The screen required 7 pins to work. 5 pins were needed for the screen to work, along with the power and ground wires.

Bryle

28 November, 2023

Following some of the component testing from yesterday, Stanley and Atanas began building the circuit in order to get a feel for how the components would need to be wired together on the Arduino. While they did this, I tested the relay and water pump to make sure that they worked since they were essential for the irrigation system of the project.

Top Left: Relay
Bottom Right: Water Pump

The relay was used in conjunction with the water pump and would be activated using code with digitalWrite, going between high and low. The relay uses a digital pin in order to receive the high or low signal to run the pump. For the irrigation system, we’ll be using the reading from the soil moisture sensor in an if statement to check whether the plant needs water.

Bryle

1 December, 2023

Today, I began coding the program we would be using for the final product.

I started with making sure that all readings that I need from the sensors can be read in. For the temperature and humidity sensor, I used the DHT Sensor library by Adafruit to read the values. Even though only one digital pin is used to connect the sensor to the Arduino, the library allows for the humidity and temperature to be pulled separately and assigns to different variables. The variables would be defined at the top of the program, outside of setup, and then the value would be taken in every time the code in the loop section is run, so that the readings are constantly refreshed.

For the light sensor and the soil moisture sensor, I didn’t need to install any libraries so I used standard Arduino code. Both these sensors used one analog pin each to take a reading. Same as the temperature and humidity, they were defined at the top of the program and then constantly refresh the reading in the loop section.

For the soil moisture sensor, I did have to write a function in order to read a value. This was because the sensor requires power to take a reading so the function essentially sends a high digital signal to power the sensor on, then takes a reading and assigns it to a variable, and then sends a low digital signal to power the sensor off. It returns the reading from the sensor.

Bryle

3 December, 2023

Today me and Stanley tested the pump and relay system and ran into an issue where the relay LEDs were turning on, but the pump was not doing anything. We ordered a new pump and relay with next day delivery to make sure this is sorted out as soon as possible.

Atanas

4 December, 2023

I continued coding the program while Stanley and Atanas begin assemblying the final product.

Stanley and Atanas used this final concept for the product.

Stanley needed to do some work on the watering can pot to fit in the water pump’s pipes so that it goes through the spout of the watering can.

Stanley and Atanas tested the new pump and relays that arrived today and thankfully they were both working successfully. They were then able to add the pump into the watering can to ensure that it works, being successful in doing so.

Regarding the code, I was able to add the if statement block, responsible for checking the soil moisture and activating the pump when the moisture is too low.

Bryle

8 December, 2023

Today, the assembly of the product involving the pots and Arduino was finished.

The product will run using a battery, ensuring that it doesn’t require a mains plug to work, meaning it isn’t restricted to where it can be placed.

Assembly Finished
10 December, 2023

Today, the coding aspect of the project was wrapped up.

The screen feedback was done today.

The first part of the screen feedback was a show of the current plant factors. Graphics were used to create bars that represent the current state of each factor that needs to be observed when taking of plants. The bars representing the current reading of each factor was done by mapping the readings into a certain range that would allow it to be displayed correctly on the screen. There was also text added below to ensure that the user knew which bar represented which factor.

Plant Factors

The second part of the screen feedback is a flower representing a general summary of the plant’s current status. It has three states:

  • Full Flower: A flower with all of its petals, representing that all the factors for the plant are optimal.
  • Decaying Flower: A flower that has lost some of its petals, representing that one or two of the factors are not optimal.
  • Wilted Flower: A flower that has lost all of its petals, representing that all three factors are not optimal for the plant.
Decayed Flower state

These states only depended on three of the factors (temperature, humidity and light) as the irrigation system handled the soil moisture.

The state changing based on the three factors was done using booleans that would check whether the factor’s reading was within a certain range, setting the boolean to true, otherwise being false if it is outside said range. It would then check all three booleans to determine the state of the plant and what is shown to the user.

I also changed the library used for the humidity and temperature sensor, from the adafruit one we were using to the official Arduino one, EduIntro. The Adafruit library we were using stopped working with a sensor so that is what necessitated the change.

Bryle

11 December, 2023

Before the presentation, we uploaded the code into the Arduino and inserted it into the finished product. We did some final testing, making sure everything was working as intended for the demonstration. We also finalised the slides within our group, ready for the presentation.

Below is our final product.

Finished Keith Care

Bryle

project task list

Task List

Group Members: Atanas Ilinov, Bryle Inandan, Stanley Parker

TaskMember/s
Choose Two Briefs – First Choice, Backup ChoiceEveryone
Confirm Group Members, First Choice, Backup ChoiceAtanas
BrainstormingEveryone
Initial Design ConceptsAtanas, Stanley
Lo-fi PrototypingAtanas, Stanley
Researching Circuitry ComponentsEveryone
Ordering Components and MaterialsEveryone
Testing ComponentsBryle
Assembling CircuitAtanas, Stanley
Modifying/Building CasingStanley
CodingBryle
AssemblyAtanas, Stanley
Testing and Bug-fixingEveryone
Create PresentationEveryone
BlogEveryone

Project Plan

maker manual

Overview

Are you tired of forgetting to water your plants? Tired of them being too hot or too cold? Tired of wilting due to a lack of light? Well, we have a solution for you, and his name is KEITH!

KEITH is a must have for any houseplant parent, he gives you critical information about your plant, including the temperature, humidity and light level of it’s surroundings, he even keeps track of the soil moisture content and waters it for you!

KEITH is the perfect caretaker for all of your green, leafy children, simply hook his moisture sensor up to the soil and adjust his watering hose to the position you need it in and let him get to work! KEITH‘s small module is non-intrusive and can be placed in most areas of your home with ease.

KEITH is perfect for casual hobbyists or more experienced plant owners due to the variety of information he can give you about your plant, and he’s so easy to set up, once he’s hooked up and you’ve filled his reservoir he’ll begin watering your plant whenever it needs it.

KEITH isn’t like those other “self-watering” plant pots you see that rely solely on the plant’s ability absorb water, KEITH will keep your plant watered no matter the conditions, even if your plant is struggling KEITH will be right there with it helping you nurture and care for it.

Tools and Supplies

Tools
Supplies
  • Textual Breakdown of Components:
    • Arduino UNO
    • Miniature submersible water pump
    • Arduino 1 channel 5V relay module
    • Velcro Tape
    • 2.42 inch 128X64 OLED Display Module IIC I2C Serial Peripheral Interface
    • 8.6mm PVC pipe
    • M-F, M-M and F-F cables
    • Capacitive Soil Moisture Sensor
    • DHT11 3 Pin Module
    • Epoxy Putty
    • Ceramic Pot + Watering Can
    • Arduino Light Sensor Module
    • 9V battery
    • 9V battery clip with 2.1*5mm Male Plug
    • Fake Grass

Layout and Circuit Diagrams

Breadboard Layout Diagram

Unfortunately the software we used to make the breadboard diagram (Fritzing) was a little outdated, so instead of a water pump image I had to use a motor image. They also did not have a photoresistor module, so we just implemented a regular photoresistor. This is also reflected in the circuit diagram below.

Circuit Diagram

Relay here is treated as a relay module. The diagram above only shows how the module itself is connected to the circuit. Some of the pins on some of the components have also been rearranged for better readability.

How to Build

Code

// libraries
#include <EduIntro.h>
#include <Arduino.h>
#include <U8g2lib.h>
#ifdef U8X8_HAVE_HW_SPI
#include <SPI.h>
#endif
#ifdef U8X8_HAVE_HW_I2C
#include <Wire.h>
#endif

// dht11 library code for temperature and humidity sensor
DHT11 dht11(D3);

// soil moisture and light pins
const int soilMoistRead = A0;
const int soilMoistPower = 4;
const int lightPin = A1;

// relay connected to pin 2, HIGH will pump water out
int pumpPin = 2;

// potentiometer to scroll between screens
const int scrollPin = A2;

// variables for plant needs
float soilMoist;
int humidity;
int temperature;
float currentLight;

// booleans for flower face
bool optimalTemp = true;
bool optimalHumid = true;
bool optimalLight = true;

// pins for screen
// GND = Ground, VCC = 3/5V, SDL/Clock = 13, SDA/Data = 11, RES/Reset = 8, DC = 9, CS = 10

// constructor for screen
U8G2_SSD1309_128X64_NONAME2_F_4W_SW_SPI u8g2(U8G2_R0, /* clock=*/ 13, /* data=*/ 11, /* cs=*/ 10, /* dc=*/ 9, /* reset=*/ 8);

// used to change between the flower faces and statistics
uint8_t page = 0;

void setup() {
       Serial.begin(9600);

       // power on the screen and prepare everything
       u8g2.begin();
       u8g2_prepare();

       // assign pin modes
       pinMode(soilMoistPower, OUTPUT);
       pinMode(pumpPin, OUTPUT);

       // default state of pump - off
      digitalWrite(soilMoistPower, LOW);
} //end setup

void loop() {
      // Serial.println();

      // updates the temperature and humidity reading every loop for updated reading
      dht11.update();

      humidity = dht11.readHumidity();
      // Serial.print("Humidity (%): ");
      // Serial.println(humidity);

      temperature = dht11.readCelsius();
      // Serial.print("Temperature (celsius): ");
      // Serial.println(temperature);

      // sensor value closer to 0 the more wet it is
      soilMoist = readSensor();
      // Serial.print("Soil Moisture: ");
      // Serial.println(soilMoist);

      currentLight = analogRead(lightPin);
     // Serial.print("Light Level: ");
      // Serial.println(currentLight);

      // drawing the plant stats and current status
      u8g2.clearBuffer();
      plantStatus();
      u8g2.sendBuffer();

      // checks for optimal conditions
      // soil moisture not included as irrigation system is automatic
      if(temperature >= 21 && temperature <= 30){
          optimalTemp = true;
      } else{
          optimalTemp = false;
      } // end if else

      if(humidity >= 40 && humidity <= 70){
          optimalHumid = true;
      } else{
          optimalHumid = false;
      } // end if else

      if(currentLight >= 40 && currentLight <= 70){
          optimalLight = true;
      } else{
          optimalLight = false;
      } // end if else

      // runs pump after checking the soil moisture
      waterPlant(soilMoist);

      // automatically flip between the two pages of flower stats
      page++;

      if(page > 1){
          page = 0;
      } // end if

      delay(2000);
} // end loop

// soil moisture reading
int readSensor(){
     
digitalWrite(soilMoistPower, HIGH);
      delay(10);
      int val = analogRead(soilMoistRead);
      digitalWrite(soilMoistPower, LOW);
     
return val;
} // end readSensor

// sensor value closer to 0 the more wet it is
// checks water and activates pump when low on water
void waterPlant(float moisture){
      if(moisture > 400){
          digitalWrite(pumpPin, HIGH);
      } else {
          digitalWrite(pumpPin, LOW);
      }
} // end waterPlant

// prepare screen to be used
void u8g2_prepare() {
      u8g2.setFont(u8g2_font_5x8_tf);
      u8g2.setFontRefHeightExtendedText();
      u8g2.setDrawColor(1);
      u8g2.setFontPosTop();
      u8g2.setFontDirection(0);
} // end function

// draw status bar of each plant need
void plantStatusBar(){
      int mapSoilMoist = map(soilMoist, 350, 600, 0, 40);
      int mapHumid = map(humidity, 20, 90, 0, 40);
      int mapTemp = map(temperature, 0, 50, 0, 40);
      int mapLight = map(currentLight, 1023, 0, 0, 40);

      u8g2.drawStr(10, 50, "Water");
      u8g2.drawBox(19, 8+(40-mapSoilMoist), 8, mapSoilMoist); // map values into range of 0 - 40
      u8g2.drawFrame(17, 6, 12, 44);
      u8g2.drawStr(37, 50, "Humid");
      u8g2.drawBox(45, 8+(40-mapHumid), 8, mapHumid);
      u8g2.drawFrame(43, 6, 12, 44);
      u8g2.drawStr(65, 50, "Temp");
      u8g2.drawBox(70, 8+(40-mapTemp), 8, mapTemp);
      u8g2.drawFrame(68, 6, 12, 44);
      u8g2.drawStr(88, 50, "Light");
      u8g2.drawBox(95, 8+(40-mapLight), 8, mapLight);
      u8g2.drawFrame(93, 6, 12, 44);
} // end plantStatusBar

void flowerFace(){
      if(!optimalTemp || !optimalHumid || !optimalLight){
          if(!optimalTemp && !optimalHumid && !optimalLight){
              // wilted flower
              u8g2.drawStr(35, 0, "Wilted Flower");
              u8g2.drawStr(30, 10, "Stats no good...");
              u8g2.drawDisc(64, 40, 9); // main body
          } else {
              // slightly decayed floweru8g2.drawStr(30, 0, "Decayed Flower");
              u8g2.drawStr(35, 10, "Check stats!");
              u8g2.drawDisc(64, 40, 9); // main body
              u8g2.drawCircle(54, 40, 5); // left petal
              // u8g2.drawCircle(74, 40, 5); // right petal
              // u8g2.drawCircle(64, 50, 5); // bottom petal
              u8g2.drawCircle(64, 30, 5); // top petal
              // u8g2.drawCircle(58, 45, 5); // bottom left petal
              u8g2.drawCircle(70, 45, 5); // bottom right petal
              u8g2.drawCircle(58, 35, 5); // top left petal
              // u8g2.drawCircle(70, 35, 5); // top right petal
          }
      } else {
          // full flower
          u8g2.drawStr(35, 0, "Full Flower");
          u8g2.drawStr(30, 10, "All stats good!");
          u8g2.drawDisc(64, 40, 9); // main body
          u8g2.drawCircle(54, 40, 5); // left petal
          u8g2.drawCircle(74, 40, 5); // right petal
          u8g2.drawCircle(64, 50, 5); // bottom petal
          u8g2.drawCircle(64, 30, 5); // top petal
          u8g2.drawCircle(58, 45, 5); // bottom left petal
          u8g2.drawCircle(70, 45, 5); // bottom right petal
          u8g2.drawCircle(58, 35, 5); // top left petal
          u8g2.drawCircle(70, 35, 5); // top right petal
      } // end if else
} // end flowerFace

void plantStatus(){
      u8g2_prepare();

      switch(page){
          case 0: plantStatusBar(); break;
          case 1: flowerFace(); break;
      }
} // end plantStatus

Testing and Shortcomings

Testing

We Tested KEITH’s water pump and soil moisture reading mapping with several different threshold values to try and make sure the range we selected was realistic for the home environment in order to optimise the display to make it more readable for the user as well as to optimise the amount of water KEITH pumps to the plant as there is slight latency in the system.
We rigorously tested all our sensors with both expected and extreme values in order to make sure they were all working well, in the process we discovered some sensors were faulty and replaced them.

Shortcomings

Our aim with KEITH was to make a household friendly plant caretaker. Unfortunately due to time limitations we didn’t get to implement a manual varying of thresholds to allow the user to fine tune KEITH and instead we set more general thresholds which will be suitable for most houseplants but may not be suitable for more exotic or unusual varieties.
KEITH is not weatherproof and is only suitable for indoor use.
KEITH is also limited on his modularity, he is only suitable for one plant at any given time due to how the system is set up.