Smart House Plant Watering System

Do not be discouraged if you are not a green thumber! Here is a watering system that can account for complex human lifestyles.

projectImage

Things used in this project

 

Hardware components

HARDWARE LIST
1 DFRobot Gravity: Analog Capacitive Soil Moisture Sensor- Corrosion Resistant
1 Particle Argon
1 ElectroPeak 0.96" OLED 64x128 Display Module
1 Relay (generic)
1 General Purpose Transistor PNP
1 Resistor 221 ohm
1 Resistor 2.21k ohm
1 DC motor (generic)
1 SparkFun Atmospheric Sensor Breakout - BME280
1 Seeed Grove - Dust Sensor(PPD42NS)
1 Seeed Grove - Air quality sensor v1.3

Software apps and online services

Autodesk Fusion 360: https://www.hackster.io/autodesk/products/fusion-360?ref=project-384696

 

Microsoft Visual Studio Code Extension for Arduino

 

Adafruit.io

Hand tools and fabrication machines

 

Plier, Long Nose

 

Plier, Cutting

 

Plier, Needle Nose

 

Wire Stripper & Cutter, 30-10 AWG Solid & Stranded Wires

 

10 Pc. Jumper Wire Kit, 5 cm Long

 

Breadboard, Plastic

Story

 

This plant watering system has the capability to communicate with you wherever you are as long as you have a phone with service. Furthermore, it will be able to maintain the most vibrant colors and complexion of any plant simply by measuring the plants moisture level and constantly setting it to match that environment. The system utilizes a DC motor component, which will act like a pump in order to continuously keep the plant at optimal hydration levels. The system, along with its multiple components, work together to gather and display data from the environment around you such as air quality, or temperature! The overall project of making a Smart Plant Watering System began on 19-Apr-2021 and took till around 1700 on 22-Apr-2021 to finish constructing. The process overall was challenging in the implementation of the two Seeed devices because I had not worked with those prior to this project. Their integration from Seeeduino into Visual Studio Code was difficult but looking at other source code helped aid that process. Furthermore, the implementations of a watering system that would dual as a self sustaining system was difficult due to the design of the flowerpots and flowerpots holder. The difficulty lies within the clogging of the drainage avenues designed for these tasks and the overall lack of time. Publishing and subscribing feeds on Adafruit.io was a rather simple task to complete due to its repetitive nature but the combining of Zapier made that process a little bit more difficult. Designing the aesthetics of this project was rather easy because I bought most of the pieces at the store in order to be able to fully focus on the coding and Wifi implications. In conclusion, this project has major advantages to improving the quality of life for day to day Americans and I am excited to see what further projects or IoTers will do with this piece of information.

 

projectImage
projectImage
projectImage

Schematics

 

The Fritz for the Smart Watering System

icon l14_04_plantwaterfritz_8SOT3ty6k7.zip 265KB Download(2)

Picture of FRITZ

projectImage

Code

Water System Code

C/C++

It is a code on Visual Studio Code designed to water the plant automatically when the soil moisture drops beneath 45 %.

CODE
/*
 * Project L14_04_PlantWater
 * Description: Getting our plant water the quick way
 * Author: Kareem Crum
 * Date: 19-APR-2021
 */

//#include's
#include <Adafruit_MQTT.h>
#include <SPI.h>
#include <Wire.h>

#include "Adafruit_MQTT/Adafruit_MQTT.h" 
#include "Adafruit_MQTT/Adafruit_MQTT_SPARK.h" 
#include "Adafruit_MQTT/Adafruit_MQTT.h" 
#include "Adafruit_BME280.h"
#include "Adafruit_Sensor.h"
#include "Grove_Air_quality_Sensor.h"

#include "Adafruit_SSD1306.h"
#include "credentials.h"
#include "math.h"

#define SCREEN_WIDTH 128 // OLED display width, in pixels
#define SCREEN_HEIGHT 64 // OLED display height, in pixels
#define OLED_RESET    D4 // Reset pin # (or -1 if sharing Arduino reset pin)
#define SCREEN_ADDRESS 0x3C ///< See datasheet for Address; 0x3D for 128x64, 0x3C for 128x32


//Global State
TCPClient TheClient;

//Adafruit BME class
Adafruit_BME280 bme;

//Grove Air Quality Sensor class
AirQualitySensor sensor(A2);

//Adafruit display class
Adafruit_SSD1306 display(OLED_RESET);

//MQTT client class
Adafruit_MQTT_SPARK mqtt(&TheClient,AIO_SERVER,AIO_SERVERPORT,AIO_USERNAME,AIO_KEY); 

//Feeds
Adafruit_MQTT_Subscribe mqttSub1 = Adafruit_MQTT_Subscribe(&mqtt, AIO_USERNAME "/feeds/manuelButton"); 
Adafruit_MQTT_Publish Moist = Adafruit_MQTT_Publish(&mqtt, AIO_USERNAME "/feeds/SoilMoisture");
Adafruit_MQTT_Publish Pressure = Adafruit_MQTT_Publish(&mqtt, AIO_USERNAME "/feeds/Pressure");
Adafruit_MQTT_Publish Humid = Adafruit_MQTT_Publish(&mqtt, AIO_USERNAME "/feeds/Humidity");
Adafruit_MQTT_Publish Temp = Adafruit_MQTT_Publish(&mqtt, AIO_USERNAME "/feeds/Temperature");
Adafruit_MQTT_Publish Air = Adafruit_MQTT_Publish(&mqtt, AIO_USERNAME "/feeds/AirQuality");
Adafruit_MQTT_Publish Dust = Adafruit_MQTT_Publish(&mqtt, AIO_USERNAME "/feeds/DustSensor");

//Variables
const int VALUE1 = 620;
const int VALUE2 = 310;
unsigned long lastMQTT;
unsigned long lastPub;
unsigned long dustTime;
unsigned long duration;
unsigned long waterTime;
unsigned long sampletime_ms = 30000;
unsigned long lowpulseoccupancy = 0;
int dustSensor = A0;
int soilSensor = A1;
int relay = A4;
int soilMoisturePercent; 
int soilMoistureValue; 
int current_quality =-1;
float dustSense;
float airSense;
float tempC;
float humidRH;
float pressPA;
float tempF;
float inHg;
float ratio = 0;
float concentration = 0;
bool buttonState;

SYSTEM_MODE(SEMI_AUTOMATIC);

// setup() runs once, when the device is first turned on.
void setup() 
{
  // Put initialization like pinMode and begin functions here.

  pinMode(soilSensor, INPUT);
  pinMode(dustSensor, INPUT);
  pinMode(relay, OUTPUT);

  Serial.begin(9600);
  bool status;
  status = bme.begin(0x76);
  sensor.init();
  dustTime = millis();
  delay(100); //wait for Serial Monitor to startup

  Serial.printf("Connecting to Internet \n");
  WiFi.connect();
  while(WiFi.connecting()) {
    Serial.printf(".");
    delay(100);
  }
  Serial.printf("\n Connected!!!!!! \n");
  // Setup MQTT subscription for onoff feed.
  mqtt.subscribe(&mqttSub1);

  display.begin(SSD1306_SWITCHCAPVCC, 0x3C);
  display.display();
  delay(2000);
  display.clearDisplay();
}

void loop()
 {

  current_quality=sensor.slope();
  if (current_quality >= 0)// if a valid data returned.
  {
      if (current_quality==0)
          Serial.println("High pollution! Force signal active");
      else if (current_quality==1)
          Serial.println("High pollution!");
      else if (current_quality==2)
          Serial.println("Low pollution!");
      else if (current_quality ==3)
          Serial.println("Fresh air");    
  }

  duration = pulseIn(dustSensor, LOW);
  lowpulseoccupancy = lowpulseoccupancy + duration;
  if ((millis()-dustTime) >= 30000){
    ratio = lowpulseoccupancy/(30000*10.0);
    concentration = 1.1*pow(ratio,3)-3.8*pow(ratio,2)+520*ratio+0.62;
    if(concentration > 1){
      dustSense = concentration;
    }
    Serial.printf("Concentration = %f pcs/0.01cf",dustSense);
    lowpulseoccupancy = 0;
    dustTime = millis();
  }
 

  // Ping MQTT Broker every 2 minutes to keep connection alive
  if ((millis()-lastMQTT)>120000) 
  {
      Serial.printf("Pinging MQTT \n");
      if(! mqtt.ping()) {
        Serial.printf("Disconnecting \n");
        mqtt.disconnect();
      }
      lastMQTT = millis();
  }

  // this is our 'wait for incoming subscription packets' busy subloop
 
  Adafruit_MQTT_Subscribe *subscription;
  while ((subscription = mqtt.readSubscription(1000)))
   {
    if (subscription == &mqttSub1) {
      buttonState = atoi((char *)mqttSub1.lastread);
      Serial.printf("buttonState is %i\n", buttonState);
    }   
  }

  if (buttonState == 1)
  {
      digitalWrite(relay,HIGH);
      Serial.printf("buttonState is on \n");
  }
    else
    {
      digitalWrite(relay,LOW);
      Serial.printf("buttonState is off \n");
    }

  if((millis()-lastPub > 30000)) 
  {
    if(mqtt.Update()) 
    {
      Moist.publish(soilMoisturePercent);
      Air.publish(airSense);
      Temp.publish(tempF);
      Humid.publish(humidRH);
      Dust.publish(dustSense);
      Pressure.publish(inHg);
 
    } 
    lastPub = millis();
  }
  soilMoistureValue = analogRead(soilSensor);
  Serial.printf("Soil moisture is %i\n", soilMoistureValue);
  soilMoisturePercent = map(soilMoistureValue, 1800, 3500, 100, 0);

  tempC = bme.readTemperature();
  tempF = map(tempC,0.0,100.0,32.0,212.0);
  pressPA = bme.readPressure();
  inHg = pressPA/3386.389;
  humidRH = bme.readHumidity();
  airSense = sensor.getValue();
  
  MQTT_connect();
  hydrate();
  OLEDDisplay();
  printValues();
}

// Function to connect and reconnect as necessary to the MQTT server.
// Should be called in the loop function and it will take care if connecting.
void MQTT_connect() 
{
  int8_t ret;
 
  // Stop if already connected.
  if (mqtt.connected()) {
    return;
  }
 
  Serial.print("Connecting to MQTT... ");
 
  while ((ret = mqtt.connect()) != 0) { // connect will return 0 for connected
       Serial.println(mqtt.connectErrorString(ret));
       Serial.println("Retrying MQTT connection in 5 seconds...");
       mqtt.disconnect();
       delay(5000);  // wait 5 seconds
  }
  Serial.println("MQTT Connected!");
}
void hydrate()
{
  if(soilMoisturePercent <= 45)
  {
    if((millis()-waterTime)>10000)
    {
      digitalWrite(relay,HIGH);
      delay(500);
      digitalWrite(relay,LOW);
      waterTime = millis();
    }
  }

}
void OLEDDisplay()
{      
    display.clearDisplay();
    display.setCursor(0,0);  //oled display
    display.setRotation(2);
    display.setTextSize(1);
    display.setTextColor(WHITE);
    display.printf("Temp: %0.2f\nHumidity: %0.2f\nDust %0.2f\nPressure: %0.2f\n", tempF, humidRH, dustSense, inHg);
    display.printf("Air: %i\nMoist: %i%%\n", airSense, soilMoisturePercent);
    display.display();
}
void printValues() 
{
    Serial.printf("Temperature = %f\n", tempF);
    Serial.print(bme.readTemperature());
    Serial.println(" *F");
    
    Serial.printf("Pressure = %f\n", inHg);
    Serial.print(bme.readPressure());
    Serial.println(" hPa");

 
    Serial.printf("Humidity = %f\n", humidRH);
    Serial.print(bme.readHumidity());
    Serial.println(" %");

    Serial.println();
}

The article was first published in hackster, April 22, 2021

cr: https://www.hackster.io/kareemcru/smart-house-plant-watering-system-384696

author: Kareem Crum

License
All Rights
Reserved
licensBg
0