CJA3D
Published © CC BY

Plant Monitoring System using AWS IoT

If you plan on a vacation, here is a great project to track the temperature and soil moisture of your Plant using dweet.io and AWS IoT.

IntermediateFull instructions provided48,170

Things used in this project

Hardware components

Arduino Yun
Arduino Yun
×1
Grove starter kit plus for Intel Edison
Seeed Studio Grove starter kit plus for Intel Edison
Using the Shield and Temperature and Light Sensor from the Kit
×1
Seeed Studio Grove - Moisture Sensor
×1
5 mm LED: Red
5 mm LED: Red
×1
Resistor 330 ohm
Resistor 330 ohm
×1

Software apps and online services

AWS IoT
Amazon Web Services AWS IoT
AWS IAM
Amazon Web Services AWS IAM
AWS DynamoDB
Amazon Web Services AWS DynamoDB
AWS SNS
Amazon Web Services AWS SNS
dweet.io
Arduino IDE
Arduino IDE

Hand tools and fabrication machines

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

Story

Read more

Custom parts and enclosures

STL file for the Base of the Yun

STl file for Pot Soil Poker

STL file for the Top Arduino Yun+Grove shield

Schematics

Circuit

Connect the sensors to the Grove starter kit that is
- Temperature sensor to A0
- Soil Moisture sensor to A1
- Light sensor to A2

In addition, using a 220 Ohms resistor connect an LED to pin#2.

Circuit

Connect the
Temperature sensor to A0
Soil Moisture sensor to A1
Light sensor to A2
And using a 220 Ohms resistor connect an LED to pin#2

Code

SoilMoistureValue

Arduino
Arduino sketch to determine the ideal Soil moisture value for your house plant
//@CarmelitoA -House Plant Monitoring project determining soil moisture value
const int moisturePin = A1; // Grove Moisture sensor connected to A1 on the Grove Shield
const int ledPin = 2;
int moisturValue = 0;
int tooDryValue = 250;//change this value based on what you come up with
void setup() {
Serial.begin(9600);
pinMode(ledPin,OUTPUT);
digitalWrite(ledPin,LOW);
}
void loop() {
moisturValue = analogRead(moisturePin);
Serial.print("Moisture sensor = " );
Serial.println(moisturValue); //Check the Value for with Dry sand and then with Wet Sand
if(moisturValue < tooDryValue)
{
digitalWrite(ledPin,HIGH);
} else{
digitalWrite(ledPin,LOW);
}
delay(3000);
}

ArduinoYunDweetio

Arduino
Posting Sensor data to dweet.io using Arduino Yun
//Created by @CarmelitoA for the House Plant Monitoring project - uploading data to dweet.io. (CC BY-SA https://creativecommons.org/licenses/by-sa/4.0/)

#include <Bridge.h>
#include <YunClient.h>

#define SITE_URL "www.dweet.io"
#include <math.h> //Added for temperature calculations

const int moisturePin = A1;    // Grove Moisture sensor connected to A1 on the Grove Shield
const int ledPin = 2; //LED indicator
int moisturValue = 0;  // variable to store the value coming from the sensor
const int tooDryValue = 500; //CHANGE this value based on you testing of how much moisture the soil should have, less then this value will turn the LED ON which means you need to water the plant
float tooLowTemp =20; //CHANGE ,temperature in degree C based on the type of your house plant, if the temperature is Lower than the value the LED will turn Red

//Temperature Sensor defs
const int B=4275;                 // B value of the thermistor
const int R0 = 100000;            // R0 = 100k
const int pinTempSensor = A0;     // Grove - Temperature Sensor connect to A5

//Light Sensor
const int lightPin = A2; 


unsigned long lastConnectionTime = 0; 
const unsigned long postingInterval = 10L * 1000L;

void setup()
{
  Bridge.begin();
  Serial.begin(9600);
  pinMode(ledPin,OUTPUT);
  digitalWrite(ledPin,LOW); 
  Serial.begin(9600);
  while (!Serial); // wait for a serial connection- disable this after deployment
}

void loop()
{
  
YunClient c;
if (millis() - lastConnectionTime > postingInterval) { 
  
  moisturValue = analogRead(moisturePin);              
  Serial.print("sensor = " );                       
  Serial.println(moisturValue); //Check the Value for with Dry sand and then with Wet Sand             
  
  //Calculating the Temperature in degress C
  int a = analogRead(pinTempSensor);
  float R = 1023.0/((float)a)-1.0;
  R = 100000.0*R;
  float temperature=1.0/(log(R/100000.0)/B+1/298.15)-273.15;//convert to temperature via datasheet ;
  Serial.print("temperature = ");
  Serial.println(temperature);
  
  //calculating Light value
  int lightValue = analogRead(lightPin); 
  Serial.print("light value = ");
  Serial.println(lightValue);

  //turning on the LED if the sensor value is than tooDryValue or tooLowTemp
  if(moisturValue < tooDryValue || temperature < tooLowTemp )
  {
    digitalWrite(ledPin,HIGH);
  }else
  {
    digitalWrite(ledPin,LOW);
  }
    
  // checking if we are conneted to dweet.io
  if(c.connect(SITE_URL, 80))
    {
       Serial.println("connected");
        // Make a HTTP request:
        String s = "POST /dweet/for/PlantMonitorTorontoON?Temperature="; //CHANGE the location of you plant to keep it unique on dweet.io
        s.concat(temperature);
        s.concat("&LightValue=");
        s.concat(lightValue);
        s.concat("&SoilMoisture=");
        s.concat(moisturValue);
        Serial.println(s);
        c.println(s);
        
        c.println("Host: www.dweet.io");
        c.println("Connection: close");
        c.println();
        lastConnectionTime = millis();  
      }
      else{
        Serial.println("disconnected from server");
      }

  }
  
}

ArduinoYunAWSIoTDynamodb

Arduino
sketch to post sensor data to AWS -DynamoDB , you will also need to add the aws_iot_config.h as a new tab in the Arduino IDE.
//Created by @CarmelitoA 01-16-2016 for the House Plant Monitoring project.Feel free to remix and modify

#include <aws_iot_mqtt.h>
#include <aws_iot_version.h>
#include "aws_iot_config.h"
#include <ArduinoJson.h>
char data[80];
StaticJsonBuffer<200> jsonBuffer;

//#define SITE_URL "www.dweet.io" //combining the YunClient.h with this example to post to dweet causing confilicts, refer to ArduinoYunDweetio.ino
#include <math.h> //Added for temperature calculations


const int moisturePin = A1;    // Grove Moisture sensor connected to A1 on the Grove Shield
const int ledPin = 2;
int moisturValue = 0;  // variable to store the value coming from the sensor
const int tooDryValue = 250; //CHANGE this value based on you testing of how much moisture the soil should have, less then this value will turn the LED ON which means you need to water the plant
float tooLowTemp =20; //CHANGE ,temperature in degree C based on the type of your house plant, if the temperature is Lower than the value the LED will turn Red

//Temperature Sensor defs
const int B=4275;                 // B value of the thermistor
const int R0 = 100000;            // R0 = 100k
const int pinTempSensor = A0;     // Grove - Temperature Sensor connect to A5

//Light Sensor
const int lightPin = A2; 

unsigned long lastConnectionTime = 0; 
const unsigned long postingInterval = 10L * 1000L; //change this value to increase the posting interval

aws_iot_mqtt_client myClient; // init iot_mqtt_client
char msg[32]; // read-write buffer
int cnt = 0; // loop counts
int rc = -100; // return value placeholder
bool success_connect = false; // whether it is connected

// Basic callback function that prints out the message
void msg_callback(char* src, int len) {
  Serial.println("CALLBACK:");
  int i;
  for(i = 0; i < len; i++) {
    Serial.print(src[i]);
  }
  Serial.println("");
}


void setup()
{
  //CJA Bridge.begin();
  pinMode(ledPin,OUTPUT);
  digitalWrite(ledPin,LOW); 
  Serial.begin(115200);
  while (!Serial); // wait for a serial connection//Comment this out once your are ready to deploy

 char curr_version[80];
  sprintf(curr_version, "AWS IoT SDK Version(dev) %d.%d.%d-%s\n", VERSION_MAJOR, VERSION_MINOR, VERSION_PATCH, VERSION_TAG);
  Serial.println(curr_version);
  // check you connection info as part of the setup - this is based on the BasicPubSub example at https://github.com/aws/aws-iot-device-sdk-arduino-yun
  if((rc = myClient.setup(AWS_IOT_CLIENT_ID)) == 0) {
    // Load user configuration
    if((rc = myClient.config(AWS_IOT_MQTT_HOST, AWS_IOT_MQTT_PORT, AWS_IOT_ROOT_CA_PATH, AWS_IOT_PRIVATE_KEY_PATH, AWS_IOT_CERTIFICATE_PATH)) == 0) {
      // Use default connect: 60 sec for keepalive
      if((rc = myClient.connect()) == 0) {
        success_connect = true;
        // Subscribe to "topic1" //we are not subscribing to any message as part of our Plant moniotring setup, 
        //but you could use this in a loop below if you were to build a feedback mechanism to water the plant with a pump
       /* if((rc = myClient.subscribe("topic1", 1, msg_callback)) != 0) {
          Serial.println("Subscribe failed!");
          Serial.println(rc);
        }*/
      }
      else {
        Serial.println("Connect failed!");
        Serial.println(rc);
      }
    }
    else {
      Serial.println("Config failed!");
      Serial.println(rc);
    }
  }
  else {
    Serial.println("Setup failed!");
    Serial.println(rc);
  }
  // Delay to make sure SUBACK is received, delay time could vary according to the server
  delay(2000);

}

void loop()
{  
  moisturValue = analogRead(moisturePin);              
  Serial.print("sensor = " );                       
  Serial.println(moisturValue); //Check the Value for with Dry sand and then with Wet Sand             
  
  //Calculating the Temperature in degress C
  int a = analogRead(pinTempSensor);
  float R = 1023.0/((float)a)-1.0;
  R = 100000.0*R;
  float temperature=1.0/(log(R/100000.0)/B+1/298.15)-273.15;//convert to temperature based on datasheet ;
  Serial.print("temperature = ");
  Serial.println(temperature);
  
  //calculating Light value
  int lightValue = analogRead(lightPin); 
  Serial.print("light value = ");
  Serial.println(lightValue);

  //turning on the LED if the sensor value is than tooDryValue or tooLowTemp
  if(moisturValue < tooDryValue || temperature < tooLowTemp )
  {
    digitalWrite(ledPin,HIGH);
  }else
  {
    digitalWrite(ledPin,LOW);
  }
 //Creating the JSON payload  
 String temp = "\"temp\": " + String(temperature) ;
 String light = ", \"lightval\":" + String(lightValue) ;
 String soilMoist = ", \"moistval\":" + String(moisturValue) ;
 // Add both value together to send as one string. 
 String value = temp + light +soilMoist;
 Serial.println(value);
 String payload = "{" + value + "}";
 payload.toCharArray(data, (payload.length() + 1));
  
  
 //Publish data to AWS IoT using  topic/plantdata,which in turn will fire the AWS IoT rule to write sensor data to Dynamo DB
 if(success_connect) {
    // Generate a new message in each loop and publish to "topic/plantdata" 

    if((rc = myClient.publish("topic/plantdata", data, strlen(data), 1, false)) != 0) {
      Serial.println("Publish failed!");
      Serial.println(rc);
    }
  
    // Get a chance to run a callback
    if((rc = myClient.yield()) != 0) {
      Serial.println("Yield failed!");
      Serial.println(rc);
    }
  
    // Done with the current loop
    sprintf(msg, "publish %d done", cnt++);
    Serial.println(msg);
  
    delay(10000);
  }

 // }//end if checking for time interval to post 
  delay(5000);
}

aws_iot_config.h

Arduino
Add as a new tab in the Arduino IDE
/*
 * Copyright 2010-2015 Amazon.com, Inc. or its affiliates. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License").
 * You may not use this file except in compliance with the License.
 * A copy of the License is located at
 *
 *  http://aws.amazon.com/apache2.0
 *
 * or in the "license" file accompanying this file. This file is distributed
 * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
 * express or implied. See the License for the specific language governing
 * permissions and limitations under the License.
 */
//@carmelitoA modified the value for the plant monitoring project

#ifndef config_usr_h
#define config_usr_h

// Copy and paste your configuration into this file
//===============================================================
#define AWS_IOT_MQTT_HOST "XXXXXXXXXXX.iot.us-west-2.amazonaws.com"   // your endpoint
#define AWS_IOT_MQTT_PORT 8883                  // your port
#define AWS_IOT_CLIENT_ID "clientYun2"            // your client ID
#define AWS_IOT_MY_THING_NAME "PlantSystem"           // your thing name
#define AWS_IOT_ROOT_CA_FILENAME "rootCA.pem"           // your root-CA filename
#define AWS_IOT_CERTIFICATE_FILENAME "cert.pem"                 // your certificate filename
#define AWS_IOT_PRIVATE_KEY_FILENAME "privateKey.pem"              // your private key filename
//===============================================================
// SDK config, DO NOT modify it
#define AWS_IOT_PATH_PREFIX "./certs/"
#define AWS_IOT_ROOT_CA_PATH AWS_IOT_PATH_PREFIX AWS_IOT_ROOT_CA_FILENAME     // use this in config call
#define AWS_IOT_CERTIFICATE_PATH AWS_IOT_PATH_PREFIX AWS_IOT_CERTIFICATE_FILENAME // use this in config call
#define AWS_IOT_PRIVATE_KEY_PATH AWS_IOT_PATH_PREFIX AWS_IOT_PRIVATE_KEY_FILENAME // use this in config call

#endif

Credits

CJA3D

CJA3D

10 projects • 80 followers
Tinkerer and 3D Printing enthusiast.

Comments