Randall Chavez
Published © MIT

How to keep your plants alive!!!!!!

When your plants need a drink, and you are not their Waterboy!!!!!

BeginnerProtip12 hours44
How to keep your plants alive!!!!!!

Things used in this project

Hardware components

Breadboard (generic)
Breadboard (generic)
×1
Photon
Particle Photon
This is how the program works in the IOT plant watering system. It sends a signal to the plants water pump to deploy water to the soil.
×1
OLED Expansion
Onion Corporation OLED Expansion
Sends information about soil conditions. And when it will receive water to plant.
×1
SparkFun Atmospheric Sensor Breakout - BME280
SparkFun Atmospheric Sensor Breakout - BME280
keeps tabs on humidity and other conditions to ensure that your plant is doing well.
×1
WunderBar
Relayr WunderBar
This is the brain of the plant watering system. It gets a signal from the photon 2 micorprocessor. And delivers the water to the plant.
×1
Grove - Capacitive Soil Moisture Sensor
Seeed Studio Grove - Capacitive Soil Moisture Sensor
This monitors the condition of the of the soil. When the soil is Dry, the relay then sends water to the plant. when the soil is moist, it tells the relay no need for water.
×1

Story

Read more

Custom parts and enclosures

Fritzing

To see how the wiring for the plant water system works.

Schematics

Schematics

To see how its wired.

Code

Code

C/C++
To show how the system works
 * Project L11_04_Seeedsensors
 * Author: Randall Chavez
 * Date: 03-15-2024 * For comprehensive documentation and examples, please visit:
 * https://docs.particle.io/firmware/best-practices/firmware-template/
 */

// Include Particle Device OS APIs
#include "Particle.h"
#include "Adafruit_GFX.h"
#include "Adafruit_SSD1306.h"
#include "Math.h"
#include <Adafruit_MQTT.h>
#include "Adafruit_MQTT/Adafruit_MQTT_SPARK.h"
#include "Adafruit_MQTT/Adafruit_MQTT.h"
#include "credentials.h"
#include "IoTTimer.h"


const int SOILSENSOR = A1;
int soilRead;
SYSTEM_THREAD(ENABLED);
IoTTimer MoistureTimer;
IoTTimer PumpTimer;


TCPClient TheClient; 
Adafruit_MQTT_SPARK mqtt(&TheClient,AIO_SERVER,AIO_SERVERPORT,AIO_USERNAME,AIO_KEY); 
Adafruit_MQTT_Subscribe subFeed = Adafruit_MQTT_Subscribe(&mqtt, AIO_USERNAME "/feeds/pumponoff"); 
//Adafruit_MQTT_Publish pubFeed = Adafruit_MQTT_Publish(&mqtt, AIO_USERNAME "/feeds/pumponoff");

bool subValue;


unsigned int lastTime;
int updateTime = 30000;
float concentration;
unsigned int lowPulseOccupancy;
const int DUSTPIN = D6;
const int PUMPPIN = D16;
float ratio;
Adafruit_SSD1306 display(-1);
 SYSTEM_THREAD ( ENABLED );  
void getConc ();
void MQTT_connect();
bool MQTT_ping();


 void setup () {
MoistureTimer.startTimer(15000);
 
 Serial . begin (9600) ;
 new Thread (" concThread ", getConc ); 
  Serial.printf("\n\n");
  display.begin(SSD1306_SWITCHCAPVCC, 0x3C); 
   display.display(); // show splashscreen
  delay(2000);
  
  

  

  display.setCursor(0,0);
  display.setTextSize(1);
  display.setTextColor(WHITE);
  display.clearDisplay();
  display.display();

  
  display.printf("Plants need water");
  display.display();
  display.clearDisplay();
  pinMode (DUSTPIN,INPUT);
  pinMode (PUMPPIN,OUTPUT);
  pinMode (SOILSENSOR,INPUT);
  //pinMode (SOILSENSOR,OUTPUT);
  mqtt.subscribe(&subFeed);
 


 
 }
 void loop() {
  MQTT_connect();
  MQTT_ping();





 if (( millis () - lastTime ) > updateTime ) {
 Serial . printf (" Time : %0.2f, CONC : %0.2f\n", millis () /1000.0 , concentration ) ;
 lastTime = millis () ;
 } 
 
   display.setCursor(0,0);
   display.printf("plants have water");
  display.display();
  display.clearDisplay();

  
if(MoistureTimer.isTimerReady()){
 soilRead = analogRead(SOILSENSOR);
Serial.printf("moisture %i\n",soilRead);
MoistureTimer.startTimer(15000);

if(soilRead > 2500) {
  digitalWrite(PUMPPIN,HIGH);
  PumpTimer.startTimer(750);
}

}
if(PumpTimer.isTimerReady()){
  digitalWrite(PUMPPIN,LOW);
}



Adafruit_MQTT_Subscribe *subscription;
  while ((subscription = mqtt.readSubscription(100))) {
    if (subscription == &subFeed) {
      subValue = atoi((char *)subFeed.lastread);
      Serial.printf("pumpstate %i\n" ,subValue );
    }
    if (subValue == 1) {
      digitalWrite(PUMPPIN, HIGH);
      }

    else {
       digitalWrite(PUMPPIN, LOW);  
    }
    }

    
  
 }
void getConc () {
  const int sampleTime = 30000;
 unsigned int duration , startTime ;
 startTime = 0;
 lowPulseOccupancy =0;
 while ( true ) { 
duration = pulseIn ( DUSTPIN , LOW );
 lowPulseOccupancy = lowPulseOccupancy + duration ;
 if (( millis () - startTime ) > sampleTime ) {
 ratio = lowPulseOccupancy /( sampleTime *10.0) ;
 concentration = 1.1* pow ( ratio ,3) -3.8* pow ( ratio ,2) +520* ratio +0.62;
 startTime = millis () ;
 lowPulseOccupancy =0;

 }
 }
}
void MQTT_connect() {
  int8_t ret;
 
  // Return if already connected.
  if (mqtt.connected()) {
    return;
  }
 
  Serial.print("Connecting to MQTT... ");
 
  while ((ret = mqtt.connect()) != 0) { // connect will return 0 for connected
       Serial.printf("Error Code %s\n",mqtt.connectErrorString(ret));
       Serial.printf("Retrying MQTT connection in 5 seconds...\n");
       mqtt.disconnect();
       delay(5000);  // wait 5 seconds and try again
  }
  Serial.printf("MQTT Connected!\n");

}
bool MQTT_ping() {
  static unsigned int last;
  bool pingStatus;

  if ((millis()-last)>120000) {
      Serial.printf("Pinging MQTT \n");
      pingStatus = mqtt.ping();
      if(!pingStatus) {
        Serial.printf("Disconnecting \n");
        mqtt.disconnect();
      }
      last = millis();
  }
  return pingStatus;

Code

C/C++
How the system works.
 * Project L11_04_Seeedsensors
 * Author: Randall Chavez
 * Date: 03-15-2024 * For comprehensive documentation and examples, please visit:
 * https://docs.particle.io/firmware/best-practices/firmware-template/
 */

// Include Particle Device OS APIs
#include "Particle.h"
#include "Adafruit_GFX.h"
#include "Adafruit_SSD1306.h"
#include "Math.h"
#include <Adafruit_MQTT.h>
#include "Adafruit_MQTT/Adafruit_MQTT_SPARK.h"
#include "Adafruit_MQTT/Adafruit_MQTT.h"
#include "credentials.h"
#include "IoTTimer.h"


const int SOILSENSOR = A1;
int soilRead;
SYSTEM_THREAD(ENABLED);
IoTTimer MoistureTimer;
IoTTimer PumpTimer;


TCPClient TheClient; 
Adafruit_MQTT_SPARK mqtt(&TheClient,AIO_SERVER,AIO_SERVERPORT,AIO_USERNAME,AIO_KEY); 
Adafruit_MQTT_Subscribe subFeed = Adafruit_MQTT_Subscribe(&mqtt, AIO_USERNAME "/feeds/pumponoff"); 
//Adafruit_MQTT_Publish pubFeed = Adafruit_MQTT_Publish(&mqtt, AIO_USERNAME "/feeds/pumponoff");

bool subValue;


unsigned int lastTime;
int updateTime = 30000;
float concentration;
unsigned int lowPulseOccupancy;
const int DUSTPIN = D6;
const int PUMPPIN = D16;
float ratio;
Adafruit_SSD1306 display(-1);
 SYSTEM_THREAD ( ENABLED );  
void getConc ();
void MQTT_connect();
bool MQTT_ping();


 void setup () {
MoistureTimer.startTimer(15000);
 
 Serial . begin (9600) ;
 new Thread (" concThread ", getConc ); 
  Serial.printf("\n\n");
  display.begin(SSD1306_SWITCHCAPVCC, 0x3C); 
   display.display(); // show splashscreen
  delay(2000);
  
  

  

  display.setCursor(0,0);
  display.setTextSize(1);
  display.setTextColor(WHITE);
  display.clearDisplay();
  display.display();

  
  display.printf("Plants need water");
  display.display();
  display.clearDisplay();
  pinMode (DUSTPIN,INPUT);
  pinMode (PUMPPIN,OUTPUT);
  pinMode (SOILSENSOR,INPUT);
  //pinMode (SOILSENSOR,OUTPUT);
  mqtt.subscribe(&subFeed);
 


 
 }
 void loop() {
  MQTT_connect();
  MQTT_ping();





 if (( millis () - lastTime ) > updateTime ) {
 Serial . printf (" Time : %0.2f, CONC : %0.2f\n", millis () /1000.0 , concentration ) ;
 lastTime = millis () ;
 } 
 
   display.setCursor(0,0);
   display.printf("plants have water");
  display.display();
  display.clearDisplay();

  
if(MoistureTimer.isTimerReady()){
 soilRead = analogRead(SOILSENSOR);
Serial.printf("moisture %i\n",soilRead);
MoistureTimer.startTimer(15000);

if(soilRead > 2500) {
  digitalWrite(PUMPPIN,HIGH);
  PumpTimer.startTimer(750);
}

}
if(PumpTimer.isTimerReady()){
  digitalWrite(PUMPPIN,LOW);
}



Adafruit_MQTT_Subscribe *subscription;
  while ((subscription = mqtt.readSubscription(100))) {
    if (subscription == &subFeed) {
      subValue = atoi((char *)subFeed.lastread);
      Serial.printf("pumpstate %i\n" ,subValue );
    }
    if (subValue == 1) {
      digitalWrite(PUMPPIN, HIGH);
      }

    else {
       digitalWrite(PUMPPIN, LOW);  
    }
    }

    
  
 }
void getConc () {
  const int sampleTime = 30000;
 unsigned int duration , startTime ;
 startTime = 0;
 lowPulseOccupancy =0;
 while ( true ) { 
duration = pulseIn ( DUSTPIN , LOW );
 lowPulseOccupancy = lowPulseOccupancy + duration ;
 if (( millis () - startTime ) > sampleTime ) {
 ratio = lowPulseOccupancy /( sampleTime *10.0) ;
 concentration = 1.1* pow ( ratio ,3) -3.8* pow ( ratio ,2) +520* ratio +0.62;
 startTime = millis () ;
 lowPulseOccupancy =0;

 }
 }
}
void MQTT_connect() {
  int8_t ret;
 
  // Return if already connected.
  if (mqtt.connected()) {
    return;
  }
 
  Serial.print("Connecting to MQTT... ");
 
  while ((ret = mqtt.connect()) != 0) { // connect will return 0 for connected
       Serial.printf("Error Code %s\n",mqtt.connectErrorString(ret));
       Serial.printf("Retrying MQTT connection in 5 seconds...\n");
       mqtt.disconnect();
       delay(5000);  // wait 5 seconds and try again
  }
  Serial.printf("MQTT Connected!\n");

}
bool MQTT_ping() {
  static unsigned int last;
  bool pingStatus;

  if ((millis()-last)>120000) {
      Serial.printf("Pinging MQTT \n");
      pingStatus = mqtt.ping();
      if(!pingStatus) {
        Serial.printf("Disconnecting \n");
        mqtt.disconnect();
      }
      last = millis();
  }
  return pingStatus;

Credits

Randall Chavez

Randall Chavez

3 projects • 3 followers

Comments