Skip to content

Instantly share code, notes, and snippets.

@ronnietucker
Last active August 29, 2015 14:14
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ronnietucker/e994feb76ac784916506 to your computer and use it in GitHub Desktop.
Save ronnietucker/e994feb76ac784916506 to your computer and use it in GitHub Desktop.
Soil Moisture Detection
/*
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