Hackster is hosting Hackster Holidays, Ep. 5: Livestream & Giveaway Drawing. Watch previous episodes or stream live on Friday!Stream Hackster Holidays, Ep. 5 on Friday!
CK Cooper
Published © GPL3+

Smart Plant watering system

This smart watering system waters your plants when the soil is dry, monitors the room temp, humidity and more.

IntermediateShowcase (no instructions)20 hours415
Smart Plant watering system

Things used in this project

Hardware components

Photon
Particle Photon
×1
Gravity: I2C BME280 Environmental Sensor
DFRobot Gravity: I2C BME280 Environmental Sensor
×1
Grove - Dust Sensor(PPD42NS)
Seeed Studio Grove - Dust Sensor(PPD42NS)
×1
Grove - Air quality sensor v1.3
Seeed Studio Grove - Air quality sensor v1.3
×1
Graphic OLED, 128 x 64
Graphic OLED, 128 x 64
×1
Relay (generic)
×1
water Pump 5v
×1
Grove - Capacitive Moisture Sensor (Corrosion Resistant)
Seeed Studio Grove - Capacitive Moisture Sensor (Corrosion Resistant)
×1

Software apps and online services

Adafruit.io

Hand tools and fabrication machines

Wire Stripper & Cutter, 18-10 AWG / 0.75-4mm² Capacity Wires
Wire Stripper & Cutter, 18-10 AWG / 0.75-4mm² Capacity Wires

Story

Read more

Custom parts and enclosures

component box

Component Box

Flower Pot

3d printed flower pot

Base

Flower pot base to hold the flower pot out of the water

Schematics

Smart pot controller

Smart pot wiring schematic

Smart flower pot bread board

Code

Smart flower pot

C/C++
Smart flower pot waters soil when it gets too dry
 Project Smart flower pot
 * Author: CKCooper
 * Date: 11-6-2023
 * 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 "Adafruit_BME280.h"
#include "Adafruit_Sensor.h"
#include <Adafruit_MQTT.h>
#include "Adafruit_MQTT/Adafruit_MQTT_SPARK.h"
#include "Adafruit_MQTT/Adafruit_MQTT.h"
#include "Grove_Air_quality_Sensor.h"
#include "credentials.h"


#define OLED_RESET D4 //OLED 
#define XPOS 0;
#define YPOS 1;
String DateTime, TimeOnly;
// constants and variables for everything
const int PUMPPIN=D19;
int dustPin=D8;
int duration;
int startTime;
int sampleTime_ms=30000;
int lowPulseOccupancy=0;
int plantPin=A1;
int currentQuality=-1;
unsigned int last, lastTime;
float tempC;
float pressPa;
float humidRH;
float tempF;
float inHg;
float moisture;
float subValue,pubValue;
float ratio=0;
float concentration=0; 
bool status;

// classes
AirQualitySensor sensor(A0);
TCPClient TheClient; 
Adafruit_MQTT_SPARK mqtt(&TheClient,AIO_SERVER,AIO_SERVERPORT,AIO_USERNAME,AIO_KEY);
Adafruit_MQTT_Publish moistureFeed = Adafruit_MQTT_Publish(&mqtt, AIO_USERNAME "/feeds/plantmoisture");
Adafruit_MQTT_Publish tempFeed = Adafruit_MQTT_Publish(&mqtt, AIO_USERNAME "/feeds/roomtemp");
Adafruit_MQTT_Publish psFeed = Adafruit_MQTT_Publish(&mqtt, AIO_USERNAME "/feeds/pressure");
Adafruit_MQTT_Publish rhFeed = Adafruit_MQTT_Publish(&mqtt, AIO_USERNAME "/feeds/humidity");
Adafruit_MQTT_Publish aqFeed = Adafruit_MQTT_Publish(&mqtt, AIO_USERNAME "/feeds/air-quality");
Adafruit_MQTT_Publish dustFeed = Adafruit_MQTT_Publish(&mqtt, AIO_USERNAME "/feeds/dust-particulates");
Adafruit_MQTT_Subscribe buttonFeed = Adafruit_MQTT_Subscribe(&mqtt, AIO_USERNAME "/feeds/buttononoff"); 
Adafruit_SSD1306 display(OLED_RESET);//OLED display
Adafruit_BME280 bme;
//functions
void myAutoWater(int moisture, int PUMPPIN);

void MQTT_connect();
bool MQTT_ping();

SYSTEM_MODE(AUTOMATIC);

SYSTEM_THREAD(ENABLED);

// setup() runs once, when the device is first turned on
void setup() {//start serial monitor
Serial.begin(9600);
waitFor(Serial.isConnected, 15000);

WiFi.on();//start the wifi
WiFi.connect();
while(WiFi.connecting()) {
Serial.printf(".");
}
Serial.printf("\n\n");

status = bme.begin(0x76);//start BME sensor
  if(status==false){
        Serial.printf("BME at address 0x%02X failed to start", 0x76);
  }
pinMode(plantPin, INPUT);//all the pins
pinMode(dustPin, INPUT);
pinMode(PUMPPIN, OUTPUT);
digitalWrite (PUMPPIN, LOW);
startTime=millis();

Particle.syncTime();//time
Time.zone(-7);

display.begin(SSD1306_SWITCHCAPVCC, 0x3D);//start oled

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

// loop() runs over and over again, as quickly as it can execute.
void loop() {
 MQTT_connect();
 MQTT_ping();

  tempC=bme.readTemperature();//BME, date and time, moisture, sensor etc
  pressPa=bme.readPressure();
  humidRH=bme.readHumidity();
  DateTime=Time.timeStr();
  moisture=analogRead(plantPin);
  currentQuality=sensor.slope();
  duration = pulseIn(dustPin, LOW);
  tempF=map(tempC,0.0,100.0,32.0,212.0);//BME maps
  inHg=map(pressPa,3386.39,108000.00,1.0,38.40); 

  lowPulseOccupancy=lowPulseOccupancy+duration;

if((millis()-startTime)>sampleTime_ms){

  }
ratio=lowPulseOccupancy/(sampleTime_ms*10.0);
concentration=1.1*pow(ratio,3)-3.8*pow(ratio,2)+520*ratio+0.62;
Serial.printf("%0.2f LPO\n", lowPulseOccupancy);
Serial.printf("%0.2f ratio\n", ratio);
Serial.printf("%0.2f concentration\n", concentration);
startTime=millis();


if((millis()-lastTime > 60000)) {
    if(mqtt.Update()) {
      moistureFeed.publish(moisture);
      Serial.printf("Moisture %0.2f \n",moisture);
      tempFeed.publish(tempF);
      Serial.printf("Temp %0.2f \n",tempF); 
      psFeed.publish(inHg);
      Serial.printf("BP %0.2f \n",inHg);
      rhFeed.publish(humidRH);
      Serial.printf("Humidity %0.1 \n",humidRH);
      aqFeed.publish(currentQuality);
      Serial.printf("AQ %i \n",currentQuality);
      dustFeed.publish(concentration);
      Serial.printf("DP %0.2f \n",concentration);
      }
      lastTime = millis();
      } 
//OLED
display.setTextSize(1);
display.setTextColor(WHITE);
display.setCursor(0,0);
display.clearDisplay();
display.printf("TF %0.1f\n BP %0.1f\n HM %0.1f\n MS %0.1f\n AQ %i\n DP %0.1f\n", tempF, inHg, humidRH, moisture, currentQuality, concentration);
// display.setTextSize(1);
display.printf("Time %s\n",DateTime.c_str());
display.display();

myAutoWater(moisture, PUMPPIN);//water function call

Adafruit_MQTT_Subscribe *subscription;//adafruit subscription
while ((subscription = mqtt.readSubscription(10000))) {
   if (subscription == &buttonFeed) {
      subValue = atof((char *)buttonFeed.lastread);
      Serial.printf("Button Subscription %f \n", subValue);
  }

if(subValue==1){//adafruit water plant button
      digitalWrite(PUMPPIN,HIGH);
      delay(500);
      digitalWrite(PUMPPIN,LOW);
  }
  else{
      digitalWrite(PUMPPIN,LOW);
  }
}
}

// 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;
 
  // 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) {//this lets adafruit know we're still here
      Serial.printf("Pinging MQTT \n");
      pingStatus = mqtt.ping();
      if(!pingStatus) {
        Serial.printf("Disconnecting \n");
        mqtt.disconnect();
      }
      last = millis();
  }
  return pingStatus;
}
void myAutoWater(int moisture, int PUMPPIN){// water the plant if it is dry, check every half hour function
static unsigned int longTime;

 if ((millis()-longTime) >6000){
  if (moisture>2000){
    digitalWrite(PUMPPIN, HIGH);
    delay(500);
    digitalWrite(PUMPPIN, LOW);
    } 
    longTime = millis();
  }

 }

Credits

CK Cooper

CK Cooper

3 projects • 2 followers
I am a sculptor building smart technology into my work to make it more interactive and fun.

Comments