$USD
  • EUR€
  • £GBP
  • $USD
PROJECTS ArduinoGravityIoT

IoT Plant Moisture Notifier

DFRobot Aug 28 2017 1541

Get a text or call if your plant is getting too dry, along with a nice LCD display giving information regarding your plant's health.



Build Log:


Introduction

The wonderful people at DFRobot reached out to me to do a project using their amazing soil moisture sensor and I2C 16x2 LCD.

I had an idea to create a device that would monitor a plant, and they provided me with the necessary hardware. I decided to build a simple box that is powered by a single Particle Photon.

Every 30 minutes it takes a reading of the soil and determines if it's too dry. If it is, it publishes an event, and then IFTTT can send a text, call, or email to notify you that it's too dry. There is also an RGB LED on top that turns green if the plant is happy, and blinks blue if the plant is too dry.


The 16x2 LCD displays a message from the plant, ranging from being very happy to feeling extremely sad.

Components

Hardware Components:

Particle Photon
Soil Moisture Sensor For Arduino
I2C 16x2 Arduino LCD Display Module
RGB Diffused Common Cathode
Micro USB Connector
Uxcell Perf Board 4x6cm


Software apps and online services:
Particle Cloud IDE
FTTT Maker service

Hand tools and fabrication machines:
Soldering iron (generic)
Millright CNC Router M3


Design

To begin building it, I started by connecting each component to the Particle Photon, along with the micro usb power connector. I loaded up some test code that simply displays the moisture level on the LCD. After the code ran successfully, I began to create a Fusion 360 design. The shape of the device is designed to be a rectangular prism, with the LCD facing out, the LED on top, and the micro USB port in the back.

I also made a hole that allows for the soil moisture sensor's cabling to attach. For the painting portion, I wanted there to be a green base coat with some floral designs on it in yellow.

Creating the Parts

My Fusion 360 design was created to be CNC routed, so I laid out all of the parts evenly on a flat surface and generated gcode from the machining paths. Next, I put my material, a sheet of 10.5" x 10.5" x 1/4" plywood on my Millright CNC machine and began cutting out each part. I also sanded down each piece and gave the edges a good rounding to create a better aesthetic.

Making it Pretty

I first collected my materials: the CNC routed pieces of plywood, a can of green spray paint, a can of shellac, a little bottle of yellow acrylic paint, some 150- 400 grit sandpaper, a bottle of wood glue, and a sander.

I started by thoroughly sanding each part, gradually using increasingly finer grit sandpaper.

After I felt the sanding was sufficient, I glued the bottom, side, and back pieces together. Next, I sprayed each part with two coats of shellac, and then applied several even coats of green spray paint.

Assembly

Now that all of the parts were painted, I added the electronic components into the enclosure, fastening them down with hot glue. I also strung the wires for the soil sensor through the hole in the side and connected it to the Photon.

I added a little compartment in which to store the sensor and wires when not in use.

Programming

I went to the Particle Photon Cloud IDE and loaded up the attached sketch, flashing it to my Photon. The RGB LED on top blinked 5 times to notify me that it was powered and connected successfully. The code is set up such that when the moisture dips below 15% the Photon sends an event called "water", which then triggers an IFTTT applet.

Usage

To use it, I simply put the moisture sensor into the soil of my potted plant, and plugged a micro USB cable into the connector, giving the device 5v. Next, I setup an IFTTT applet to text me whenever it receives the event named "dry" from the Particle Photon service.


It sends an email with the message: "Your plant needs water!". In addition, the LCD on the device displays the percentage of soil moisture along with a message from the plant, from very happy to very sad. Now, you never have to worry about whether or not your plant needs water.


Schematic


CODE

//DFRobot.com
//Compatible with the Arduino IDE 1.0
//Library version:1.1


#include <Wire.h>
#include <LiquidCrystal_I2C.h>

#define BLUE_PIN A3
#define GREEN_PIN A4
#define SOIL_SENSOR A1

//#define RESOLUTION 1024 //Use for 10 bit resolution ADC (Arduino)
#define RESOLUTION 4096 //Use for 12 bit resolution ADC (Particle Photon)

#define DEBUG_VALS //Comment if you don't want values published to the Particle Cloud

LiquidCrystal_I2C lcd(0x20,16,2);  // set the LCD address to 0x20(Cooperate with 3 short circuit caps) for a 16 chars and 2 line display
int level;

/*byte one_bar[8] = {
    B00000,
    B00000,
    B00000,
    B00000,
    B00000,
    B00000,
    B00000,
    B11111
};

byte two_bar[8] = {
    B00000,
    B00000,
    B00000,
    B00000,
    B00000,
    B00000,
    B11111,
    B11111
};

byte three_bar[8] = {
    B00000,
    B00000,
    B00000,
    B00000,
    B00000,
    B11111,
    B11111,
    B11111
};

byte four_bar[8] = {
    B00000,
    B00000,
    B00000,
    B00000,
    B11111,
    B11111,
    B11111,
    B11111
};

byte five_bar[8] = {
    B00000,
    B00000,
    B00000,
    B11111,
    B11111,
    B11111,
    B11111,
    B11111
};

byte six_bar[8] = {
    B00000,
    B00000,
    B11111,
    B11111,
    B11111,
    B11111,
    B11111,
    B11111,
};

byte seven_bar[8] = {
    B00000,
    B11111,
    B11111,
    B11111,
    B11111,
    B11111,
    B11111,
    B11111
};

byte eight_bar[8] = {
    B11111,
    B11111,
    B11111,
    B11111,
    B11111,
    B11111,
    B11111,
    B11111
}; */

bool is_spam = false;
    
void debug_values(int raw_value){
    Particle.publish("soil_values_raw", String(raw_value));
}

void setup(){
  
   /*lcd.createChar(0, one_bar);
   lcd.createChar(1, two_bar);
   lcd.createChar(2, three_bar);
   lcd.createChar(3, four_bar);
   lcd.createChar(4, five_bar);
   lcd.createChar(5, six_bar);
   lcd.createChar(6, seven_bar);
   lcd.createChar(7, eight_bar);*/
  
  pinMode(BLUE_PIN, OUTPUT);
  pinMode(GREEN_PIN, OUTPUT);
  pinMode(SOIL_SENSOR, INPUT);
  lcd.init();                      // initialize the lcd 
  lcd.backlight();
  
  lcd_clear();
  
  lcd.setCursor(0, 0);
  lcd.print("Plant hydration");
  lcd.setCursor(0, 1);
  lcd.print("monitor");
  delay(4000);
}
  
void loop(){
  
  int reading2 = take_reading();
  
  float reading = reading2;
  
  lcd.print("Water level:");
  lcd.setCursor(0,1);
  lcd.print(reading);
  delay(1000);
  
  #ifdef DEBUG_VALS
  debug_values(reading);
  #endif
  
  Particle.publish("level", String(reading));
  
  if(reading >= .95*RESOLUTION){
      lcd_clear();
      lcd.print("Did you water");
      lcd.setCursor(0,1);
      lcd.print("too much?");
      level = 16;
  }
  else if(reading >= .85*RESOLUTION){
      lcd_clear();
      lcd.print("That's plenty");
      level = 14;
  }
  else if(reading >= .78*RESOLUTION){
      lcd_clear();
      lcd.print("Thanks for all");
      lcd.setCursor(0,1);
      lcd.print("of that water");
      level = 13;
  }
  else if(reading >= .70*RESOLUTION){
      lcd_clear();
      lcd.print("Woah, that's");
      lcd.setCursor(0,1);
      lcd.print("a good drink");
      level = 12;
  }
  else if(reading >= .65*RESOLUTION){
      lcd_clear();
      lcd.print("That makes me");
      lcd.setCursor(0,1);
      lcd.print("very happy");
      level = 11;
  }
  else if(reading >= .60*RESOLUTION){
      lcd_clear();
      lcd.print("I love you");
      lcd.setCursor(0,1);
      lcd.print("more now");
      level = 10;
  }
  else if(reading >= .55*RESOLUTION){
      lcd_clear();
      lcd.print("Meh, almost");
      lcd.setCursor(0,1);
      lcd.print("time for more");
      level = 9;
  }
  else if(reading >= .50*RESOLUTION){
      lcd_clear();
      lcd.print("Did you water");
      lcd.setCursor(0,1);
      lcd.print("too much?");
      level = 8;
  }
  else if(reading >= .45*RESOLUTION){
      lcd_clear();
      lcd.print("Still pretty");
      lcd.setCursor(0,1);
      lcd.print("content");
      level = 7;
  }
  else if(reading >= .40*RESOLUTION){
      lcd_clear();
      lcd.print("Get ready for");
      lcd.setCursor(0,1);
      lcd.print("some watering!");
      level = 6;
  }
  else if(reading >= .35*RESOLUTION){
      lcd_clear();
      lcd.print("I'm still");
      lcd.setCursor(0,1);
      lcd.print("waiting");
      level = 5;
  }
  else if(reading >= .30*RESOLUTION){
      lcd_clear();
      lcd.print("OK, water me");
      lcd.setCursor(0,1);
      lcd.print("I'm very thirsty");
      level = 4;
  }
  else if(reading >= .22*RESOLUTION){
      lcd_clear();
      lcd.print("Still no water?");
      lcd.setCursor(0,1);
      lcd.print("You're mean");
      level = 3;
  }
  else if(reading >= .15*RESOLUTION){
      lcd_clear();
      lcd.print("Water please");
      lcd.setCursor(0,1);
      lcd.print("it's dry here!");
      level = 2;
  }
  else if(reading >= .08*RESOLUTION){
      lcd_clear();
      lcd.print("I'm about");
      lcd.setCursor(0,1);
      lcd.print("to die");
      level = 1;
  }
  else if(reading >= .04*RESOLUTION){
      lcd_clear();
      lcd.print("Blahhh :(");
      lcd.setCursor(0,1);
      lcd.print("you killed me");
      level = 0;
  }
  delay(3000);
  eval_level();
  delay(4000);
  lcd_clear();
  no_green();
  
}

void eval_level(){
    if(level>8){
        solid_green();
    }
    else if(level<8 && level != 0){
        blink_blue(8, 250);
        if(is_spam==false){
        Particle.publish("dry", "True");
        }
        is_spam = true;
    }
    else if(level==8){
        blink_blue(3, 250);
    }
    else if(level==0){
        blink_blue(10, 250);
    }
}

int take_reading(){
    lcd_clear();
    lcd.print("Taking reading");
    int amount = analogRead(SOIL_SENSOR);
    delay(1000);
    lcd_clear();
    return amount;
}

void blink_blue(int number_of_loops, int duration){
    for(int i=0; i< number_of_loops; i++){
        digitalWrite(BLUE_PIN, 1);
        delay(duration);
        digitalWrite(BLUE_PIN, 0);
        delay(duration);
    }
}

void solid_green(){
    digitalWrite(GREEN_PIN, 1);
}

void no_green(){
    digitalWrite(GREEN_PIN, 0);
}

void lcd_clear(){
    lcd.clear();
    lcd.setCursor(0,0);
}

This Project is made by Arduino “having11” Guy, the original project is here.

More Particle Photon Projects:

REVIEW