Staf Van Gestel
Published © GPL3+

Plant Assistant

You can check on your plant with your smartphone to determine if it has enough water, fertillizer, sunlight, and if the air quality is good.

AdvancedShowcase (no instructions)24 hours7,067
Plant Assistant

Things used in this project

Hardware components

Android device
Android device
×1
Arduino UNO
Arduino UNO
×1
IOTOPIA Rapid Development kit
AllThingsTalk IOTOPIA Rapid Development kit
×1
AllThingsTalk Environmental sensor pack
×1
PB8
×1
SSA 05320
Solid State Relais from celduc NO LONGER AVAILABLE
×4
Soil Moisture Meter
×1

Software apps and online services

Arduino IDE
Arduino IDE
AllThingsTalk Maker
AllThingsTalk Maker

Story

Read more

Schematics

Waterlevelmeter Shematic

this is the schematic for a waterlevelmeter we created to know if there is still enough water to give for the plant

Waterlevelmeter Board

This is the print we created here you can see wich components we used

Code

Arduino program

Arduino
Arduino program that controles all the sensors
#include <SoftwareSerial.h>
#include "ATT_IOT_FONA.h"
#include "ATT_MQTT.h"

#include "ATT_IOT_GPRS.h"
#include <SPI.h>

#define deviceId "x0Oq5Nf4rbnQZJC3YcWYzbJb"
#define clientId "vitronics_KJOcxvkQ"
#define clientKey "DGfg9VmT"

#define FONA_APN       "web.pro.be"
#define FONA_USERNAME  ""
#define FONA_PASSWORD  ""

#define FONA_RX 2
#define FONA_TX 3
#define FONA_RST 5
SoftwareSerial fonaSS = SoftwareSerial(FONA_TX, FONA_RX);

ATTDevice Device(deviceId, clientId, clientKey);
#define httpServer "api.AllThingsTalk.io"       
#define mqttServer httpServer

#include <Wire.h>
#include <SPI.h>
#include <Adafruit_Sensor.h>
#include <Adafruit_BME280.h>

#define BME_SCK 13
#define BME_MISO 12
#define BME_MOSI 11
#define BME_CS 10

#define SEALEVELPRESSURE_HPA (1013.25)

#define voltageFlipPin1 6
#define voltageFlipPin2 5
#define sensorPin 1

#include "Arduino.h"
#include "SI114X.h"


SI114X SI1145 = SI114X();

Adafruit_BME280 bme;
unsigned long newTime;
unsigned long oldTime;  
int pinTemp = 15;
int pinPRES = 16;
int pinHUM = 17;
int pinSL = 18;
int aiQ = 19;
int pinGVS = 0;
int avg = 0;

int flipTimer = 1000;

int niveauPin =8;
int niveau = 0;
float xniveau = 0;
const int pinNiveauSensor = A3;

int niveauPin2 =7;
int niveau2 = 0;
float xniveau2 = 0;
const int pinNiveauSensor2 = A2;
int motorPin = 9;
int motorPin2 = 10;
int motorPin3 = 11;
int lamp = 12;
int kaart = 13;
int B = 0;
int water;
int TSetMest;
int wacht;
int delayStuur;

void callback(const char* topic, const char* payload, unsigned int length);

void setup() {
  pinMode(niveauPin, OUTPUT);
  pinMode(niveauPin2, OUTPUT);
  pinMode(motorPin, OUTPUT);
  pinMode(motorPin2, OUTPUT);
  pinMode(motorPin3, OUTPUT);
  pinMode(lamp, OUTPUT);
  pinMode(kaart,OUTPUT);
  pinMode(voltageFlipPin1, OUTPUT);
  pinMode(voltageFlipPin2, OUTPUT);
  fonaSS.begin(19200);
  Serial.begin(57600);
  
  digitalWrite(motorPin, HIGH);
  digitalWrite(motorPin2, HIGH);
  digitalWrite(motorPin3, HIGH);
  digitalWrite(lamp, HIGH);
  while (!SI1145.Begin()) {
    delay(1000);
  }

  bool status;
    
    // default settings
    status = bme.begin();
    
  while(!Serial && millis() < 2000);                       // Make sure you see all output on the monitor. After 2 sec, it will skip this step, so that the board can also work without being connected to a pc  
  
    while (! Device.InitGPRS(fonaSS, FONA_RST, F(FONA_APN), F(FONA_USERNAME), F(FONA_PASSWORD))) {
        Serial.println("Retrying FONA");
    }
    Serial.println(F("Connected to Cellular!"));
    delay(2000);                                            // wait a few seconds to stabilize connection
  
    while(!Device.Connect(httpServer))                    // connect the device with the IOT platform.
        Serial.println("retrying");
    Device.AddAsset(pinTemp, "temperature", "rotary switch",false, "{\"type\": \"integer\", \"minimum\": -10.0, \"maximum\": 50.0}");     // data input to Allthingstalk app
    Device.AddAsset(pinPRES, "presure", "rotary switch",false, "{\"type\": \"integer\", \"minimum\": 0, \"maximum\": 1200}");
    Device.AddAsset(pinHUM, "vochtigheid", "rotary switch",false, "{\"type\": \"integer\", \"minimum\": 0, \"maximum\": 100}");
    Device.AddAsset(niveauPin, "niveau", "rotary switch",false, "{\"type\": \"integer\", \"minimum\": 0, \"maximum\": 100}");
    Device.AddAsset(niveauPin2, "niveau Mest", "rotary switch",false, "{\"type\": \"integer\", \"minimum\": 0, \"maximum\": 100}");
    Device.AddAsset(pinGVS, "GV", "rotary switch",false, "{\"type\": \"integer\", \"minimum\": 0, \"maximum\": 100}");
    Device.AddAsset(pinSL, "licht sensor", "rotary switch",false, "{\"type\": \"integer\", \"minimum\": 0, \"maximum\": 1000}");
    Device.AddAsset(aiQ, "lucht qualiteit", "rotary switch",false, "{\"type\": \"integer\", \"minimum\": 0, \"maximum\": 3}");
    Device.AddAsset(motorPin, "motor1", "light emitting diode", true, "boolean");
    Device.AddAsset(motorPin2, "motor2", "light emitting diode", true, "boolean");
    Device.AddAsset(motorPin3, "motor3", "light emitting diode", true, "boolean");
    Device.AddAsset(lamp, "lamp", "light emitting diode", true, "boolean");
    Device.AddAsset(kaart, "kaart", "light emitting diode", true, "boolean");
    while(!Device.Subscribe(callback, mqttServer, 1883))                          // make certain that we can receive message from the iot platform (activate mqtt)
        Serial.println("retrying");
}

void loop() {
  int x = bme.readTemperature();    // measure temperature from TPH meter
  Device.Send(String(x), pinTemp);
  delay(1000);

  int y = bme.readPressure() / 100.0F;   // measure pressure from TPH meter
  Device.Send(String(y), pinPRES);
  delay(1000);
  
  int z = bme.readHumidity();   // measure humidity from TPH meter
  Device.Send(String(z), pinHUM);
  delay(1000);

  digitalWrite(niveauPin, HIGH);        //  water level meter activates
  xniveau = analogRead(pinNiveauSensor);    // measure water level
  delay(5);
  
  digitalWrite(niveauPin, LOW);   //  water level meter deactivates
  
  xniveau = (xniveau*5.0)/1023.0;     // from analoge to value from 0-100
  if(xniveau<1.20){
    niveau = 0;
  }
  else if (xniveau<2.20){
    niveau = 10;
  }
  else if(xniveau<2.70){
    niveau = 25;
  }
   else if(xniveau<3.30){
    niveau = 50;
  }
  else if(xniveau<5){
    niveau = 100;
  }
  Device.Send(String(niveau),niveauPin);
  delay(1000);
  digitalWrite(niveauPin2, HIGH);   //  fertillizer level meter activates
  xniveau2 = analogRead(pinNiveauSensor2);  // measure fertillizer level
  delay(5);
  
  digitalWrite(niveauPin2, LOW);  //  fertillizer level meter deactivates
  
  xniveau2 = (xniveau2*5.0)/1023.0; // from analoge to value from 0-100
  if(xniveau2<1.40){
    niveau2 = 0;
  }
  else if(xniveau2<3.80){
    niveau2 = 50;
  }
  else if(xniveau2<5){
    niveau2 = 100;
  }
  Device.Send(String(niveau2),niveauPin2);
  delay(1000);
  setSensorPolarity(true);    // activated soil moisture sensor
  delay(flipTimer);
  
  int val1 = analogRead(sensorPin);   // measure of soil moisture
  delay(flipTimer);
   
  setSensorPolarity(false);   // switch polarity of the soil moisture sensor
  delay(flipTimer);
   
  // invert the reading
  int val2 = 1023 - analogRead(sensorPin);  // measure of soil moisture
  //
  reportLevels(val1,val2);    // compare 2 values
  Device.Send(String(avg),pinGVS);
  delay(1000);
  
  int B = SI1145.ReadVisible();   // sunlight measuring
  Device.Send(String(B),pinSL);
  delay(1000);
  
  Device.Process(); 
}

void setSensorPolarity(boolean flip){   // activate or switch polarity of the soil moisture sensor
  if(flip){
    digitalWrite(voltageFlipPin1, HIGH);
    digitalWrite(voltageFlipPin2, LOW);
  }else{
    digitalWrite(voltageFlipPin1, LOW);
    digitalWrite(voltageFlipPin2, HIGH);
  }
}

void reportLevels(int val1,int val2){   // compare 2 values
  
  avg = (val1 + val2) / 2;
  avg=map(avg,0,1000,0,100);
  
}

void callback(const char* topic, const char* payload, unsigned int length) 
{ 
  String msgString(payload);                              //convert to string object, so we can easily compare and modify the string.
  int* idOut = NULL;
  idOut = &motorPin;

  idOut = &motorPin2;

  idOut = &motorPin3;

  idOut = &lamp;

  idOut = &kaart;
  int pinNr = Device.GetPinNr(topic, strlen(topic));
    
  Serial.print("Payload: ");                            //show some debugging.
    Serial.println(msgString);
    Serial.print("topic: ");
    Serial.println(topic);
    Serial.print("pin: ");
    Serial.println(pinNr);
    
    if (pinNr == motorPin)                      //check for which asset we received an actuator so that we can perform the correct actuation.
    {
        msgString.toLowerCase();                            //to make certain that our comparison later on works ok (it could be that a 'True' or 'False' was sent)
        if (msgString == "false") {
            digitalWrite(motorPin, LOW);//change the led
            Device.Send(String("true"),motorPin);
            delay(1000);
            digitalWrite(motorPin, HIGH);
            digitalWrite(motorPin2, LOW);
            delay(20000);
            digitalWrite(motorPin2, HIGH);
            digitalWrite(motorPin3, LOW);
            delay(21000);
            digitalWrite(motorPin3, HIGH);   
            idOut = &motorPin;                                
        }
        else if (msgString == "true") {
            digitalWrite(motorPin, HIGH);
            idOut = &motorPin;
        }
    }

  if (pinNr == motorPin2)                      //check for which asset we received an actuator so that we can perform the correct actuation.
    {
        msgString.toLowerCase();                            //to make certain that our comparison later on works ok (it could be that a 'True' or 'False' was sent)
        if (msgString == "false") {
            digitalWrite(motorPin2, LOW);                      //change the led    
            idOut = &motorPin2;                                
        }
        else if (msgString == "true") {
            digitalWrite(motorPin2, HIGH);
            idOut = &motorPin2;
        }
    }
    if (pinNr == motorPin3)                      //check for which asset we received an actuator so that we can perform the correct actuation.
    {
        msgString.toLowerCase();                            //to make certain that our comparison later on works ok (it could be that a 'True' or 'False' was sent)
        if (msgString == "false") {
            digitalWrite(motorPin3, LOW);                      //change the led    
            idOut = &motorPin3;                                
        }
        else if (msgString == "true") {
            digitalWrite(motorPin3, HIGH);
            idOut = &motorPin3;
        }
    }

    if (pinNr == lamp)                      //check for which asset we received an actuator so that we can perform the correct actuation.
    {
        msgString.toLowerCase();                            //to make certain that our comparison later on works ok (it could be that a 'True' or 'False' was sent)
        if (msgString == "false") {
            digitalWrite(lamp, LOW);                      //change the led    
            idOut = &lamp;                                
        }
        else if (msgString == "true") {
            digitalWrite(lamp, HIGH);
            idOut = &lamp;
        }
    }

    if (pinNr == kaart)                      //check for which asset we received an actuator so that we can perform the correct actuation.
    {
        msgString.toLowerCase();                            //to make certain that our comparison later on works ok (it could be that a 'True' or 'False' was sent)
        if (msgString == "false") {
            digitalWrite(kaart, LOW);                      //change the led    
            idOut = &kaart;                                
        }
        else if (msgString == "true") {
            digitalWrite(kaart, HIGH);
            idOut = &kaart;
        }
    }

    
  if(idOut != NULL)                                       //also let the iot platform know that the operation was succesful: give it some feedback. This also allows the iot to update the GUI's correctly & run scenarios.
    Device.Send(msgString, *idOut);  
}

Credits

Staf Van Gestel

Staf Van Gestel

5 projects • 20 followers

Comments