2023 Group 9 – SmartLeaf

Project by Benjamin Gaunt, Jessica Malek, Catriona Gholami

Selected Project Brief:

Our brief was on the basis of monitoring your plants, by which we must create an automatic irrigation system with sensors for plant conditions. 

You care about your plants, right? Then, why not try Arduino to help you monitor and water them? This project should include a soil humidity sensor that alerts (through some beeping sound or LCD display) when the humidity is too low or too high. It also has to include some automatic irrigation system (see some examples here: https://all3dp.com/2/arduino-watering-system-plant-irrigation-project/). You can also add a light sensor for the amount of light available and an indicator to the user (the carer) in case they need to change the position of the plant accordingly, among other sensors you think would help to keep your plant healthy. Design for providing long term behaviours like the plant thanking you if you have been treating them well (for example, by watering them the last couple of days) and then showing a “Thank you!” message in the display.

Design Process

Based on our selected project brief, we researched the market and audience and how such a product would be beneficial in creation of an interactive plant watering system. We recognize the importance of maintenance of optimal conditions in aiding plant growth and decided to focus our project on the development of an intelligent monitoring system for plant care with feedback to the user.

Plant wellfare is intricately tied to numerous biotic and abiotic factors which consist of light exposure, soil moisture, temperature and just general conditions of the surrounding environment. Our solution to this brief is the creation of an integrated approach and sense of autonomy in plant care systems, to ensure conditions can remain optimum with minumum effort on the client/user based side; meaning the plant can be kept well and alive, even if the user has forgotten about it. Traditional plant care relies solely on periodic human interaction and intervention of conditioning, meaning the parameters of care can be fluctuating and inconsistent, becoming easily overseen. This is where our idea of providing physical and realtime feedback of interaction stemmed from; aiming to notify the user of watering system activations and how the plant is holding up.

The main aspects of our design choices were to ensure effective usability and reliability, interaction (some kind of user experience aspect that makes it fun), and feedback to the user,.

Selection of components:

We ordered the kit giving us things necessary for the completion of the system such as a capacitive soil moisture sensor, a 1-channel 5V relay module, a mini water pump, and vinyl tubing. This integration reduces the complexity of sourcing individual components, ensuring compatibility amongst the system components and functions:

Capacitive soil moisture sensor: Accurately measuring soil moisture levels; more reliable sense compared to a resistive one meaning consistent reading can be obtained throughout.

5V Relay module: Controling of both devices i.e the water pump and the arduino microcontroller; simplifying the interface for safe, efficient operation

Water pump: The specific water pump we ordered consisted of a submersible design. This submersible nature meant that all conditions would be suitable and enabled the use of a water reservoir submersion, so that water can be efficiently delivered directly to the plant as needed for our irrigation system. Has a brushless DC, meaning energy efficiency is sourced.

Vinyl tubing: Water transportation to the plant; flexibility for streamlining the component connection and adjustable to design and system architecture.

Graphical Display Selection:

We were unsure of whether to select an LCD graphical display or an OLED graphical display for our system, but we decided to go with an OLED graphical display module. The OLED would enable us to provide our visual feedback to the user and due to the properties of an OLED it means we would be able to display graphics with a fast response and contrast/brightness compared to an LCD. It ensures accessibility at all times even in lower light conditions where the user may not be able to see well. The response time is also much faster, allowing us to display our feedback in a swift manner; which is important particularly if a change of an optimum condition is drastic and urgent action or notification to the user is necessary.

Component Trials:

We wanted to get started despite not having all our components arrived, so we began through testing the things we did have. Our first experiments began with the DHT sensor (detection of humidity and temperature). We tested the functionality of the sensor and how it responds to different conditions, different rooms etc. The wiring was as below:

Wiring and testing of the humidity and temperature sensor

Our initial wiring was incorrect and the sensor was heating up due to a large voltage and current being passed through which resulted us in implementing a resistor. This was our initial attempt of setting up the sensor; which we later adjusted and corrected the wiring to no longer require a resistor.

To ensure accurate readings, calibration was required and we tested to ensure that it could provide reliable data by changing conditions. This allowed us to begin setting up our arduino environment for the final hard coding of the system.

Configuration of the DHT sensor:

#include "DHT.h"
#define DHTPIN 4
#define DHTTYPE DHT11
DHT dht(DHTPIN, DHTTYPE);

To allow the sensor to work we had to include the DHT library in arduino; providing pre-written code for this specific component and allowing functionality to be activated; abstracting the communication protocols and readings. Inclusion of this library means that we can instantise functions such as ‘readTemperature()’ and ‘readHumiditity()’ in our code testing. We then assigned it to a digital pin (in this picture, it was 7, although in later testing we switched to 4 to accomodate our other components). The sensor type we were using was established as DHT11.

Library reference: https://www.arduino.cc/reference/en/libraries/dht11/

Setup function:

void setup() {
  Serial.begin(9600); // Initialize serial communication
  dht.begin();
  }
}

Initialising the serial communication for the DHT sensor to activate outputs and confirm readings are viable and reliable.

Loop function:

void loop() {
  ReadSoil();     // Reads soil moisture
  ReadHumidity(); // Reads humidity and temperature
}

Calls the functions which we shall define to be in a loop, so that measurements can be consistently taken and updated; to make sure system is in real-time.

ReadHumidity function:

void ReadHumidity(){
  // read humidity
  float humi  = dht.readHumidity();
  // read temperature as Celsius
  float tempC = dht.readTemperature();
  Serial.println();
  // check if any reads failed
  if (isnan(humi) || isnan(tempC)) {
    Serial.println("Failed to read from DHT sensor!");
  } else {
    Serial.print("Humidity: ");
    Serial.print(humi);
    Serial.print("%");

    Serial.print("  |  ");

    Serial.print("Temperature: ");
    Serial.print(tempC);
    Serial.print("°C ~ ");
  }

}

In this function we use the pre-defined functions from the DHT library to obtain the readings from the sensor. We print out the results in the serial monitor so that we can track the changes. By making sure we include the isnan() function, we check to make sure the readings are number values that can be printed and reflected from the physical environment – allowing a route for display of error messages and communication. This means the system can be aware of potential issues with the reading, ensuring reliability of the future monitoring system.

ReadSoil function:

void ReadSoil(){
  int sensorSoilValue = analogRead(soilSensorPin); // Read soil analog value
  float moisturePercentage = map(sensorSoilValue, 0, 1023, 0, 100); // Map to percentage
  //code to print moisture level to LED sensor

  delay(1000); // Wait for a second before the next reading

}

ReadSoil represents the part of the water pump system responsible for the soil moisture level. We decided to use the analog value and conversion of it through mapping into a percentage for better readability and more intuitive representation of soil moisture to the user. This is the basis of the main code which we will later use to make the irrigation system activate when soil moisture falls below a certain threshold (where optimum conditions of the plant can no longer be satisfied). It is also necessary to incorporate a delay so that there is space between consecutive readings, to allow adjustments of soil as required.

Visual feedback experimentation:

After setting up the hardware and phsyical architecture of pump and system, we decided to experiment with the sensor detections and how we can map them onto visual feedback for example an RGB LED.

RGB feedback of plant soil humidity

This is the code we had to add to activate the functionality of our feedback RGB LED light. In our void setup function we added:

for(int i = 0; i < 3; i++){
    //  set the 3 pins as outputs
    pinMode(ledDigitalOne[i], OUTPUT);

We established the threshold of humidity in which feedback must be shown. The choice of humidity values are relative to the plant optimum conditions required. A response will be triggered when the humidity is too low. Within our ReadHumidity function we added:

 if (humi > 80 || humi < 40) {
    setColor(ledDigitalOne, RED);
  } else {
    setColor(ledDigitalOne, GREEN);
  }

setColor function:

Allows seting up of the LEDs by iteration of the respective pins to visually indicate the conditions like the soil humidity detection

void setColor(int* led, const boolean* color) {
  for(int i = 0; i < 3; i++){
    digitalWrite(led[i], color[i]);
  }
}

Main system architecture design:

For the design we decided to use all recycled materials; with our thought process being resembling of a smal garden made with an eco-conscious approach. The garden design aimed to create a visual aesthetic/appeal for the user, furthermore aligning with the purpose and intention of the project – a familiar and pleasant environment for interactivity and accessibility. By creating a miniature representation of a garden with the automatic plant irrigation system, we foster a sense of engagement and enjoyment; a wholesome experience for a user when making use of the system.

As for the base/foundation of all the components we decided to use a recycled tin foil tray for stability and mounting all our required components on. The shallow edges of the tray also ensured for any potential spill-offs to be caught and overall organizing the appearance of our structure.

We also used scrap paper to create decorative elements on this foil tray resembling of flowers and plants to enhance the aesthetic appeal of the system, likewise with the water tray looking like a watering bucket or can adding a thematic touch to the whole system.

Combining components and feedbacks and testing:

After combining all the elements which we worked on/tested individually beforehand, we had to figure out which feedback would be most approapriate for our system.

Initially we incorporated and additional blue LED in the system, which would dim/brighten in response/correlation with the light sensor detections. However we did not proceed with this as it was rather redundant as this data is already displayed on the OLED screen and isn’t such a drastic influential factor to the irrigation system. This also allowed more simplicity and only the necessary feedback/most useful remained.

Addition of RGB LED:

As a visual feedback choice we enhance the user experience with an RGB LED providing immediate visual feedback without the need for users to wait for the values/confirmation on the OLED screen. This means users instantly gauge the conditions of the plant by the colouring of the LED. This allows for intuitive color recognition and real-time monitoring, making the overall experience rather user-friendly. It is complementary to the OLED display which allows for a comprehensive visual feedback system.

OLED Screen testing:

The OLED screen is our main instant visual feedback that the user can rely on; displaying swift feedback about the plant conditions in an intuitive way. The real-time values are presented (converted to percentages) alongside the temperature in Celsius. We created three separate display screens that cycle through to show to the user.

Add to our void loop:

 //cycles through the 3 different displays
  if (displaynum == 1){
    DisplayFace();
    displaynum = 2;
  }
  else if(displaynum == 2){
    DisplayText();
    displaynum=3;
  }
  else if(displaynum == 3){
    DisplayGoodBad();
    displaynum = 1;
  }

Coding the display of the values:

void DisplayText(){
  display.setTextSize(1); //set the size of the text
  display.setTextColor(WHITE); //color setting
  display.setCursor(0,0); //The string will start at 0,0 (x,y)
  display.clearDisplay(); //Erase the previous display on the screen
  display.print("Soil Moisture: ");
  display.print(100 - soilPercentage); //displays the inverse of the soil percentage as reading a high percentage as water increases is more human friendly
  display.println("%");
  display.print("Humidity: ");
  display.print(humi);
  display.println("%");
  display.print("Temperature: ");
  display.print(tempC);
  display.println("C");
  display.print("Light: ");
  display.print(100 - lightPercentage);
  display.println("%");
  display.display(); //send the text to the screen
}

In another representation we have the numerical values stripped and “Good” or “Bad” messages streamlining communication the user on the plant conditions. This enhances the user-friendly environment by which especially users without technical expertise can grasp the plant healthy without the need of delving into specific numerical readings. Due to this, the system aligns with the goal of making it accessible in many ways to a wide range of users. If a user is not familiar with plant metrics this is ideal and the user will not need to be overwhelmed by any technical details. The indicators are clear and concise and along with the piezo buzzer notification too make it much more inclusive.

Coding the display of good/bad indicators:

/This display shows if the values on the previous display are good or bad, cycling through the facefactors array to see if they are 1(good) or 0(bad)
void DisplayGoodBad(){
  display.setTextSize(1);
  display.setTextColor(WHITE);
  display.setCursor(0,0);
  display.clearDisplay();
  display.print("Soil Moisture: ");
  if(FaceFactors[0] == 1){
    display.println("Good");
  }
  else if(FaceFactors[0] == 0){
    display.println("Bad");
  }
  display.print("Humidity: ");
  if(FaceFactors[1] == 1){
    display.println("Good");
  }
  else if(FaceFactors[1] == 0){
    display.println("Bad");
  }
  display.print("Temperature: ");
  if(FaceFactors[2] == 1){
    display.println("Good");
  }
  else if(FaceFactors[2] == 0){
    display.println("Bad");
  }
  display.print("Light: ");
  if(FaceFactors[3] == 1){
    display.println("Good");
  }
  else if(FaceFactors[3] == 0){
    display.println("Bad");
  }
  display.display(); //send the text to the screen

}

The user will be alerted with the piezo buzzer, and the OLED display which will display and tell the user if the watering can is empty and if it need to be refilled in order for the plant to be watered once again/ for the automatic irrigation system to continue.

We added a Smiley/Sad face display on the OLED as a graphical representation of plant status/ if optimum conditions are reached or not. This enables the user to understand the status at a quick glance without needing to interpret any of the numerical values if they do not want to. This also in a way humanizes the interaction with the plant system, making users more likely to care for and engage with the plant when presented with a communication of a friendly and approachable manner. A smiley face provides a positive reinforcement for users to continue engaging in the plant care and highlights the idea of the users efforts contributing to their plant well-being.

Coding the display of the faces:

void DisplayFace(){
  //check how many of the 4 factors for plant growth are good(1)/bad(0)
  int counter = 0; //sets a counter as a local variable, which gets incremented by 1 as per each factor is good
  for(int i = 0; i <=3; i++){
    if(FaceFactors[i] == 1){ //loops through all 4 items in the global array named facefactors
      counter+=1;
    }
  }

  display.clearDisplay();
  //face
  display.drawCircle(SCREEN_WIDTH / 2, SCREEN_HEIGHT / 2, 30, WHITE); // circle drawn at midpoint of screen with radius 30
  //eyes
  display.drawCircle(SCREEN_WIDTH / 2 - 10, SCREEN_HEIGHT / 2 - 5, 5, WHITE);
  display.drawCircle(SCREEN_WIDTH / 2 + 10, SCREEN_HEIGHT / 2 - 5, 5, WHITE);

  //smily face drawn when all 4 factors are good
  if(counter == 4){
    display.fillCircle(SCREEN_WIDTH / 2, SCREEN_HEIGHT / 2 + 7, 6, WHITE);
    display.fillCircle(SCREEN_WIDTH / 2, SCREEN_HEIGHT / 2 + 6, 6, BLACK); // black circle drawn just above the mouth circle to leave a smily face
  }
  //midface drawn when 1 or 2 factors are bad
  else if (counter > 1 && counter <=3){
    display.fillRect(SCREEN_WIDTH / 2 - 15, SCREEN_HEIGHT / 2 + 10, 30, 3, WHITE);
  }
  //sadface drawn when 3 or 4 factors are bad
  else if(counter <=1){
    display.fillCircle(SCREEN_WIDTH / 2, SCREEN_HEIGHT / 2 + 9, 6, WHITE);
    display.fillCircle(SCREEN_WIDTH / 2, SCREEN_HEIGHT / 2 + 11, 6, BLACK); //black circle drawn just below the mouth circle to leave a frowny face
  }
  display.display();
}

Finalising and putting it all together:

We also decided to implement a controlled watering mechanism, where the water pump only dispenses the water in limited bursts with frequency adjusted based on the plant current conditions. The water pump is limited to only two pumps to prevent the soil from becoming waterlogged and that there is sufficient moisture throughout in this automatic irrigation system; preventing the risk of overwatering and excessing water accumulation which tends to be a frequent cause in plant struggle under manual human care. An automatic irrigation system also avoids water stress on a plant; the adaptive nature means the soil moisture is monitored and if failed and remains dry after the initial watering, will be watered again or detected that the watering can is empty.

Final wiring/arduino breadboard and component layout
Watering/ Irrigation system entering plant
OLED Technical Display version with real-time statistics
Final Design of system

Project Task List

Week 9– selection of topic for project
– creation of low fidelity design prototype
– project objectives and scope definition alongside research
– finalising selection of approapriate components
-All members
-Ben, Cat
-All members
-Ben, Jess
Week 10– ordered all components necessary
– sorting out code structure and logic
– designing overall system architecture and arduino code
– planning layout of physical components for when they arrive
– testing of separate functions for the different components used
-Ben, Jess
-Cat
-All members
-All members
-Ben, Jess
Week 11– design of final outcome and ensuring functionalities
– finalising and organisation of code + comments
– blog creation to compile all previous documentation together
– blog design
– video final product
– final product design/aesthetics
– debugging
-All members
-Ben
-Jess
-Jess
-Ben
-Cat
-Ben, Cat
Timeline and Task management/assignment

Maker Manual

Overview

Happy plant 🙂
Good conditions!
Shows functioning of system (and how light will change depending on conditions i.e. holding DHT sensor to change condition to show the feedback and response to mimic a bad plant condition)

SmartLeaf! Automatic Irrigation, arduino-based system combining technology and commitment to sustainability. A user-friendly graphical interface with an automatic irrigation system designed to revolutionize plant care.

Tools and Supplies

  • Tin foil tray (base of project) – recycled material
  • Scrap paper – recycled material
  • Sellotape
  • Scissors
  • Plastic cups – recycled material
  • Plant in a pot
  • Soil
  • Arduino board
  • Wires
  • Resistors (x4)
  • Piezo buzzer
  • RGB LED
  • Soil moisture sensor
  • DHT (humidity and temperature sensor)
  • Light sensor
  • Water pump
  • Relay module
  • OLED Display
  • Laptop/USB as power supply

Circuit Diagram

Arduino breadboard layout and circuit diagram:

Building System

In crafting the physical aspects of the system we prioritized sustainability through opting to use recyclable materials to pose emphasise on the eco-friendly approach of the project. For the base structure and foundation we used a tin foil tray; a recyclable material providing a foundation for the components and structural integrity. Scrap paper also used for decorative purposes of paper plants/flowers alongside plastic cups to hold the water.

Code

#include "DHT.h"
#define DHTPIN 4
#define DHTTYPE DHT11
DHT dht(DHTPIN, DHTTYPE);
const int soilSensorPin = A0; // Analog input pin for the sensor
const int relayPin = 2;  // Digital output pin connected to the relay module
int ledDigitalOne[] = {6, 3, 7};
const boolean RED[] = {LOW, LOW, HIGH};  //sets the red and green colours for rgb led
const boolean GREEN[] = {LOW, HIGH, LOW};
int lightPin = A1;
int speakerPin = 5;
int displaynum = 1;
int sensorSoilValue ; //global values are created for sensor values so they can read throughout
int FaceFactors[] = {1,1,1,1}; //good(1)/bad(0) for {moisture,humidity,temp,light}
float humi;
float tempC;
int lightLevel;
float lightPercentage;
float soilPercentage;

//sets up screen
#include <SPI.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#define SCREEN_WIDTH 128 // OLED display width, in pixels
#define SCREEN_HEIGHT 64 // OLED display height, in pixels
// Declaration for SSD1306 display connected using software SPI (default case):
#define OLED_MOSI   9
#define OLED_CLK   10
#define OLED_DC    11
#define OLED_CS    12
#define OLED_RESET 13
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT,
  OLED_MOSI, OLED_CLK, OLED_DC, OLED_RESET, OLED_CS);


void setup() {
  Serial.begin(9600); // Initialize serial communication
  dht.begin(); //starts humidity/temp sensor
  for(int i = 0; i < 3; i++){
    //  set the 3 pins as outputs on the RGB LED
    pinMode(ledDigitalOne[i], OUTPUT);
  }
  pinMode(relayPin, OUTPUT);
  digitalWrite(relayPin, HIGH);
  //screen
  if(!display.begin(SSD1306_SWITCHCAPVCC)) {
    Serial.println(F("SSD1306 allocation failed"));
    for(;;); // Don't proceed, loop forever
  }

}


void loop() {
  //lightcode
  ReadLight();
  //soil code
  ReadSoil();
  //humidity and temperature code
  ReadHumidityTemp();
  delay(1000); // Wait for a second before the next reading

  //cycles through the 3 different displays
  if (displaynum == 1){
    DisplayFace();
    displaynum = 2;
  }
  else if(displaynum == 2){
    DisplayText();
    displaynum=3;
  }
  else if(displaynum == 3){
    DisplayGoodBad();
    displaynum = 1;
  }
}


void DisplayFace(){
  //check how many of the 4 factors for plant growth are good(1)/bad(0)
  int counter = 0; //sets a counter as a local variable, which gets incremented by 1 as per each factor is good
  for(int i = 0; i <=3; i++){
    if(FaceFactors[i] == 1){ //loops through all 4 items in the global array named facefactors
      counter+=1;
    }
  }

  display.clearDisplay();
  //face
  display.drawCircle(SCREEN_WIDTH / 2, SCREEN_HEIGHT / 2, 30, WHITE); // circle drawn at midpoint of screen with radius 30
  //eyes
  display.drawCircle(SCREEN_WIDTH / 2 - 10, SCREEN_HEIGHT / 2 - 5, 5, WHITE);
  display.drawCircle(SCREEN_WIDTH / 2 + 10, SCREEN_HEIGHT / 2 - 5, 5, WHITE);

  //smily face drawn when all 4 factors are good
  if(counter == 4){
    display.fillCircle(SCREEN_WIDTH / 2, SCREEN_HEIGHT / 2 + 7, 6, WHITE);
    display.fillCircle(SCREEN_WIDTH / 2, SCREEN_HEIGHT / 2 + 6, 6, BLACK); // black circle drawn just above the mouth circle to leave a smily face
  }
  //midface drawn when 1 or 2 factors are bad
  else if (counter > 1 && counter <=3){
    display.fillRect(SCREEN_WIDTH / 2 - 15, SCREEN_HEIGHT / 2 + 10, 30, 3, WHITE);
  }
  //sadface drawn when 3 or 4 factors are bad
  else if(counter <=1){
    display.fillCircle(SCREEN_WIDTH / 2, SCREEN_HEIGHT / 2 + 9, 6, WHITE);
    display.fillCircle(SCREEN_WIDTH / 2, SCREEN_HEIGHT / 2 + 11, 6, BLACK); //black circle drawn just below the mouth circle to leave a frowny face
  }
  display.display();
}


void DisplayText(){
  display.setTextSize(1); //set the size of the text
  display.setTextColor(WHITE); //color setting
  display.setCursor(0,0); //The string will start at 0,0 (x,y)
  display.clearDisplay(); //Erase the previous display on the screen
  display.print("Soil Moisture: ");
  display.print(100 - soilPercentage); //displays the inverse of the soil percentage as reading a high percentage as water increases is more human friendly
  display.println("%");
  display.print("Humidity: ");
  display.print(humi);
  display.println("%");
  display.print("Temperature: ");
  display.print(tempC);
  display.println("C");
  display.print("Light: ");
  display.print(100 - lightPercentage);
  display.println("%");
  display.display(); //send the text to the screen
}

//This display shows if the values on the previous display are good or bad, cycling through the facefactors array to see if they are 1(good) or 0(bad)
void DisplayGoodBad(){
  display.setTextSize(1);
  display.setTextColor(WHITE);
  display.setCursor(0,0);
  display.clearDisplay();
  display.print("Soil Moisture: ");
  if(FaceFactors[0] == 1){
    display.println("Good");
  }
  else if(FaceFactors[0] == 0){
    display.println("Bad");
  }
  display.print("Humidity: ");
  if(FaceFactors[1] == 1){
    display.println("Good");
  }
  else if(FaceFactors[1] == 0){
    display.println("Bad");
  }
  display.print("Temperature: ");
  if(FaceFactors[2] == 1){
    display.println("Good");
  }
  else if(FaceFactors[2] == 0){
    display.println("Bad");
  }
  display.print("Light: ");
  if(FaceFactors[3] == 1){
    display.println("Good");
  }
  else if(FaceFactors[3] == 0){
    display.println("Bad");
  }
  display.display(); //send the text to the screen

}

void ReadLight(){
  lightLevel = analogRead(lightPin);  
  lightPercentage = map(lightLevel, 0, 1023, 0, 100); //maps the lightlevel to a percentage
  if(lightPercentage > 78){ //If the percentage of light is less than 22%(Value on OLED), then thats bad
    FaceFactors[3] = 0;
  }
  else{
    FaceFactors[3] = 1;
  }
}

void ReadHumidityTemp(){
  // read humidity
  humi  = dht.readHumidity();  //uses dht library
  // read temperature as Celsius
  tempC = dht.readTemperature();
  Serial.println();
  // check if any reads failed
  if (isnan(humi) || isnan(tempC)) { //if not a number returned, alert developer that the dht sensor is not working
    Serial.println("Failed to read from DHT sensor!");
  } else {
  }
  if (humi > 80 || humi < 40) {  //led set to let the user know if the humidity is good or bad
    setColor(ledDigitalOne, RED);
    FaceFactors[1] = 0;
  } else {
    setColor(ledDigitalOne, GREEN); //calls set colour with the green boolean array created
    FaceFactors[1] = 1;
  }
    if (tempC<15 || tempC >25) {
    FaceFactors[2] = 0;
  } else {
    FaceFactors[2] = 1;
  }
}


void setColor(int* led, const boolean* color) {
  for(int i = 0; i < 3; i++){ //cycles though the LED pins in the rgb led and sets based on the values written in the colour array specified
    digitalWrite(led[i], color[i]);
  }
}


//function to acitivate the pump
void activatePump(){
  for(int i = 0; i <2;i++){ //pump lets out 2 squirts of water
    digitalWrite(relayPin, LOW);  // Turn on the relay, which activates the pump
    delay(1000);      
    digitalWrite(relayPin, HIGH);   // Turn off the relay, turning off the pump
    delay(1000);
  }

  sensorSoilValue = analogRead(soilSensorPin);
  soilPercentage = map(sensorSoilValue, 200, 600, 0, 100);
  if (soilPercentage >50) { //after reading the moisture sensor again after watering, it lets you know if its still dry(water can is empty)
    tone(speakerPin, 1600, 2000); //annoying noise is played to annoy the user into filling the can
    display.setTextSize(2); //makes larger text
    display.setCursor(0, 0);
    display.clearDisplay();
    display.print("Watering  Can is    empty!");
    FaceFactors[0] = 0; //sets moisture to bad
    display.display();
  }
  else{ // it was successfully watered, shown by a melody
    tone(speakerPin, 1400, 700); //1400 pitch at a duration of 700
    delay(150);
    tone(speakerPin, 1800, 300);
    delay(150);
    tone(speakerPin, 1600, 700);
    delay(150);
  }
}


void ReadSoil(){
  sensorSoilValue = analogRead(soilSensorPin); // Read soil analog value
  soilPercentage = map(sensorSoilValue, 200, 600, 0, 100);// the readings we found were between 200 and 600 so we mapped this to a percentage
  FaceFactors[0] = 1;
  if (soilPercentage >45) {  //if the soil moisture is less than 55%(print screen) then water the plant
    // Activate the water pump using the relay
    activatePump();
  }
  else{
    delay(2000);
  }

}

Testing and Shortcomings

As seen in the design blog, there was many testing conducted of the different components and their effectivity or redundancy in demonstrating our project

  • Single threshold for humidity: different types of plants have varying optimal humidity conditions therefore system may not be adequate or suitable for all the kinds of plants available.
    • One way this could be overcome in further development is by the creation of a more rigorous algoerithm with customisable thresholds for the possible types of plants used.
  • Power dependency: the system relies on a usb connection to a computer for example, meaning it isnt completely versatile and limits the ability of outdoor location use.
    • Could be overcome by design of waterproof enclosure for the physical electronic components (like the power supply); meaning system can be used outdoors and protected from natural elemental conditions.
  • Scalability: the system is designed for a singular area of plant/soil based on the detectors and sensore therefore it is limited for larger setups.