S Christian Chavez
Published © GPL3+

Smart Plant Watering System

An internet connected plant watering system that monitors environmental conditions and manages soil moisture.

IntermediateShowcase (no instructions)Over 1 day499
Smart Plant Watering System

Things used in this project

Hardware components

Argon
Particle Argon
×1
Resistor 2.21k ohm
Resistor 2.21k ohm
×1
Resistor 220 ohm
Resistor 220 ohm
×1
Humidity and Temperature Sensor
Adafruit Humidity and Temperature Sensor
×1
0.96" OLED 64x128 Display Module
ElectroPeak 0.96" OLED 64x128 Display Module
×1
Gravity: Analog Capacitive Soil Moisture Sensor- Corrosion Resistant
DFRobot Gravity: Analog Capacitive Soil Moisture Sensor- Corrosion Resistant
×1
Submersible Water Pump
×1
Grove - Air quality sensor v1.3
Seeed Grove - Air quality sensor v1.3
×1
Grove - Dust Sensor(PPD42NS)
Seeed Grove - Dust Sensor(PPD42NS)
×1
Relay Module
×1
General Purpose Transistor NPN
General Purpose Transistor NPN
×1

Software apps and online services

Fusion 360
Autodesk Fusion 360
Visual Studio 2015
Microsoft Visual Studio 2015

Hand tools and fabrication machines

Laser cutter (generic)
Laser cutter (generic)
Formlabs SLA 3D Printer

Story

Read more

Custom parts and enclosures

Flower Pot Stand

Flower Pot

Schematics

Fritzing Schematic

Breadboard Layout

Code

Smart Plant Watering System Code

C/C++
/*
 * Project L14_04_PlantWater
 * Description: Smart Plant Watering System
 * Author: Christian Chavez
 * Date: 11-09-2020
 */


#include <Adafruit_MQTT.h>

#include "Adafruit_MQTT/Adafruit_MQTT.h" 
#include "Adafruit_MQTT/Adafruit_MQTT_SPARK.h" 
#include "Adafruit_MQTT/Adafruit_MQTT.h" 

#include "credentials.h"

#include <Adafruit_BME280.h>
#include <Adafruit_SSD1306.h>

#include "Air_Quality_Sensor.h"

#define OLED_RESET D4

Adafruit_SSD1306 display(OLED_RESET);

Adafruit_BME280 bme;

AirQualitySensor sensor(A4);

TCPClient TheClient; 
 
Adafruit_MQTT_SPARK mqtt(&TheClient,AIO_SERVER,AIO_SERVERPORT,AIO_USERNAME,AIO_KEY); 

Adafruit_MQTT_Subscribe buttonState = Adafruit_MQTT_Subscribe(&mqtt, AIO_USERNAME "/feeds/buttonOnOff"); 
Adafruit_MQTT_Publish soilRead = Adafruit_MQTT_Publish(&mqtt, AIO_USERNAME "/feeds/Soil Moisture"); 
Adafruit_MQTT_Publish tempRead = Adafruit_MQTT_Publish(&mqtt, AIO_USERNAME "/feeds/Temperature Reading");
Adafruit_MQTT_Publish pressureRead = Adafruit_MQTT_Publish(&mqtt, AIO_USERNAME "/feeds/Pressure Reading");
Adafruit_MQTT_Publish humidityRead = Adafruit_MQTT_Publish(&mqtt, AIO_USERNAME "/feeds/Humidity Reading");
Adafruit_MQTT_Publish airRead = Adafruit_MQTT_Publish(&mqtt, AIO_USERNAME "/feeds/Air Quality Reading");
Adafruit_MQTT_Publish dustRead = Adafruit_MQTT_Publish(&mqtt, AIO_USERNAME "/feeds/Dust Reading");

float temp;
float pressure;
float humidity;
unsigned long last;
unsigned long lastTime;
unsigned long pumpLastTime;
unsigned long dustStartTime;
unsigned long duration;
int capRead; //stores capacitive soil sensor reading
int value; //stores value subcribed from adafruit.io
int airQuality; //stores value from Air Quality Sensor
int slopeQuality;
char dangerReading;
int dust;
float lowPulseOccupancy;

float concentration = 0;
float realConcentration;
float ratio;

const int ledPin = D7; //pin to turn on Particle led 
const int soilPin = A1; 
const int dustPin = A3;
const int airPin = A4;
const int pumpPin = A5;

void setup() {
  Serial.begin(9600);
  display.begin(SSD1306_SWITCHCAPVCC, 0x3C);
  display.display();
  delay(2000);

  bme.begin(0x76);

  if (sensor.init()) {
      Serial.printf("Sensor ready.");
  } else {
      Serial.printf("Sensor ERROR!");
  }  

  mqtt.subscribe(&buttonState);

  pinMode(soilPin, INPUT);
  pinMode(pumpPin, OUTPUT);
  pinMode(ledPin, OUTPUT);
  pinMode(airPin, INPUT);
  pinMode(dustPin, INPUT);

  dustStartTime = millis();
}

void loop() {

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

  int slopeQuality = sensor.slope();
  if (slopeQuality == AirQualitySensor::FORCE_SIGNAL) {
  Serial.println("High pollution! Force signal active.");
  }
  else if (slopeQuality == AirQualitySensor::HIGH_POLLUTION) {
    Serial.println("High pollution!");
  }
  else if (slopeQuality == AirQualitySensor::LOW_POLLUTION) {
    Serial.println("Low pollution!");
  }
  else if (slopeQuality == AirQualitySensor::FRESH_AIR) {
    Serial.println("Fresh air.");
  }

  display.clearDisplay();
  display.setRotation(2);
  display.setTextSize(1);
  display.setTextColor(WHITE);
  display.setCursor(0,0);
  temp = ((bme.readTemperature()*9/5)+32);
  pressure = ((bme.readPressure()/100)*0.03);
  humidity = bme.readHumidity();
  airQuality = sensor.getValue();

  display.printf("Soil: %i\nTemp: %.2f%c\nPressure: %.2f\nHumidity: %.2f%c\nAir Quality: %i\nDust: %.2f\n",capRead,temp,(char)247,pressure,humidity,(char)37,airQuality,realConcentration);
  display.display();

  MQTT_connect();

  if ((millis()-last)>5000) {
      Serial.printf("Pinging MQTT \n");
      if(! mqtt.ping()) {
        Serial.printf("Disconnecting \n");
        mqtt.disconnect();
      }
      last = millis();
  }
 
  Adafruit_MQTT_Subscribe *subscription;
  while ((subscription = mqtt.readSubscription(10000))) {
    if (subscription == &buttonState) {
      value = atof((char *)buttonState.lastread);
      if(value == 1){
      digitalWrite(ledPin, HIGH);
      digitalWrite(pumpPin, HIGH);
      }
      else{
      digitalWrite(ledPin, LOW);
      digitalWrite(pumpPin, LOW);
      }
    }
  }

  if((millis()-lastTime > 30000)) {
    if(mqtt.Update()) {
      analogWrite(pumpPin, HIGH);
      capRead = analogRead(soilPin);
      soilRead.publish(capRead);
      tempRead.publish(temp);
      pressureRead.publish(pressure);
      humidityRead.publish(humidity);
      airRead.publish(airQuality);
      dustRead.publish(concentration);
      Serial.printf("Soil Read: %i Temp: %f Pressure: %f Humidity %f Air Quality: %i Dust: %f\n",capRead,temp,pressure,humidity, airQuality, concentration); 
      } 
    lastTime = millis();
  }

  if((millis()-pumpLastTime > 60000)) { //automatic plant watering 
    if(capRead > 1600){
    digitalWrite(pumpPin, HIGH);
    digitalWrite(ledPin, HIGH);
    Serial.printf("Watering plant\n");
    delay(1000);
    digitalWrite(pumpPin, LOW);
    digitalWrite(ledPin, LOW);
    Serial.printf("Stop Watering plant\n");
    }
    pumpLastTime = millis();
  }

}

void MQTT_connect() {
  int8_t ret;
 
  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!");
}

Credits

S Christian Chavez

S Christian Chavez

3 projects • 4 followers
Internet of Things Coding and Hardware Design Student

Comments