Andrew Fukawa
Published

Home Automation: Plant Health Notifier

Updates soil status of connected plant every morning, and notifies whenever soil moisture falls below a threshold via a Discord webhook.

BeginnerShowcase (no instructions)3 hours118
Home Automation: Plant Health Notifier

Things used in this project

Hardware components

Photon 2
Particle Photon 2
×1
Breadboard (generic)
Breadboard (generic)
×1
Micro-USB to USB Cable (Generic)
Micro-USB to USB Cable (Generic)
×1
Jumper wires (generic)
Jumper wires (generic)
×1
Male/Female Jumper Wires
Male/Female Jumper Wires
×1
Tactile Switch, Top Actuated
Tactile Switch, Top Actuated
×1
Gravity: Analog Capacitive Soil Moisture Sensor- Corrosion Resistant
DFRobot Gravity: Analog Capacitive Soil Moisture Sensor- Corrosion Resistant
×1

Software apps and online services

Particle Build Web IDE
Particle Build Web IDE
Discord

Story

Read more

Schematics

screenshot_2025-11-09_11_58_28_pm_8SERGsEgww.png

Code

Home Automation: Plant Health Notifier

C#
At a set time every day, the user is notified of the status of their plant. Using the analog value retrieved by a soil moisture sensor that is inserted in the soil of a plant, my code maps gets the percent value (out of 100) of the moisture in the plants' soil. After that, it determines the status of the plant soil by assigning a status (Overwatered, Healthy, Needs water soon, and Needs water now) to the plant based on the percent moisture.

Additionally, when the moisture level drops below a healthy range, the user is automatically notified and is told to water their plant.

Finally, the final section of code allows me to send the notifier messages into discord with the press of a button, allowing me to test changes in my code without having to wait for the schedules sending times or for the moisture to dip below a threshold.
#include <stdio.h>

int analogPin = A5; // potentiometer connected to analog pin A5
int val = 0; // value
int button = 5; // button digital pin
int count = 0; // for button tracking
int color = 0;
String status;
bool warningSent = false;
bool secondWarningSent = false;

void setup()
{
    pinMode(button, INPUT_PULLUP);
    Serial.begin(9600);
    Time.zone(-6);
    delay(1000);
    
}

void loop()
{
    // tell time
    int hour = Time.hour();
    int minute = Time.minute();
    
    //get moisture reading
	val = analogRead(analogPin);
	val = map(val, 0, 4095, 0, 100);
	
	// determine status
	// if moisture is 50-100 its overwatered
	// if moisture is 30-49 it's healthy
	// if moisture is 20-39 it needs water soon
	// if moisture is 0-19 it is wilting
	if (val >= 50)
	{
	    status = "Overwatered";
	    color = 5191211;
	} else if ( val >= 30)
	{
	    status = "Healthy";
	    color = 4518529;
	} else if ( val >= 20)
	{
	    status = "Needs water soon";
	    color = 14603927;
	} else
	{
	    status = "Needs water now";
	    color = 9846591;
	}

    String tooLowData = String::format("{\"val\":\"%d\",\"status\":\"%s\",\"color\":%d}",val, status.c_str(), color);
    
    // sending if needs water soon
    if (val < 30 && val >= 20)
    {
        if (!warningSent){
            Particle.publish("tooLow", tooLowData, PRIVATE);
            warningSent = true;
        }
    } else if (val < 20)
    {
        if(!secondWarningSent){
            Particle.publish("tooLow", tooLowData, PRIVATE);
            secondWarningSent = true;
        }
    } else if (val >= 30)
    {
        warningSent = false;
        secondWarningSent = false;
    }
    
    String statusData = String::format("{\"val\":%d,\"status\":\"%s\",\"color\":%d}", val, status.c_str(), color);
    
    // status code
    if ((hour == 18 && minute == 3))
    {
        Particle.publish("statusUpdate", statusData, PRIVATE);
        delay(61000);
    }
    
    // Testing webhooks with button
  	int btnState = digitalRead(button);
	if ( btnState == LOW && count == 0)
	{
        Particle.publish("statusUpdate", statusData, PRIVATE);
        delay(1000);
        count++;
	} else if ( btnState == LOW && count == 1 )
	{
        Particle.publish("tooLow", tooLowData, PRIVATE);
        delay(1000);
        count--;
	}
}

JSON data for "tooLow" webhook

JSON
This JSON webhook template takes the data sent from my Particle code and replaces the placeholders for values such as moisture value, plant status, and embed color to create the structure of the message that sends into discord.
{
  "embeds": [
    {
      "title": "**⚠️ Moisture Threshold Triggered! 🌾**",
      "description": "Moisture Level: **{{val}}%**\nStatus: **{{status}}**",
      "color": {{color}},
      "footer": {
        "text": "Automatic Alert"
      },
      "timestamp": "{{PARTICLE_PUBLISHED_AT}}"
    }
  ]
}

JSON data for "statusUpdate" webhook

JSON
This JSON webhook template takes the data sent from my Particle code and replaces the placeholders for values such as moisture value, plant status, and embed color to create the structure of the message that sends into discord. Additionally, an image is added to the message that is sent.
{
  "embeds": [
    {
      "title": "**Daily Plant Health Status 🌞🌱**",
      "description": "Soil moisture: **{{val}}%**\nStatus: **{{status}}**",
      "color": {{color}},
      "image": {
        "url": "https://img.freepik.com/free-vector/plant-growing_78370-263.jpg"
      },
      "timestamp": "{{PARTICLE_PUBLISHED_AT}}"
    }
  ]
}

Credits

Andrew Fukawa
1 project • 0 followers

Comments