Last active
August 29, 2015 14:14
-
-
Save ronnietucker/e994feb76ac784916506 to your computer and use it in GitHub Desktop.
Soil Moisture Detection
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
CREDITS: | |
DS3231 library: https://github.com/rodan/ds3231 | |
RTC+LCD code: https://www.youtube.com/watch?v=NDwSrgfsiYQ | |
DHT11 code: http://playground.arduino.cc/main/DHT11Lib | |
WiFi to Thingspeak: http://www.instructables.com/id/ESP8266-Wifi-Temperature-Logger/step3/Arduino-Setup-and-Sketch/ | |
*/ | |
//Celsius to Fahrenheit conversion | |
double Fahrenheit(double celsius) | |
{ | |
return 1.8 * celsius + 32; | |
} | |
// fast integer version with rounding | |
//int Celcius2Fahrenheit(int celcius) | |
//{ | |
// return (celsius * 18 + 5)/10 + 32; | |
//} | |
//Celsius to Kelvin conversion | |
double Kelvin(double celsius) | |
{ | |
return celsius + 273.15; | |
} | |
// dewPoint function NOAA | |
// reference (1) : http://wahiduddin.net/calc/density_algorithms.htm | |
// reference (2) : http://www.colorado.edu/geography/weather_station/Geog_site/about.htm | |
// | |
double dewPoint(double celsius, double humidity) | |
{ | |
// (1) Saturation Vapor Pressure = ESGG(T) | |
double RATIO = 373.15 / (273.15 + celsius); | |
double RHS = -7.90298 * (RATIO - 1); | |
RHS += 5.02808 * log10(RATIO); | |
RHS += -1.3816e-7 * (pow(10, (11.344 * (1 - 1/RATIO ))) - 1) ; | |
RHS += 8.1328e-3 * (pow(10, (-3.49149 * (RATIO - 1))) - 1) ; | |
RHS += log10(1013.246); | |
// factor -3 is to adjust units - Vapor Pressure SVP * humidity | |
double VP = pow(10, RHS - 3) * humidity; | |
// (2) DEWPOINT = F(Vapor Pressure) | |
double T = log(VP/0.61078); // temp var | |
return (241.88 * T) / (17.558 - T); | |
} | |
// delta max = 0.6544 wrt dewPoint() | |
// 6.9 x faster than dewPoint() | |
// reference: http://en.wikipedia.org/wiki/Dew_point | |
double dewPointFast(double celsius, double humidity) | |
{ | |
double a = 17.271; | |
double b = 237.7; | |
double temp = (a * celsius) / (b + celsius) + log(humidity*0.01); | |
double Td = (b * temp) / (a - temp); | |
return Td; | |
} | |
/* | |
* SD card attached to SPI bus ON MEGA as follows: | |
** MOSI - pin 51 | |
** MISO - pin 50 | |
** CLK - pin 52 | |
** CS - pin 53 | |
*/ | |
#include <SD.h> | |
#include <dht11.h> // for DHT11 temp/hum sensor | |
#include <Wire.h> // for use with RTC | |
#include "ds3231.h" // for use with DS3231 RTC | |
#include <LiquidCrystal.h> // for 16x2 LCD screen | |
File myFile; // sets up for SD card file | |
LiquidCrystal lcd(7,6,5,9,3,2); // pins for the LCD screen | |
#define BUFF_MAX 128 | |
dht11 DHT11; // temp sensor stuff | |
#define DHT11PIN 8 // temp sensor stuff | |
// WiFi | |
#define SSID "BTHub4-S5TP" | |
#define PASS "PASSWORD" | |
// Thingspeak | |
#define IP "184.106.153.149" // Thingspeak.com | |
String GET = "GET /update?key=FCN2K2LFWU7YVGLH&field1="; | |
uint8_t time[8]; // for RTC | |
char recv[BUFF_MAX]; | |
unsigned int recv_size = 0; | |
unsigned long prev, interval = 1000; // RTC | |
int const moistureSensor1 = 2; // plant 1 = A2 | |
int moisture_val1 = 0; // plant 1 value | |
int const moistureSensor2 = 1; // plant 2 = A1 | |
int moisture_val2 = 0; // plant 1 value | |
int const lightSensor = 0; // ldr = A0 | |
int lightLevel; // light value | |
void setup() | |
{ | |
Serial.begin(115200); // serial | |
Serial2.begin(9600); // wifi | |
Serial2.setTimeout(1000); | |
Wire.begin(); // RTC | |
DS3231_init(DS3231_INTCN); // RTC | |
memset(recv, 0, BUFF_MAX); // RTC | |
Serial.println("GET time"); | |
lcd.begin(16, 2); // start LCD | |
lcd.clear(); // clear LCD | |
pinMode(53,OUTPUT); // for SD card CS pin | |
if (!SD.begin(53)) { // checks if SD card is ready | |
Serial.println("sd card initialization failed!"); | |
return; | |
} | |
Serial.println("sd card initialization done."); | |
//WiFi setup | |
Serial2.println("AT"); | |
delay(5000); | |
if(Serial2.find("OK")){ | |
connectWiFi(); | |
} | |
//Serial.println("Setting time"); | |
//parse_cmd("T302911604102014",16); | |
// uncomment these two lines (ABOVE) to set date/time | |
// 30=secs / 29=min / 11=hr / 6=day of week / 04=day / 10=month / 2014=year | |
} | |
void loop() | |
{ | |
char in; | |
char tempF[6]; // RTC temp? poss not needed | |
float temperature; // poss for RTC temp | |
char buff[BUFF_MAX]; // RTC | |
unsigned long now = millis(); // RTC | |
struct ts t; // RTC | |
// show time once in a while | |
if ((now - prev > interval) && (Serial.available() <= 0)) { | |
DS3231_get(&t); //Get time | |
int chk = DHT11.read(DHT11PIN); // get temp & humidity | |
lcd.clear(); // clear LCD | |
lcd.setCursor(0,0); // set cursor to 0,0 | |
lcd.print(t.hour); // print hr to LCD | |
lcd.print(":"); // : between hr:mm | |
if(t.min<10) // if mins are <10.... | |
{ | |
lcd.print("0"); // ... put a leading zero | |
} | |
lcd.print(t.min); // print mins to LCD | |
lcd.print(" "); // print space | |
prev = now; // UNSURE | |
if(t.mday<10) // if day <10... | |
{ | |
lcd.print("0"); // ... add a zero | |
} | |
lcd.print(t.mday); // print day to LCD | |
printMonth(t.mon); // print month to LCD | |
// see sub routine to change month between numbers and words | |
lcd.print(t.year); // print year to LCD | |
lcd.setCursor(0,1); //Go to second line of the LCD Screen | |
lcd.print("Tem:"); // write tem | |
lcd.print((float)DHT11.temperature, 0); // print temp to LCD | |
lcd.print((char)223); // degrees symbol for temperature | |
lcd.print("C"); // print C after degrees symbol | |
lcd.print(" "); // print space | |
lcd.print("Hum:"); // print hum | |
lcd.print((float)DHT11.humidity, 0); // print hum to sceen | |
lcd.print("%"); // print % symbol | |
moisture_val1 = analogRead(moistureSensor1); // get plant1 moisture | |
moisture_val2 = analogRead(moistureSensor2); // get plant1 moisture | |
lightLevel = analogRead(lightSensor); // get light level | |
// Thingspeak: | |
String SendLightLevel = String(lightLevel); // for sending to Thingspeak | |
String SendTempLevel = String((float)DHT11.temperature, 0); | |
String SendHumLevel = String((float)DHT11.humidity, 0); | |
String SendPlant1Level = String(moisture_val1); | |
String SendPlant2Level = String(moisture_val2); | |
// Log to file: | |
myFile = SD.open("PLANTLOG.txt", FILE_WRITE); // open file for logging | |
// THIS WILL NEED TO END UP BEING COMMA SEPARATED FOR IMPORTING | |
if (myFile) { | |
// Serial.print("Writing to plantlog.txt..."); | |
myFile.print(t.year); | |
myFile.print("/"); | |
myFile.print(t.mon); | |
myFile.print("/"); | |
myFile.print(t.mday); | |
myFile.print("-"); | |
myFile.print(t.hour); | |
myFile.print(":"); | |
myFile.print(t.min); // log year, month, day, time... | |
myFile.print("-"); | |
myFile.print((float)DHT11.temperature, 0); // log temp | |
myFile.print("'C "); | |
myFile.print((float)DHT11.humidity, 0); // log humidity | |
myFile.print("% | "); | |
myFile.print("Plant 1 = "); | |
myFile.print(moisture_val1); // log moisture value | |
myFile.print(" | "); | |
myFile.print("Plant 2 = "); | |
myFile.print(moisture_val2); // log moisture value | |
myFile.print(" | "); | |
myFile.print("Light = "); | |
myFile.println(lightLevel); // log light level | |
// close the file: | |
myFile.close(); // close file | |
// Serial.println("file closed"); // not really required | |
} else { | |
// if the file didn't open, print an error: | |
// Serial.println("error opening plantlog.txt"); // error message is card is out | |
} | |
// send to Thingspeak | |
updateTemp(SendLightLevel,SendTempLevel, SendHumLevel, SendPlant1Level, SendPlant2Level); | |
delay(100000); // 100 secs (1min) - delay between checks, screen update and logging | |
} | |
} | |
void printMonth(int month) | |
{ | |
switch(month) | |
{ | |
// the /02/, /04/, etc. (below) can be changed to say January, Feb, etc. | |
case 1: lcd.print("/01/");break; | |
case 2: lcd.print("/02/");break; | |
case 3: lcd.print("/03/");break; | |
case 4: lcd.print("/04/");break; | |
case 5: lcd.print("/05/");break; | |
case 6: lcd.print("/06/");break; | |
case 7: lcd.print("/07/");break; | |
case 8: lcd.print("/08/");break; | |
case 9: lcd.print("/09/");break; | |
case 10: lcd.print("/10/");break; | |
case 11: lcd.print("/11/");break; | |
case 12: lcd.print("/12/");break; | |
default: lcd.print(" Error ");break; | |
} | |
} | |
void updateTemp(String SendLightLevel, String SendTempLevel, String SendHumLevel, String SendPlant1Level, String SendPlant2Level){ | |
String cmd = "AT+CIPSTART=\"TCP\",\""; | |
cmd += IP; | |
cmd += "\",80"; | |
Serial2.println(cmd); | |
delay(2000); | |
if(Serial2.find("Error")){ | |
return; | |
} | |
cmd = GET; | |
cmd += "&field1="; | |
cmd += SendLightLevel; | |
cmd += "&field2="; | |
cmd += SendTempLevel; | |
cmd += "&field3="; | |
cmd += SendHumLevel; | |
cmd += "&field4="; | |
cmd += SendPlant1Level; | |
cmd += "&field5="; | |
cmd += SendPlant2Level; | |
cmd += "\r\n"; | |
Serial2.print("AT+CIPSEND="); | |
Serial2.println(cmd.length()); | |
if(Serial2.find(">")){ | |
Serial2.print(cmd); | |
}else{ | |
Serial2.println("AT+CIPCLOSE"); | |
} | |
} | |
boolean connectWiFi(){ | |
Serial2.println("AT+CWMODE=1"); | |
delay(2000); | |
String cmd="AT+CWJAP=\""; | |
cmd+=SSID; | |
cmd+="\",\""; | |
cmd+=PASS; | |
cmd+="\""; | |
Serial2.println(cmd); | |
delay(5000); | |
if(Serial2.find("OK")){ | |
Serial.println("wifi connect"); | |
return true; | |
}else{ | |
Serial.println("wifi not connected"); | |
return false; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment