Introduction: Plant Care Automation With Arduino and Raspberry Pi Expansion

About: I build things

An Automated System that waters and looks after your plant. features expandability and a wide range of sensors and features.

Supplies

Materials

  • 2 Containers
  • 1 Pump 5 volt
  • 1 Arduino
  • 1 Raspberry Pi (for expansion)
  • 1 Water level sensor
  • 1 Capacitive moisture sensor
  • 1 Dht11 temp and humidity sensor
  • 1 SPI oled display (128x64)
  • 1 Five volt relay
  • 1 Power supply board (look up Elegoo) and a 9 volt battery
  • 1 Power bank for Pi and/or Arduino
  • 1 Breadboard
  • Cables
  • Tubing and cable ties

Tools

  • Double sided tape
  • Duct tape and bluetack is useful but not necessary
  • Screw driver flathead
  • Drill

Software

  • Arduino ide

Step 1: What the System Is Built for and What It Does

So this system is built to water and display data about the plant and the enviroment around it. It uses a DHT11 sensor to get temprature and humidity. Uses Capacitive soil moisture Sensor to get the moisture levels of the soil and tell the pump if the plant needs more water. Uses a Water level Sensor to prevent the pump from running dry. All of this infomation is displayed to a 1.3" ips Oled Display. You can expand on this system with a Raspberry Pi and Python adding things such as a camera to monitor the plant from somewhere else, saving the data to a file, sending emails to fill the container, display info on a public website and more. This guide is only covering the Arduino side of things.

Step 2: Setting Up Bread Board Power

  1. Add power supply to breadboard
  2. Connect 3.3v to a rail on breadboard
  3. Connect GND to GND on Breadboard

Step 3: Wiring the Sensors

DHT11:

Connect Signal to A0 on Arduino

Connect negative to GND rail on breadboard

Connect positive to 3.3v rail on breadboard (The 3.3v from the arduino)


Capacitive soil sensor:

Connect GND to GND rail on breadboard

Connect VCC to 3.3v rail (same as the DHT11)

Connect Aout (signal) to A1 on Arduino


Water Level Sensor:

Connect negative to GND rail on breadboard

Connect positive to Pin 7 on Arduino

Connect Signal to A3 on Arduino

Step 4: Pump and Relay

Relay:

Connect negative to GND rail on breadboard

Connect positive to 5v on Arduino

Connect Signal to Pin 4 on Arduino

Need Screwdriver for next two

Unscrew and Connect C (the middle slot) to Power Rail. Make sure to screw it back in

Unscrew and connect the NO slot to the Positive of the pump. I would suggest using an alligator clip or a female to male connector wire for the pump wires.

Don't connect the pump negative to the GND rail on the breadboard until you are ready to test it. Make sure you have water as to not burnout the pump. Alternatively you can use a motor to test the code as they are functionally the same thing. When you are planning on using the Pump make sure the power supply module is on.

Step 5: Oled Display

Oled:

Connect GND to GND on Arduino

Connect VCC to Power rail on Breadboard

Connect CLK (D0) to Pin 13 on Arduino

Connect MOSI (D1) to Pin 11 on Arduino

Connect RES to Pin 8 on Arduino

Connect DC to Pin 9 on Arduino

Connect CS to Pin 10 on Arduino

You can display different images on the Oled besides the included image. Im not covering that here but I'll link some GUIDES for those who want to explore that option. The image that is included is Patrick Bateman, because why not.

Step 6: Birds Nest

If wired up correctly you should end up with this birds nest of wires.

grab two container, 1 for the pump and water level sensor. The other to house all the electronics.

Double sided tape is your Friend. I also Drilled holes in the lids of the containers to allow the sensors and cables out while protecting the electronics. If your worried about the sensors getting water damage you can use a couple layers of clear nail polish to Protect them from the water. Bluetack and duct tape is also a good combo for water proofing the holes in the container.

Step 7: CODE

#include "U8glib.h"      // Libraries
#include "dht.h"


#define dht_apin A0                      // Define DHT pin
#define sensorPower 7                    // Define water level pin
#define sensorPin A2
#define requiredWaterLevel 110           // Minimum water level requirement till the pump stops working
#define minute5_to_seconds 300            // Convert 5 minutes into seconds


long current_seconds = 0;                // declare globally
int sensor_moist = A1;                   // Signal from the capacitive soil moisture sensor
int output_value ;                       // Value of soil moisture
int pump = 4;                            // Digital pin where the relay is plugged in
int threshold = 19;                      // Threshold value to trigger pump
int val = 0;                             // Value for storing water level
int level = 0;


bool hasWater = false;                   // Check if the pump has water to start off with


void runPump(int output_value);
void stopRun();
void render();


dht DHT;


U8GLIB_SH1106_128X64 u8g(13, 11, 10, 9, 8);  // D0=13, D1=11, CS=10, DC=9, Reset=8 // tells u8.glib what model screen is used
// Image in the oled
const uint8_t Bate_bitmap[] PROGMEM = {
  0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1C, 0x00, 0x10, 0x00, 0x00, 0x00, 0x18, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x38, 0x00, 0x40, 0x00, 0x00, 0x00, 0x70, 0x3F, 0xE0, 0x00, 0x00, 0x00,
  0xF0, 0x3F, 0xF0, 0x00, 0x00, 0x00, 0xE0, 0x1F, 0xF8, 0x00, 0x00, 0x01, 0xE0, 0x1F, 0xF8, 0x00,
  0x00, 0x01, 0xC0, 0x1F, 0xFC, 0x00, 0x00, 0x00, 0x80, 0x3F, 0xFC, 0x00, 0x00, 0x00, 0xC0, 0x1F,
  0xFC, 0x00, 0x00, 0x00, 0xC0, 0x1F, 0xFC, 0x00, 0x00, 0x01, 0x80, 0x0F, 0xFC, 0x00, 0x00, 0x01,
  0x80, 0x0F, 0xFC, 0x00, 0x00, 0x01, 0x80, 0x0F, 0xFC, 0x00, 0x00, 0x01, 0x80, 0x03, 0x7C, 0x00,
  0x00, 0x01, 0x00, 0x03, 0x3C, 0x00, 0x00, 0x01, 0x00, 0x23, 0x0C, 0x00, 0x00, 0x01, 0x00, 0x03,
  0x0C, 0x00, 0x00, 0x01, 0x00, 0x03, 0x0C, 0x00, 0x00, 0x01, 0x00, 0x63, 0xBC, 0x00, 0x00, 0x01,
  0x01, 0xE3, 0xFC, 0x00, 0x00, 0x01, 0x81, 0xE3, 0xFC, 0x00, 0x00, 0x03, 0x81, 0xE3, 0xFC, 0x00,
  0x00, 0x03, 0xD1, 0xC3, 0xFC, 0x00, 0x00, 0x00, 0xD0, 0x03, 0xFC, 0x00, 0x0C, 0x00, 0xD0, 0x01,
  0xBC, 0x00, 0x1C, 0x00, 0x10, 0x03, 0xF8, 0x00, 0x0C, 0x01, 0x80, 0x03, 0xDF, 0x00, 0x0C, 0x00,
  0x10, 0x0F, 0xCF, 0x00, 0x00, 0x00, 0x10, 0x1F, 0xDF, 0x00, 0x00, 0x00, 0x12, 0x1F, 0xFE, 0x00,
  0x00, 0x18, 0x12, 0x0F, 0xE0, 0x00, 0x00, 0x18, 0x00, 0x3F, 0xE0, 0x00, 0x00, 0x38, 0x00, 0x1F,
  0xE0, 0x00, 0x00, 0x38, 0x00, 0x07, 0xC0, 0x00, 0x00, 0x78, 0x00, 0x07, 0xC0, 0x00, 0x00, 0x70,
  0x00, 0x0F, 0xE0, 0x00, 0x00, 0x70, 0x00, 0x5F, 0xE0, 0x00, 0x00, 0x00, 0x10, 0x1F, 0xC0, 0x00,
  0x00, 0x00, 0x10, 0x1F, 0xE0, 0x00, 0x00, 0x00, 0x10, 0x1F, 0xE0, 0x00, 0x00, 0x00, 0x30, 0x07,
  0xE0, 0x00, 0x00, 0x00, 0x70, 0x03, 0xE0, 0x00, 0x00, 0x00, 0x70, 0x07, 0xE0, 0x00, 0x00, 0x00,
  0x90, 0x07, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x07, 0xE0, 0x00,
  0x00, 0x00, 0x03, 0x03, 0xE0, 0x00, 0x11, 0x03, 0xA6, 0xB6, 0x48, 0xF2, 0x3C, 0x05, 0x3D, 0x5B,
0xEC, 0x12,
};


void draw() {
  u8g.drawBitmapP( 76, 5, 6, 50, Bate_bitmap);  // Put bitmap
  //u8g.setFont(u8g_font_unifont);  // Select font
  u8g.setFont(u8g_font_6x13); // Smaller font
  u8g.drawStr(0, 10, "Temp: ");   // Put string of display at position X, Y
  u8g.drawStr(0, 25, "Hum: ");
  u8g.drawStr(0, 40, "Soil: ");
  u8g.drawStr(0, 55, "Water: ");
  u8g.setPrintPos(44, 10);  // Set position
  u8g.print(DHT.temperature, 0);  // Display temperature from DHT11
  u8g.drawStr(60, 10, "c ");
  u8g.setPrintPos(44, 25);
  u8g.print(DHT.humidity, 0);  // Display humidity from DHT11
  u8g.drawStr(60, 25, "% ");
  u8g.setPrintPos(44, 40);
  u8g.print(output_value);  // Display soil moisture from sensor
  u8g.drawStr(60, 40, "%");
  u8g.setPrintPos(44, 55);
  u8g.print(level < requiredWaterLevel ? "Fill" : "Good");  // Display water level from sensor
}


void setup() {
  Serial.begin(9600);
 
  pinMode(sensorPower, OUTPUT);    // Set D7 as an OUTPUT
  digitalWrite(sensorPower, LOW); // Set to LOW so no power flows through the sensor


  pinMode(sensor_moist, INPUT);    // Setup for the soil moisture sensor aka INPUt
  pinMode(pump, OUTPUT);         // Setup for the pump aka OUTPUT
 
  level = readSensor();


  Serial.println("Reading From the Sensor ...");
  delay(1000);  // 1 second delay
}


void loop() {
  current_seconds++; // increment by one every second.
 
  output_value = analogRead(sensor_moist);            // Gets the value from the soil moisture sensor
  output_value = map(output_value, 550, 0, 0, 100);  // This sets the percentage value
 
  Serial.print("Moisture : ");
  Serial.print(output_value);                        // Print the percent of soil moisture - max is 33% if dipped in a cup of water
  Serial.println("%");
 
  if ((current_seconds % minute5_to_seconds) == 0 && hasWater) runPump(output_value);
  if ((current_seconds % minute5_to_seconds) == 1) stopPump();


  level = readSensor(); // Get the reading from the function below and print it
  Serial.print("Water level: ");
  Serial.println(level);
     
  DHT.read11(dht_apin);  // Read apin on DHT11


  render();


  delay(1000);
}


int readSensor() {
  // Water level sensor code
  digitalWrite(sensorPower, HIGH);                      // Turn the sensor ON
  delay(10);                                            // Wait 10 milliseconds
  val = analogRead(sensorPin);                          // Read the analog value form sensor
  digitalWrite(sensorPower, LOW);                       // Turn the sensor OFF
  hasWater = val > requiredWaterLevel;                  // Update variable based on water level
  if (!hasWater)
    Serial.println("Fill me up");
  return val;                                           // Send current reading
}


void runPump(int output_value) {
  if (output_value < threshold)  // If the soil is dry then pump out water for 1 second
  {
    digitalWrite(pump, HIGH);
    Serial.println("pump on for 1 second");
  }
  else
  {
    digitalWrite(pump, LOW);
    Serial.println("do not turn on pump");
  }
}


void stopPump() {
  digitalWrite(pump, LOW);
  Serial.println("pump off");
}


void render() {
  u8g.firstPage();  
  do {
    draw();
  } while( u8g.nextPage() );
}

// dont copy after here
//Copy this Code into your IDE and when your ready to test the whole circuit plug the Pump ground into the GND rail //of the breadboard.

You can change the time it takes for the pump to check if it needs watering by changing the number after

#define minute5_to_seconds  

I have it set up for 300 which is 5 minutes. other times include 10 = 600, 15 = 900 so on.

You can also change the level of water you need for the pump to run with by changing the number after

#define requiredWaterLevel

I have it set at 110 for leniency but you can go lower or higher for your use case. This is so the pump doesnt run dry and burn out.

You can change the degree of moisture in the soil required to turn the pump on by changing the number after

int threshold = ;

I would suggest testing your soil sensor in dry soil and in water to get the min and max readings as there are variation between them as they can give wildly differant readings from sensor to sensor. I found dry soil for mine to be about 18 ~ 21 I chose 18 but the type of plant matters as well.

Make sure You Download This DHT lib. For the U8Glib library download it straight of the IDE just look up U8Glib.

Step 8: Final Product

Put the soil sensor into the plant and make sure everything is wired up and that theres water in the pump container.

If all is done properly then you have a working and automated plant care system.

The Raspberry pi is for further expansion at your own leisure.

*Note Be careful when turning on the power supply and battery pack as if you used water proofed the holes like i did you might disconnect the cables when lifting the lid up too far.

Step 9: Let Me Know How You Did

I hope this was useful For some College students in a couple of years. And to everyone else thanks for getting this far.

Step 10: Sites, Guides and Further Learning

Here are the sites I used and drew inspiration from:

Coraline Dunn and her plant watering automation:

https://github.com/carolinedunn/Plant-Watering

https://github.com/carolinedunn/Plant_Management_ESP8266

Her Youtube Vids: Plant watering and Plant watering with wifi capabilities

Brainy Bits and there DHT11 and Oled

https://www.brainy-bits.com/post/how-to-connect-and-use-an-spi-oled-display

https://www.brainy-bits.com/post/how-to-use-the-dht11-temperature-and-humidity-sensor-with-an-arduino

His Youtube Vids: DHT11 and Oled and DHT11

Last Minute Engineers and there Tutorials on the Oled and Water Level Sensor

https://lastminuteengineers.com/water-level-sensor-arduino-tutorial/

https://lastminuteengineers.com/oled-display-arduino-tutorial/

Oliver Kraus for His U8Glib library.

https://github.com/olikraus/U8glib_Arduino

*Challenge: Change the image to this as a gif while running everything else.

https://youtu.be/dQw4w9WgXcQ