Components Required: MediaTek Linkit One, Soil Moisture sensor, Servo motor, GPS Module, Temperature and Humidity sensor, Capacitor, Resistors, LEDs.
Tool required: MediaTek Cloud Sandbox
ABOUT THE PROJECT:
Smart Irrigation module is a prototype system based on MediaTek Linkit. The Soil Moisture sensor senses the the moisture level in the soil, and sends this information to the controller board (MediaTek Linkit One). Based on the level, the servo motor rotates by certain angle which ensures sufficient moisture in the soil. Each Reading is displayed and updated in the cloud. A switch is also provided to override the motor, Temperature and Humidity sensor is interfaced in order to maintain proper moisture level based on the climatic conditions. GPS module is interfaced in order get the coordinates of the location where the unit is placed. This concept can be used when we use multiple units at different locations in a Farm.
Soil Moisture Sensor:This sensor monitors the soil moisture level continuously. It sends this moisture data to the MediaTek Linkit for further processing.
Servo MotorBased on the moisture level the servo motor rotates from 0 degree to 180 degree. It is programmed in such a way that, if the soil has 100 % moisture then the motor will be Off (i.e. 0 degree). If the moisture level ranges anywhere between 75% - 99% then the motor shaft rotates to 36 degrees. If the moisture level ranges in between 50% - 74% then the motor shaft rotates to 72 degrees. If the moisture level ranges anywhere between 25% - 49% then the motor shaft rotates to 108 degrees. If the soil moisture level is in between 1% - 24% then the motor shaft rotates to 144 degrees. If the moisture level is 0% then the motor shaft rotates 180 degrees (ON).
It is possible to override these ranges, a switch is provided in the MediaTek cloud Sandbox, using which irrespective of the moisture level the motor can be switched ON or switched OFF.
MediaTek Linkit OneIt is the heart of the system where all the processing is done.
Temperature and Humidity Sensor:It gives the Temperature and Humidity level at a particular unit.
GPS Module:Pin Connections
Linkit Code
C/C++/*
* SMART IRRIGATION
*
* MediaTek Linkit based soil moisture monitoring and irrigation
*
* Version 1.1 February, 2016
* Developed by Green Robot Machinery Pvt. Ltd., Bangalore.
*
*/
//headers for interfacing modules
#include <LGPS.h> // for GPS module
#include <DHT.h> // for Temperature and Humidity sensor
#include <HttpClient.h>
#include <LTask.h>
#include <LWiFi.h>
#include <LWiFiClient.h>
#include<Servo.h>
#include <SPI.h>
#include <LDateTime.h>
//WiFi configuration
#define WIFI_AP "grobomac-wifi"
#define WIFI_PASSWORD "grobomac"
#define WIFI_AUTH LWIFI_WPA
#define per 50
#define per1 3
#define DEVICEID "DJ6nvDvr" // Input your deviceId
#define DEVICEKEY "yz5SP0WksLWM76aD" // Input your deviceKey
#define SITE_URL "api.mediatek.com"
#define DHTPIN 2 // ‘Temperature and humidity’ sensor to pin2
#define DHTTYPE DHT22
DHT dht(DHTPIN,DHTTYPE);
gpsSentenceInfoStruct info; // getting GPS coordinates
char buff[256];
int servoPin = 9; //the servo motor is connected to pin9
Servo servo;
int angle = 0; //servo angle
String dataToUpload;
LWiFiClient c;
unsigned int rtc;
unsigned int lrtc;
unsigned int rtc1;
unsigned int lrtc1;
char port[4]={0};
char connection_info[21]={0};
char ip[21]={0};
int portnum;
int val = 0;
String tcpdata = String(DEVICEID) + "," + String(DEVICEKEY) + ",0";
String upload_led;
String tcpcmd_led_on = "LED_Control,1";
String tcpcmd_led_off = "LED_Control,0";
String upload_weather;
String upload_GPS;
LWiFiClient c2;
HttpClient http(c2);
// initialise variables for GPS coordinates
double latitude;
double longitude;
double altitude=0.0;
// functions to run the GPS modules
static unsigned char getComma(unsigned char num,const char *str)
{
unsigned char i,j = 0;
int len=strlen(str);
for(i = 0;i < len;i ++)
{
if(str[i] == ',')
j++;
if(j == num)
return i + 1;
}
return 0;
}
static double getDoubleNumber(const char *s)
{
char buf[10];
unsigned char i;
double rev;
i=getComma(1, s);
i = i - 1;
strncpy(buf, s, i);
buf[i] = 0;
rev=atof(buf);
return rev;
}
static double getIntNumber(const char *s)
{
char buf[10];
unsigned char i;
double rev;
i=getComma(1, s);
i = i - 1;
strncpy(buf, s, i);
buf[i] = 0;
rev=atoi(buf);
return rev;
}
void parseGPGGA(const char* GPGGAstr)
{
/* Refer to http://www.gpsinformation.org/dale/nmea.htm#GGA
* Sample data: $GPGGA,123519,4807.038,N,01131.000,E,1,08,0.9,545.4,M,46.9,M,,*47
* Where:
* GGA Global Positioning System Fix Data
* 123519 Fix taken at 12:35:19 UTC
* 4807.038,N Latitude 48 deg 07.038' N
* 01131.000,E Longitude 11 deg 31.000' E
* 1 Fix quality: 0 = invalid
* 1 = GPS fix (SPS)
* 2 = DGPS fix
* 3 = PPS fix
* 4 = Real Time Kinematic
* 5 = Float RTK
* 6 = estimated (dead reckoning) (2.3 feature)
* 7 = Manual input mode
* 8 = Simulation mode
* 08 Number of satellites being tracked
* 0.9 Horizontal dilution of position
* 545.4,M Altitude, Meters, above mean sea level
* 46.9,M Height of geoid (mean sea level) above WGS84
* ellipsoid
* (empty field) time in seconds since last DGPS update
* (empty field) DGPS station ID number
* *47 the checksum data, always begins with *
*/
int tmp, hour, minute, second, num ;
if(GPGGAstr[0] == '$')
{
tmp = getComma(1, GPGGAstr);
hour = (GPGGAstr[tmp + 0] - '0') * 10 + (GPGGAstr[tmp + 1] - '0');
minute = (GPGGAstr[tmp + 2] - '0') * 10 + (GPGGAstr[tmp + 3] - '0');
second = (GPGGAstr[tmp + 4] - '0') * 10 + (GPGGAstr[tmp + 5] - '0');
sprintf(buff, "UTC timer %2d-%2d-%2d", hour, minute, second);
Serial.println(buff);
tmp = getComma(2, GPGGAstr);
latitude = getDoubleNumber(&GPGGAstr[tmp]);
tmp = getComma(4, GPGGAstr);
longitude = getDoubleNumber(&GPGGAstr[tmp]);
sprintf(buff, "latitude = %10.4f, longitude = %10.4f", latitude, longitude);
Serial.println(buff);
tmp = getComma(7, GPGGAstr);
num = getIntNumber(&GPGGAstr[tmp]);
sprintf(buff, "satellites number = %d", num);
Serial.println(buff);
}
else
{
Serial.println("Not get data");
}
}
void setup()
{
servo.attach(9);
pinMode(A0,INPUT); //make A0 input to read the moisture data
pinMode(7, OUTPUT); ////make pin7 to send out the input moisture data
LTask.begin();
LWiFi.begin();
Serial.begin(115200);
dht.begin();
Serial.println("Temperature sensor on...");
LGPS.powerOn();
Serial.println("LGPS Power on, and waiting ...");
delay(3000);
while(!Serial) delay(1000); /* comment out this line when Serial is not present, ie. run this demo without connect to PC */
Serial.println("Connecting to AP");
while (0 == LWiFi.connect(WIFI_AP, LWiFiLoginInfo(WIFI_AUTH, WIFI_PASSWORD)))
{
delay(1000);
}
Serial.println("calling connection");
while (!c2.connect(SITE_URL, 80))
{
Serial.println("Re-Connecting to WebSite");
delay(1000);
}
delay(100);
getconnectInfo();
connectTCP();
uploadstatusweather();
}
void getconnectInfo(){
//calling RESTful API to get TCP socket connection
c2.print("GET /mcs/v2/devices/");
c2.print(DEVICEID);
c2.println("/connections.csv HTTP/1.1");
c2.print("Host: ");
c2.println(SITE_URL);
c2.print("deviceKey: ");
c2.println(DEVICEKEY);
c2.println("Connection: close");
c2.println();
delay(500);
int errorcount = 0;
while (!c2.available())
{
Serial.println("waiting HTTP response: ");
Serial.println(errorcount);
errorcount += 1;
if (errorcount > 10) {
c2.stop();
return;
}
delay(100);
}
int err = http.skipResponseHeaders();
int bodyLen = http.contentLength();
Serial.print("Content length is: ");
Serial.println(bodyLen);
Serial.println();
char c;
int ipcount = 0;
int count = 0;
int separater = 0;
while (c2)
{
int v = c2.read();
if (v != -1)
{
c = v;
Serial.print(c);
connection_info[ipcount]=c;
if(c==',')
separater=ipcount;
ipcount++;
}
else
{
Serial.println("no more content, disconnect");
c2.stop();
}
}
Serial.print("The connection info: ");
Serial.println(connection_info);
int i;
for(i=0;i<separater;i++)
{ ip[i]=connection_info[i];
}
int j=0;
separater++;
for(i=separater;i<21 && j<5;i++)
{ port[j]=connection_info[i];
j++;
}
Serial.println("The TCP Socket connection instructions:");
Serial.print("IP: ");
Serial.println(ip);
Serial.print("Port: ");
Serial.println(port);
portnum = atoi (port);
Serial.println(portnum);
} //getconnectInfo
void uploadstatus(){
//calling RESTful API to upload datapoint to MCS to report LED status
Serial.println("calling connection");
LWiFiClient c2;
while (!c2.connect(SITE_URL, 80))
{
Serial.println("Re-Connecting to WebSite");
delay(1000);
}
delay(100);
if(digitalRead(7)==1)
upload_led = "LED_Display,,1";
else
upload_led = "LED_Display,,0";
int thislength = upload_led.length();
HttpClient http(c2);
c2.print("POST /mcs/v2/devices/");
c2.print(DEVICEID);
c2.println("/datapoints.csv HTTP/1.1");
c2.print("Host: ");
c2.println(SITE_URL);
c2.print("deviceKey: ");
c2.println(DEVICEKEY);
c2.print("Content-Length: ");
c2.println(thislength);
c2.println("Content-Type: text/csv");
c2.println("Connection: close");
c2.println();
c2.println(upload_led);
delay(500);
int errorcount = 0;
while (!c2.available())
{
Serial.print("waiting HTTP response: ");
Serial.println(errorcount);
errorcount += 1;
if (errorcount > 10) {
c2.stop();
return;
}
delay(100);
}
int err = http.skipResponseHeaders();
int bodyLen = http.contentLength();
Serial.print("Content length is: ");
Serial.println(bodyLen);
Serial.println();
while (c2)
{
int v = c2.read();
if (v != -1)
{
Serial.print(char(v));
}
else
{
Serial.println("no more content, disconnect");
c2.stop();
}
}
}
void connectTCP(){
//establish TCP connection with TCP Server with designate IP and Port
c.stop();
Serial.println("Connecting to TCP");
Serial.println(ip);
Serial.println(portnum);
while (0 == c.connect(ip, portnum))
{
Serial.println("Re-Connecting to TCP");
delay(1000);
}
Serial.println("send TCP connect");
c.println(tcpdata);
c.println();
Serial.println("waiting TCP response:");
} //connectTCP
void heartBeat(){
Serial.println("send TCP heartBeat");
c.println(tcpdata);
c.println();
} //heartBeat
void loop()
{
float h,t,temperature;
dht.readHT(&h,&t);
temperature=t-17;
Serial.println("temp:");
Serial.println(temperature);
Serial.println("LGPS loop");
LGPS.getData(&info);
Serial.println((char*)info.GPGGA);
parseGPGGA((const char*)info.GPGGA);
delay(2000);
val = analogRead(A0);
Serial.println(val);
constrain(val,320,590);// sets the upper and lower limit for val
int mapval= map (val,320,590,100,0); // maps the val values in between 0&100, this is %reading
uploadsensorValues(String(val),"moisture"); // one sample value
uploadsensorValues(String(mapval),"moisture_per");
uploadstatusGPS();
uploadsensorValues(String(temperature),"temperature");
delay(1000);
Serial.println(mapval);
if( mapval>=100)
{
mapval=100;
Serial.println("100% moist");
digitalWrite(7,LOW);
angle = 0;
servo.write(angle);
delay(500);
//motordrive("off");
}
else if( mapval>75 && mapval<=99)
{
Serial.print(mapval);
Serial.println("% moist");
digitalWrite(7,LOW);
angle = 36;
servo.write(angle);
delay(500);
//motordrive("off");
}
else if( mapval>50 && mapval<=75)
{
Serial.print(mapval);
Serial.println("% moist");
digitalWrite(7,LOW);
angle = 72;
servo.write(angle);
delay(500);
//motordrive("off");
}
else if( mapval>25 && mapval<=50)
{
Serial.print(mapval);
Serial.println("% moist");
digitalWrite(7,HIGH);
angle = 108;
servo.write(angle);
delay(500);
//motordrive("off");
}
else if( mapval>0 && mapval<=25)
{
Serial.print(mapval);
Serial.println("% moist");
digitalWrite(7,HIGH);
angle = 144;
servo.write(angle);
delay(500);
//motordrive("off");
}
else if( mapval==0)
{
Serial.print(mapval);
Serial.println("% moist");
digitalWrite(7,HIGH);
angle = 180;
servo.write(angle);
delay(500);
//motordrive("off");
}
//Check for TCP socket command from MCS Server
String tcpcmd="";
while (c.available())
{
int v = c.read();
if (v != -1)
{
Serial.print((char)v);
tcpcmd += (char)v;
if (tcpcmd.substring(40).equals(tcpcmd_led_on)){
digitalWrite(7, HIGH);
angle=180;
servo.write(angle);
delay(10000);
Serial.print("Switch LED ON ");
tcpcmd="";
}else if(tcpcmd.substring(40).equals(tcpcmd_led_off)){
digitalWrite(7, LOW);
angle=0;
servo.write(angle);
delay(10000);
Serial.print("Switch LED OFF");
tcpcmd="";
}
}
}
LDateTime.getRtc(&rtc);
if ((rtc - lrtc) >= per) {
heartBeat();
lrtc = rtc;
}
//Check for report datapoint status interval
LDateTime.getRtc(&rtc1);
if ((rtc1 - lrtc1) >= per1) {
uploadstatus();
lrtc1 = rtc1;
}
}
void uploadsensorValues(String value,String varid){
//calling RESTful API to upload datapoint to MCS to report LED status
Serial.println("calling connection");
LWiFiClient c2;
while (!c2.connect(SITE_URL, 80))
{
Serial.println("Re-Connecting to WebSite");
delay(1000);
}
delay(100);
Serial.println("Connected to MCS");
dataToUpload = "";
dataToUpload = varid+",,"+value;
Serial.println(dataToUpload);
String data = "";
int dataLength = data.length();
int thislength = dataToUpload.length();
HttpClient http(c2);
c2.print("POST /mcs/v2/devices/");
c2.print(DEVICEID);
c2.println("/datapoints.csv HTTP/1.1");
c2.print("Host: ");
c2.println(SITE_URL);
c2.print("deviceKey: ");
c2.println(DEVICEKEY);
c2.print("Content-Length: ");
c2.println(thislength);
c2.println("Content-Type: text/csv");
c2.println("Connection: close");
c2.println();
c2.println(dataToUpload);
c2.println();
c2.println(data);
c2.println();
delay(500);
int errorcount = 0;
while (!c2.available())
{
Serial.print("waiting HTTP response: ");
Serial.println(errorcount);
errorcount += 1;
if (errorcount > 10) {
c2.stop();
return;
}
delay(100);
}
int err = http.skipResponseHeaders();
int bodyLen = http.contentLength();
Serial.print("Content length is: ");
Serial.println(bodyLen);
Serial.println();
while (c2)
{
int v = c2.read();
if (v != -1)
{
Serial.print(char(v));
}
else
{
Serial.println("no more content, disconnect");
c2.stop();
}
}
}
void uploadstatusweather(){
//calling RESTful API to upload datapoint to MCS to report LED status
Serial.println("calling connection");
LWiFiClient c2;
while (!c2.connect(SITE_URL, 80))
{
Serial.println("Re-Connecting to WebSite");
delay(1000);
}
int val1 = analogRead(A0);
Serial.println(val1);
constrain(val1,320,590);// sets the upper and lower limit for val
int mapval1= map (val1,320,590,100,0);
if (val1<10)
{
upload_weather="weather,,1";
Serial.println("HOT weather");
}
else if (mapval1<30 && mapval1>=10)
{
upload_weather="weather,,2";
Serial.println("SUNNY weather");
}
else if (mapval1<70 && mapval1>=30)
{
upload_weather="weather,,3";
Serial.println("DRIZZLING");
}
else if (mapval1<=100 && mapval1>=70)
{
upload_weather="weather,,4";
Serial.println("RAINING");
}
uploadsensorValues(String(mapval1),"weather");
int thislength1 = upload_weather.length();
HttpClient http(c2);
c2.print("POST /mcs/v2/devices/");
c2.print(DEVICEID);
c2.println("/datapoints.csv HTTP/1.1");
c2.print("Host: ");
c2.println(SITE_URL);
c2.print("deviceKey: ");
c2.println(DEVICEKEY);
c2.print("Content-Length: ");
c2.println(thislength1);
c2.println("Content-Type: text/csv");
c2.println("Connection: close");
c2.println();
c2.println(upload_weather);
delay(500);
int errorcount = 0;
while (!c2.available())
{
Serial.print("waiting HTTP response: ");
Serial.println(errorcount);
errorcount += 1;
if (errorcount > 10) {
c2.stop();
return;
}
delay(100);
}
int err = http.skipResponseHeaders();
int bodyLen = http.contentLength();
Serial.print("Content length is: ");
Serial.println(bodyLen);
Serial.println();
while (c2)
{
int v = c2.read();
if (v != -1)
{
Serial.print(char(v));
}
else
{
Serial.println("no more content, disconnect");
c2.stop();
}
}
}
void uploadstatusGPS(){
//calling RESTful API to upload datapoint to MCS to report LED status
Serial.println("calling connection");
LWiFiClient c2;
double lat=latitude/100;
double longi=longitude/100;
while (!c2.connect(SITE_URL, 80))
{
Serial.println("Re-Connecting to WebSite");
delay(1000);
}
String upload_GPS = "GPS_Location,,"+String(lat)+","+String(longi)+","+String(altitude);
//String upload_GPS = "GPS_Location,,12.58,77.36,0";
//uploadsensorValues(upload_GPS,"GPS_Location");
Serial.println(upload_GPS);
int thislength2 = upload_GPS.length();
HttpClient http(c2);
c2.print("POST /mcs/v2/devices/");
c2.print(DEVICEID);
c2.println("/datapoints.csv HTTP/1.1");
c2.print("Host: ");
c2.println(SITE_URL);
c2.print("deviceKey: ");
c2.println(DEVICEKEY);
c2.print("Content-Length: ");
c2.println(thislength2);
c2.println("Content-Type: text/csv");
c2.println("Connection: close");
c2.println();
c2.println(upload_GPS);
delay(500);
int errorcount = 0;
while (!c2.available())
{
Serial.print("waiting HTTP response: ");
Serial.println(errorcount);
errorcount += 1;
if (errorcount > 10) {
c2.stop();
return;
}
delay(100);
}
int err = http.skipResponseHeaders();
int bodyLen = http.contentLength();
Serial.print("Content length is: ");
Serial.println(bodyLen);
Serial.println();
while (c2)
{
int v = c2.read();
if (v != -1)
{
Serial.print(char(v));
}
else
{
Serial.println("no more content, disconnect");
c2.stop();
}
}
}
Comments