Josh Leong

Biomedical Engineering @ Imperial

Creating a sensor based system to increase crop yield

The need for this system

In the Summer of 2025, my brother was gifted an assortment of plants (pictured below) to grow. During this time, London (unexpectedly) had a beautiful stretch of hot weather allowing his tomato and chilli plant to grow well. However, not all ideal conditions last, and this inspired me to think of a solution. My idea was to use a simple Arduino kit with a very basic DHT11 sensor in order to detect temperature and humidity levels and then to automate a response which in theory will allow the user to create the perfect conditions to grow their plants.

Tomato and chilli plants
My Brother's Chilli and Tomato plants in July 2025

The Plan

My idea was to create a simple negative feedback loop to regulate conditions back to a standard temperature and humidity. The focus on these two measurements is due to my focus on using the DHT11 sensor. Humidity and temperature will each be changed individually by one device each making control of the entire system easier.

Tomato and chilli plants
Feedback loops to show how a change in temperature or humidity would be handled

Circuit Design

I began by using an Elegoo Arduini UNO R3, and connecting a simple DHT11 sensor to a LCD 1602 module. It was during the building of this circuit that I was exposed to the inconsistencies of prototyping with a breadboard. At times, a single loose connection or two exposed wires touching caused short circuits which led to my Arduino heating up rapidly. Digital testing via TinkerCad should've been utilised more in my case to avoid accidents. The 10K potentiometer is used to adjust the contrast of the LCD screen which in turn adjusts brightness.

Tomato and chilli plants
Circuit Diagram of the DHT11 Sensor (replaced with a temperature sensor) and LCD screen

Code

#include <LiquidCrystal.h>
#include <dht.h> //importing relevant libraries
 
LiquidCrystal lcd(12, 11, 5, 4, 3, 2);
int data = A0; // output outpin
dht sensor;
 
void setup()
{
  lcd.begin(16,2); //16 col by 2 rows character display 
  Serial.begin(9600);
  while (!Serial);
}
void loop()
{
  delay(1000); //wait a sec
  sensor.read11(data);
  lcd.clear();
  lcd.setCursor(0,0); // col 0 , row 0
  lcd.print("Humidity = ");
  lcd.print(sensor.humidity);
  lcd.setCursor(0,1); // row 0 , col 1
  lcd.print("Temp = ");
  lcd.print(sensor.temperature);
  Serial.print(millis() / 1000.0); // time in seconds
  Serial.print(",");
  Serial.print(sensor.temperature);
  Serial.print(",");
  Serial.println(sensor.humidity);
}

The code above gives allows the LCD to display the temperature and humidity on the LCD screen, which would give the user basic information for them to create a response.

LCD display
The LCD display showing data measurements from the DHT11 Sensor

At this point, I thought that the device was little basic and I wanted to somehow manipulate this data to give insights for the user. As a result I used python to plot graphs to show how temperature and humidity varied with time for the user to identify changes within the environment. The idea was that, the user could identify when conditions were non - ideal for the plants to generate a response.

from serial.tools import list_ports
import serial
import csv
import time

ports = list_ports.comports()
for port in ports: print(port)

f = open("data.csv", "w", newline = "")
f.truncate()


serialCom = serial.Serial("COM8", "9600")

# Reset arduino
# Simulates USB disconnect
serialCom.setDTR(False) 
time.sleep(1) # stop one sec
serialCom.flushInput()
# "usb connects again"
serialCom.setDTR(True)


while True:
    try:
        Time = float(input("Enter the number of minutes you would like to record? "))
        break
    except:
        print("Please enter a numerical value.")

data_points = Time * 60  # 1 second a point
points = int(data_points) # data points to record
for reading in range(points):
    try:
        s_bytes = serialCom.readline()
        # Decode binary 
        decoded_bytes = s_bytes.decode("utf-8").strip("\r\n")
        #print(decoded_bytes)

        # parsing lines
        
        values = decoded_bytes.split(",")
        
        
        values = [float(x) for x in decoded_bytes.split(",")]
        print(values)

        writer = csv.writer(f,delimiter = ",")
        writer.writerow(values)

    except:
        print("ERROR, line not recorded")

f.close()

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt

# import data with pandas to create a table
# add headers to the table
data = pd.read_csv("data.csv", header=None, names=["Time", "Temp", "Humidity"])

print(data)

plt.subplot(2, 2, 1)
plt.plot(data["Time"], data["Temp"], label="Temperature(°C)")
plt.xlabel("Time (s)")
plt.ylabel("Temperature (°C)")
plt.title("Temperature vs Time")
plt.grid(True)
plt.legend()


plt.subplot(2,2,2)
plt.plot(data["Time"], data["Humidity"], label = "Humidity(%)")
plt.xlabel("Time (s)")
plt.ylabel("Humidity (%)")
plt.title("Humidity vs Time")
plt.grid(True)
plt.legend()

plt.tight_layout()
plt.show()

The Python code allows for communication between the Arduino and Python. The code writes the data from the DHT11 sensor into a CSV file. The Pandas library then turns this data into a table with headings and using Matplotlib, I was able to easily plot data from each table heading. As well as this, the user can also decide the timeframe that they measure over. Although basic, I was able to generate line graphs to show how humidity and temperature changed with time. At this point in the project, I did not have a clear vision of what I wanted to do for an automated response.

First figure
Temperature and Humidity plotted against time on Matplotlib
Second figure
Terminal readings from python code

With the sensors and graphs now working, it was time to move onto creating a response to this data.

Response

Originally, I planned to use a motor (controlled by a transistor) with a fan to cool and reduce humidity. However, I ran into power distribution problems. If the fan was implemented then the LED screen would not display correctly and this meant that I needed another power supply which I did not want as the whole device would feel clunky. In the end, I stuck to not using a fan as the fan's job of reducing humidity and temperature could be easily done by the user opening a window.

First figure
The proposed circuit with a fan attached and controlled via a transistor

In the end I decided to buy an ultrasonic humidifier from Amazon as I believed that increasing humidity is a harder task for everyday users. I decided to buy the model shown below.

First figure
A screenshot of the purchased humidifier

During the implementation of this humidifier, I realised I made a massive oversight in my purchase. The purchased humidifier worked by connecting the humidifier via a USB cable which is not compatible with my Arduino UNO R3. This meant that to power the humidifier, I needed to use another laptop port. This was a problem as I wanted to use the Arduino to communicate to the humidifier to switch it on and off. In the end I decided to keep using a separate port for the humidifier but this came with some complications.

Upon researching ways to control the port in which the humidifier would be attached to, I considered using Python to switch the port on and off. However, since I am using Windows OS, this would not be possible as this method would require Mac OS or Linux OS. Whilst researching this, another massive oversight occurred. I had assumed that the humidifier was a "dumb" device that switched on and off when powered and when power disconnected. In reality the humidifier required the button to be pushed before switching on after being powered. This meant that even if I did connect the humidifier to the Arduino board, a button would still need to be pressed which cannot be done by code. As a result, I left the setup as shown below.

First figure
The full setup with the Humidifier

Although, not being able to connect my humidifier to the Arduino meant that I could not automate the system, I decided to compromise by changing my Arduino code to display to the user when to switch the humidifier on and off.

#include <LiquidCrystal.h>
#include <dht.h>

LiquidCrystal lcd(12, 11, 5, 4, 3, 2);
int data = A0;
dht sensor;

void setup() {
  lcd.begin(16, 2); // 16 by 2 character display
  Serial.begin(9600);
  while (!Serial);
}

void loop() {
  delay(1000); // wait a sec (recommended for DHT11)
  sensor.read11(data);
  float temp = sensor.temperature;
  float hum = sensor.humidity;

  lcd.clear();

  if (temp > 30) {
    lcd.setCursor(0, 0);
    lcd.print("Temp too high");
    lcd.setCursor(0, 1);
    lcd.print("Humidifier ON"); 
  }
  else if (hum < 10) {
    lcd.setCursor(0, 0);
    lcd.print("Humidity low!");
    lcd.setCursor(0, 1);
    lcd.print("Add moisture");
  }
  else {
    lcd.setCursor(0, 0);
    lcd.print("Humidity = ");
    lcd.print(hum);
    lcd.setCursor(0, 1);
    lcd.print("Temp = ");
    lcd.print(temp);
  }

  Serial.print(millis() / 1000.0); // time in seconds
  Serial.print(",");
  Serial.print(temp);
  Serial.print(",");
  Serial.println(hum);
}

The updated code simply adds parameters of temperature and humidity to the code (this would ideally be set to the ideal values for their plants). The user would then be alerted about when to turn the humidifier on or off.

Design alterations

Since, the device could no longer be automated, I decided to change the design. I plan to have two modes. One for data driven insights where the board will be connected via USB to the laptop so graphs can be generated and another where the board will be battery powered to be used as a portable device for everyday use. Although, I stated above that the humidifier could only be connected to my laptop, I made another oversight where I did not realise that I could use a portable charger to power it instead. In total my design will feature two separate devices, one to track temp and humidity and the humidifier will be separate to generate a response.

Final comments

In general, I thought this design was a bit weak as it was not automated and required the user to manually press buttons for a response. This was largely due to massive oversights when purchasing equipment where I did not consider how different components would connect to the Arduino board. In the future, I will try to test more at the University lab before I fully commit to buying equipment just so I know which components connect in what way. In the future, I will also create a whole plan first with my designs before actually building anything. I felt that this project was a massive improvisation and in the end the lack of planning meant that I did not have a clear vision when building.