Jack DoganieriJacob Brooks
Published

Automatic Snake Plant Watering Device

Have you ever forgotten to water your plant which resulted in a tragic death? Now you won't worry with this new watering device!

IntermediateFull instructions provided597
Automatic Snake Plant Watering Device

Things used in this project

Hardware components

Snake Plant
Watering device can be accommodated to any preferred plant.
×1
Argon
Particle Argon
×1
Breadboard (generic)
Breadboard (generic)
×1
Jumper wires (generic)
Jumper wires (generic)
×13
SparkFun Breadboard Power Supply 5V/3.3V
SparkFun Breadboard Power Supply 5V/3.3V
×1
9VDC 400mA Power Adapter
×1
Resistive Soil Moisture Board and Probe
×1
3.3VDCRelay Board
×1
5VDC Water Pump
×1
Water tank (watertight cereal container)
×1
M5x35mm Screws
×3
M5 Locknuts
×3
5mm Washers
×6

Software apps and online services

Particle Build Web IDE
Particle Build Web IDE

Hand tools and fabrication machines

3D Printer (generic)
3D Printer (generic)

Story

Read more

Custom parts and enclosures

Pot Dish (STL)

You need to print 1 of these

Tube Holder (STL)

You need to print 1 of these

Thick Arm Segment (STL)

You need to print 2 of these

Narrow Arm Segment (STL)

You need to print 3 of these

Schematics

Schematic

This is a wiring diagram for the main watering device. The sattelite only needs power and does not require additional wiring.

Code

Plant Watering Device - Main

C/C++
This is the main Particle Argon code for the watering device. It essentially checks the moisture level four times per month and waters at a set time if the level is below a certain threshold.
//  -------------------------
// |  Plant Watering Device  | 
// |    for Particle Argon   |
//  -------------------------
// |    MEGR 3171 Group 27   |
// |       Jacob Brooks      |
// |      Jack Doganiari     |
//  -------------------------
// |  Code by: Jacob Brooks  |
//  -------------------------

// Pin Assignments:
// - D6: Output: Pump relay
// - D7: Output: LED
// - A1: Input: Moisture Sensor 

// Function prototypes
void waterPlant(int amount);   // Function for watering plant
double checkMoisture();   // Function for checking moisture sensor

// Handler for Subscribe function
int finds;  // Variable to hold the count of recieved reciept reciepts
void myHandler(const char *event, const char *data)
{
    for (int i=1; i<51; i++) // Repeat 50 times
    {
        digitalWrite(D7,HIGH); // Turn LED on 
        delay (100);  // Wait 100 ms
        digitalWrite(D7,LOW);  // Turn LED off
        delay (100);  // Wait 100 ms
    }
    finds ++;  // Increase recieved count by 1
    Particle.publish("return_recieved_reciept");  // Publish reciept of singal recieved
}


// Declare constants
const int water_ml = 100;   // How much water (in ml) the pump dispenses
const int moistureThreshold = 42;   // Moisture percent trigger threshold
const int wateringDay1 = 1;   // Day of the month when the pump turns on
const int wateringDay2 = 6;   // Second day of the month when the pump turns on
const int wateringDay3 = 15;   // 3rd ...
const int wateringDay4 = 22;   // 4th ... 
const int wateringHour = 12+1;   // Hour at which the pump turns on (24 hour format)
const int wateringMinute = 0;   // Minute at which if statements trigger
const int timeZoneOffset = -5;   // Time zone offset from Greenwich, England (Eastern Standard Time, USA)
const int delayPeriod = 60000;   // How long the argon delays after each main loop (milliseconds)

// Declare other variables
int date;   // Date variable
int hour;   // Hour variable
int minute;   // Minute variable
int second;   // Second variable
double moisture_percent;   // Variable for moisture percent
int lastWaterDate;   // Variable for last watering date

// Debug toggles
bool displayDateTime = false;   // Publishes date and time each loop cycle
bool debugHour = false;   // Causes every hour to be the watering hour
bool debugMinute = false;   // Causes every minute to be the watering/moisture checking minute
bool debugDate = false;   // Causes the watering day to be every day
bool debugMoisture = false; // Causes the moisture level threshold to trigger

void setup() 
{
    // Set up time zone 
    Time.zone(timeZoneOffset);
    
    // Set up inputs and outputs
    pinMode(D6,OUTPUT);   // Output for pump relay
    pinMode(D7,OUTPUT);   // Output for LED
    pinMode(A1,INPUT);   // Input for soil moisture sensor
    
    // Set up particle variables
    Particle.variable("moisture_percent",moisture_percent);
    Particle.variable("lastWaterDate",lastWaterDate);
    Particle.variable("finds",finds);
    
    // Set up particle Subscribe
    Particle.subscribe("recieved_reciept",myHandler);
    
}

// Main loop
void loop() 
{
    // Check date and time
    date = Time.day(); 
    hour = Time.hour(); 
    minute = Time.minute(); 
    second = Time.second(); 
    
    // Display date and time for debug if toggle is active
    if (displayDateTime == true)
    {
        Particle.publish("date",String(date));
        Particle.publish("hour",String(hour));
        Particle.publish("minute",String(minute));
        Particle.publish("second",String(second));
    }
    
    // Check to see if it is time to check moisture / time to water
    if (minute == wateringMinute || debugMinute == true)
    {
        // Check moisture level
        moisture_percent = checkMoisture();
        
        // Publish moisture percent
        Particle.publish("moisture_percent",String(moisture_percent));
        
        // Check to see if moisture is below threshold
        if (moisture_percent < moistureThreshold || debugMoisture == true)
        {
            // Check to see if it is the correct hour...
            if (hour == wateringHour || debugHour == true)
            {
                // Check to see if it is on the correct day
                if (date == wateringDay1 || date == wateringDay2 || date == wateringDay3 || date == wateringDay4 || debugDate == true)
                {
                    // Publish water notification
                    Particle.publish("Watering (mL)",String(water_ml));
                    
                    // Water plant
                    waterPlant(water_ml);
                    
                    // Update last watering date variable
                    lastWaterDate = date;
                }
            }
        }
    }
    
    // Delay before next cycle
    delay(delayPeriod);
}

// Function for watering plant
void waterPlant(int amount)
{
    // Turn on pump
    digitalWrite(D6,HIGH);
    
    // Convert ml to pump on time milliseconds, delay for that length of time
    float pumpTime = 41.248*amount+446.05;   // Function to convert ml out to pump on time
    int pumpTimeInt = pumpTime;  // Convert float to int
    delay (pumpTimeInt);
    
    // Turn pump off
    digitalWrite(D6, LOW);
}

// Function for checking moisture sensor
double checkMoisture()
{
    // Define function variables: moisturePercent=m*sensor+b
    double m = -0.0220088035; double b = 89.90596235;
    
    // Read analog input and convert raw data to moisture percent
    double moisturePercent = m*analogRead(A1)+b;  // Function to convert raw sensor data to moisture percent
    return moisturePercent;
}

Plant Watering Device - Sattelite

C/C++
This is the code for the sattelite Particle Argon board. It essentially waits for a signal from the main board, blinks five times, and returns a confirmation signal to the main board through the cloud.
//  -------------------------
// |  Plant Watering Device  | 
// |       (Sattelite)       |
// |    for Particle Argon   |
//  -------------------------
// |    MEGR 3171 Group 27   |
// |       Jacob Brooks      |
// |      Jack Doganiari     |
//  -------------------------

// Pin assignment:
// - D7 - Output - LED

// Variables
int finds;  // Variable to hold number of times signal recieved

// Handler for Subscribe Function
void myHandler(const char *event, const char *data)
{
    for (int i=1; i<51; i++) // Repeat 50 times
    {
        digitalWrite(D7,HIGH); // Turn LED on 
        delay (100);  // Wait 100 ms
        digitalWrite(D7,LOW);  // Turn LED off
        delay (100);  // Wait 100 ms
    }
    finds ++;  // Increase recieved count by 1
    Particle.publish("recieved_reciept");  // Publish reciept of singal recieved
}

void setup() 
{
    // Set up output
    pinMode(D7, OUTPUT);
    
    // Set up particle variable
    Particle.variable("finds",finds);
    
    // Set up subscribe function 
    Particle.subscribe("Watering (mL)",myHandler);
}

void loop() 
{
    // Nothing here for now... only waiting for Subscribe
}

Credits

Jack Doganieri

Jack Doganieri

1 project • 1 follower
Mechanical Engineering Student Attending The University of North Carolina at Charlotte
Jacob Brooks

Jacob Brooks

0 projects • 1 follower
I am a maker, musician, mechanical engineering student, commercial HVAC technician, welder, woodworker, artist, and an avid pizza enthusiast

Comments