Jacob SantschiErik AldanaSalman Nizam
Published © LGPL

MEGR 3171: Automatic Houseplant Monitor

A monitor that will monitor the soil moisture and light exposure of a houseplant, and the fullness of a water supply.

IntermediateFull instructions provided4 hours251
MEGR 3171: Automatic Houseplant Monitor

Things used in this project

Hardware components

Argon
Particle Argon
×3
BH1750 Light Intensity Sensor
×1
SparkFun Soil Moisture Sensor (with Screw Terminals)
SparkFun Soil Moisture Sensor (with Screw Terminals)
×1
Jumper wires (generic)
Jumper wires (generic)
×12
Breadboard (generic)
Breadboard (generic)
×3

Software apps and online services

Particle Build Web IDE
Particle Build Web IDE
Maker service
IFTTT Maker service
ThingSpeak API
ThingSpeak API

Story

Read more

Schematics

Soil moisture sensor and micro servo motor

Light Sensor Module

With the Argon connected to power via a USB cable, this module will periodically measure the ambient light around the plant.

Water Storage Sensor Circuit Diagram

The argon input and output is connected to the water to sense its presence in a storage tank.

Code

Light Sensor Module

C/C++
This module will track light exposure over any period of time, while also confirming the measurement functions of another module.
// This #include statement was automatically added by the Particle IDE.
#include <BH1750.h>

BH1750 sensor(0x23, Wire);

double brightnessdata = 0; //creates a variable that can be made into a particle variable

bool inthelight = false; //sets up a simple check whether the sensor is in bright light

int Ledlight = D7; //sets up the argon's LED to blink

void setup() {
  sensor.begin();

  sensor.set_sensor_mode(BH1750::forced_mode_high_res2); //configures the sensor

  Serial.begin();
  
  Particle.variable("Brightness", brightnessdata);
  
  Particle.subscribe("moist", moist, MY_DEVICES); //listens for another argon's measurements
}

void moist(const char*event, const char*data) //blinks the led when the other argon takes a measurement
{
    digitalWrite(Ledlight, HIGH);
        delay(1000);
        digitalWrite(Ledlight, LOW);
        delay(1000);
        digitalWrite(Ledlight, HIGH);
        delay(1000);
        digitalWrite(Ledlight, LOW);
        
}

void loop() {
  sensor.make_forced_measurement(); //takes a brightness measurement

  Serial.println(String::format("%f", sensor.get_light_level()));

  brightnessdata = sensor.get_light_level();

  String lightdata = String(brightnessdata);
  
  Particle.publish("light", lightdata, PRIVATE); //publishes an event with the brightness data
  
  if (brightnessdata > 2000) {
  inthelight = true;
  }
  else {
  inthelight = false;
  };
  
  Particle.publish("inthelight", String(inthelight), PRIVATE); //publishes an event saying if the sensor is in bright light

  delay(300000); //waits 5 minutes between measurements
}

Water Storage Sensor

C/C++
This module passes a voltage through the D6 pin and reads an input through the A2 pin. When there water present at the given level, the voltage received by the A2 will vary significantly than otherwise and this is used to blink an led and relay the message to other Argons in the network.
int led1 = A2; 
int led2 = D7;
int led3 = D6;
int val = 0;

void setup() {
  pinMode(led1, INPUT); //reads the voltage coming from the storage
  pinMode(led2, OUTPUT); //builtin led to show response
  pinMode(led3, OUTPUT); //output voltage to the storage
  digitalWrite(led3, HIGH); //start sending voltage
}

void loop() {
  val = analogRead(led1);
  if (val > 3900) digitalWrite(led2, HIGH); //when theres water led on
  if (val < 3900) digitalWrite(led2, LOW); //no water, led turns off
  if (val < 3900) Particle.publish("no water", PRIVATE); //signals other                                                   //argons when theres no water
  delay(13000); //waits 13 seconds 
}

Soil Moisture Sensor And Micro Servo Motor

C/C++
This module will allow The soil moisture sensor to send data to the user and call functions to get an instant measurement or to activate movement of the micro servo motor. Communication between Argon devices is also possible
#define MOIST_CHECK_INTERVAL 3600000  ////take a reading each hour
int moist = 0;//variable to store soil value
unsigned long lastMoistCheck = 0;
int soil = A2;//Declare a variable for the soil moisture sensor 
int soilPower = D6;//Variable for Soil moisture Power
//Rather than powering the sensor through the V-USB or 3.3V pins, 
//we'll use a digital pin to power the sensor. This will 
//prevent oxidation of the sensor as it sits in the corrosive soil. 
int Ledlight = D7;  ///variable for pin D7
char waternow = 'waternow';
Servo myservo;
int pos = 0; ////initial position of servo motor
int pos2=340; /// final position of servo motor

void servo()
{       //////if a function for the servo is called, the motor will move to final position, then it will wait 4 seconds and return to initial position
        if ( servread() == waternow)
    {
        myservo.write(pos2);
        delay(4000);
        myservo.write(pos);
    }
}

void checkMoist()
{
     if(readSoil() < 1000)    ///An event will be published if the sensor reads a value below 1000
    {
      Particle.publish("moist", String(moist), PRIVATE); 
    }
    else
    {                                ///An event will be published if the sensor reads a value above 1000
     Particle.publish("moist", String(moist), PRIVATE);
    }
}


void setup()
{
    Particle.subscribe("no water", waterlevel, MY_DEVICES);  ///subscribe to argon with water level sensor
    
    Particle.subscribe("light", Light, MY_DEVICES);            ////Subscribe to argon with light sensor
    
    Particle.function("servo", ser);   ///function used to activate the servo motor
    myservo.attach(D8);  ////attached motor to pin D8
    myservo.write(pos);//// when Argon is powered, servo motor will be in the initial position
    checkMoist(); /// contains conditioning info to publish events
    Particle.function("checkMoist", checkHandler); /// function used to call in a reading from the sensor
    Particle.variable("moistValue", moist);  /// variable holding the most recent reading
    pinMode(Ledlight, OUTPUT); ////Set d7 as an OUTPUT
pinMode(soilPower, OUTPUT);//Set D6 as an OUTPUT
digitalWrite(soilPower, LOW);//Set to LOW so no power is flowing through the sensor
}

void loop () 
{
    if(lastMoistCheck + MOIST_CHECK_INTERVAL < millis())
    {
      lastMoistCheck = millis();
      checkMoist();
    }
}


void Light(const char*event, const char*data)   ///// when the Light sensor takes a reading, the argon will blink one time
{
    
    digitalWrite(Ledlight, HIGH);
        delay(500);
        digitalWrite(Ledlight, LOW);
}

void waterlevel(const char*event, const char*data)  ////when the water level sensor detects no water, the argon will blink 3 times rapidly
{
         digitalWrite(Ledlight, HIGH);
        delay(200);
        digitalWrite(Ledlight, LOW);
        delay(200);
        digitalWrite(Ledlight, HIGH);
        delay(200);
        digitalWrite(Ledlight, LOW);
        delay(200);
        digitalWrite(Ledlight, HIGH);
        delay(200);
        digitalWrite(Ledlight, LOW);
}

//This is a function used to get the soil moisture content
int readSoil()
{
    digitalWrite(soilPower, HIGH);//turn D6 "On"
    delay(10);//wait 10 milliseconds 
    moist = analogRead(soil);
    digitalWrite(soilPower, LOW);//turn D6 "Off"
    return moist;
}

int checkHandler(String command)
{
    checkMoist();
    return 1;
}


int servread()
{
    return waternow;
}



int ser(String command)
{
    servo();
    return 1;
}

Credits

Jacob Santschi

Jacob Santschi

1 project • 2 followers
Erik Aldana

Erik Aldana

1 project • 2 followers
Salman Nizam

Salman Nizam

1 project • 2 followers

Comments

Add projectSign up / Login