//Irragation controller project
//
// To-Do List
//
// Complete
// Wind speed - daily average over 24 hours
// Need to slow down ABS Press to maybe hourly or every 15 min, maybe not req'd
//-----X---- Need to figure out floats and ints for next calculations for ETO
// Need to get hours of sunlight, need to setup and test LDR under various conditons
//-----X---- Need to figure out why there is gaps/skips in the seconds, trying to fix with bool true and false in the if statements
// Issue with day of year, seems to be one day short/behind, possible daylight savings issues in eztime library
//-----X---- Eliminate double count of EtoTotal
//-----X---- Elimnate double clear/reset of values, possibly add another bool value as with other if loops
// There is still a gap in the time ?
// Need to figure out how to have the calculation start properly when it's turned on
// for example if unit is started at 1:45 pm code will have to run at 11:50 pm not 1:45 pm plus time period (23 hours)
//
//
// Rev1 - 3/20/2019
// Started Vapour Press Deficit Calc
//
// Rev2 - 3/22/2019
// finished Vapour Press Deficit Calc
// started radiation section
//
// Rev2a - 3/24/2019
// completed Eto Calc with test example
//
// Rev2b - 3/24/2019
// added test parameters to code for testing
//
// Rev3 - 3/24/2019
// started live testting
// eto calc does not match - correct in 3a
// pressure does not have any decimal digits - corrected in 3a
//
// Rev3a - 3/25/2019
// Live testing complete without (sun hours and wind)
// Code clean-up
//
// Rev3b - 3/26/2019
// started to test why code is double counting Eto -corrected
// everything seems to work as required
//
// Rev3c - 3/26/2019
// will start to increase time in min and hours to see response
// works but still skips
//
// Rev3d - 3/27/2019
// start to play with millis for timing of events
// seems to work as needed with the exception of the timing still being off
#include <ezTime.h>
#include <ESP8266WiFi.h>
#include <OneWire.h>
#include <DallasTemperature.h>
#include <Wire.h>
#include <Adafruit_Sensor.h>
#include "Adafruit_BME680.h"
#include <elapsedMillis.h>
//Timing functions
elapsedMillis Test1; //time to calculate Eto
elapsedMillis Test2; //adds to EtoTotal
elapsedMillis Test3; //if total Eto > 12.7
elapsedMillis Test4; //clears dailty parameter
unsigned long time1;
#define ONE_WIRE_BUS 2
int TempLive;
int TempMax = 0;
int TempMin = 99999;
float TempMean = 0;
float TempMaxDay = 0;
float TempMinDay = 0;
int RHLive;
int RHMax = 0;
int RHMin = 99999;
float RHMean = 0;
float RHMaxDay = 0;
float RHMinDay = 0;
float PressLive;
float PressTotal = 0;
float PressCount = 0;
float PressAvg = 0;
float u2 = 0;
float u2Test = 2.0171; //to be removed when sensor installed, also in wind section
float g = 0;
float D = 0;
float n = 9.25; //need to get a sensor to get actual hours of sun, contstant for now
float eoTmax = 0;
float eoTmin = 0;
float es = 0;
float ea = 0;
float SatVapPressDeff = 0;
String Day;
float J = 0;
float j = 0;
float dr = 0;
float d = 0;
float ws = 0;
float Radi1 = 0;
float Radi2 = 0;
float Ra = 0;
float N = 0;
float nN = 0;
float Rs = 0;
float Rso = 0;
float RsRso = 0;
float Rns = 0;
float oTmaxK4 = 0;
float oTminK4 = 0;
float Rnl = 0;
float Rn = 0;
float G = 0.0;
float RnG = 0;
float Radi3 = 0;
float gre1 = 0;
float gre2 = 0;
float EtoDay = 0;
float EtoTotal = 0;
int Control = 0;
//TEST Values
Timezone Canada;
OneWire oneWire (ONE_WIRE_BUS); //Sets up a oneWire instance to communicate with any OneWire devices
DallasTemperature DS18B20(&oneWire); //Pass our one wire reference to Dallas temperature
Adafruit_BME680 bme; //BME680 using I2C
void setup() {
Serial.begin(115200);
WiFi.begin("", ""); //wifi credentials to connect
waitForSync(); //Syncs NTP Time
//Serial.println("UTC: " + UTC.dateTime());
Canada.setLocation("America/Yellowknife"); //https://en.wikipedia.org/wiki/List_of_tz_database_time_zones
//Serial.println("Canada time: " + Canada.dateTime()); //prints local time based on fixed location
setInterval(3600); //pools and/or adjusts time from pooling the NTP server every 15 (xx) seconds
//setDebug(INFO); //Show's what eztime library is doing, uncomment to show
DS18B20.begin(); // Start up the library
bme.begin();
bme.setTemperatureOversampling(BME680_OS_8X);
bme.setHumidityOversampling(BME680_OS_2X);
bme.setPressureOversampling(BME680_OS_4X);
bme.setIIRFilterSize(BME680_FILTER_SIZE_3);
bme.setGasHeater(320, 150); // 320*C for 150 ms
}
//Run over and over :)
void loop() {
time1 = millis();
//events(); //Part of setInterval and setDebu, shows what's going on, uncomment to show
//Gets live values every second (not sure what dictates the seconds/interval), may change interval at a later time
Serial.println(time1);
DS18B20.requestTemperatures(); //send command to get temp
Serial.println(millis());
TempLive = DS18B20.getTempCByIndex(0)*100; //By index becuase you can have more than one IC on the BUS 0 = first device
if (TempLive > TempMax) { //see's if live value is greater than first max temp value
TempMax=TempLive; } //if it is MaxTemp is changed to the new value
if (TempLive < TempMin) { //see's if live value is greater than first min temp value
TempMin=TempLive; } //if it is MinTemp is changed to the new value
bme.performReading();
RHLive = bme.humidity*100;
if (RHLive > RHMax) { //see's if live value is greater than first max RH value
RHMax=RHLive; } //if it is RHMax is changed to the new value
if (RHLive < RHMin) {
RHMin=RHLive; }
PressLive = bme.pressure / 10.0;
PressTotal = PressTotal + PressLive;
PressCount = PressCount + 1.0;
PressAvg = (PressTotal / PressCount)/100.0;
//
//START - gets the live sensors daily min/max values, pressure will be the average
TempMaxDay = TempMax/100.0;
TempMinDay = TempMin/100.0;
RHMaxDay = RHMax/100.0;
RHMinDay = RHMin/100.0;
//END -gets the sensor data every minute and reports hourly average, this data will be used for the min/max 24 hour values
//
//START - calculates the eto value from the past day - Exact Run Time TBA
if (Test1 >= 10000) {
Test1 = Test1 -10000;
//Parameters
//TempMaxDay = TempMax/100.0;
//TempMinDay = TempMin/100.0;
TempMean = (TempMaxDay+TempMinDay)/2.0;
g = 0.000665 * (PressAvg);
D = (4098*(0.6108*exp((17.27*TempMean)/(TempMean+237.3))))/((TempMean+237.3)*(TempMean+237.3));
//Wind
//u2 = 2.0778; //needs to wind in m/s at 2 m height
u2 = u2Test;
//Vapour Pressure Deficit
//RHMaxDay = RHMax/100.0;
//RHMinDay = RHMin/100.0;
RHMean = (RHMaxDay+RHMinDay)/2.0;
eoTmax = 0.6108*exp((17.27*TempMaxDay)/(TempMaxDay+237.3));
eoTmin = 0.6108*exp((17.27*TempMinDay)/(TempMinDay+237.3));
es = (eoTmax + eoTmin)/2;
ea = ((eoTmin*(RHMaxDay/100.0))+(eoTmax*(RHMinDay/100.0)))/2;
SatVapPressDeff = es-ea;
//Radiation
Day = Canada.dayOfYear();
J = Day.toFloat();
j = (M_PI/180.0)*(53.54444+(113.4909/60.0));
dr = 1.0+0.033*cos((2.0*M_PI/365.0)*J);
d = 0.409*sin(((2.0*M_PI)/365.0)*J-1.39);
ws = acos(-tan(j)*tan(d));
Radi1 = sin(j)*sin(d);
Radi2 = cos(j)*cos(d);
Ra = ((24.0*60.0)/M_PI)*0.082*dr*((ws*Radi1)+Radi2*sin(ws));
N = (24.0/M_PI)*ws;
nN = n/N;
Rs = (0.25+(0.5*(nN)))*Ra;
Rso = (0.75+0.00002*645.0)*Ra;
RsRso = Rs/Rso;
Rns = (1.0-0.23)*Rs;
oTmaxK4 = 0.0026*(TempMaxDay*TempMaxDay)+0.3912*TempMaxDay+27.336;
oTminK4 = 0.0026*(TempMinDay*TempMinDay)+0.3912*TempMinDay+27.336;
Rnl = ((oTmaxK4+oTminK4)/2)*(0.34-0.14*sqrt(ea))*((1.35*(Rs/Rso))-0.35);
Rn = Rns - Rnl;
RnG = Rn - G;
Radi3 = 0.408*(Rn-G);
//Grass refernce evapotranspiration
gre1 = 0.408*(Rn)*D/(D+g*(1.0+(0.34*u2)));
gre2 = 900.0/(TempMaxDay+273.0)*u2*(es-ea)*g/(D+g*(1.0+(0.34*u2)));
EtoDay = gre1+gre2;
}
//FirstTimeParam = true;
if (Test2 >= 20000) {
Test2 = Test2 -20000;
EtoTotal = EtoTotal + EtoDay;
//FirstTimeParam = false;
}
//END -calculates the past/current day eto value
// START - checks to see if watering is required
if (Test3 >= 30000 && EtoTotal >= 12.70) {
Test3 = Test3 -30000;
Serial.println("Sprinklers On");
EtoTotal = EtoTotal - 12.70; //subtract applied water (12.7 mm) from total
}
//END - calculates to see if watering is required
//START - clears the last values used for Eto calculation, will start with fresh readings at the time below
if (Test4 >= 40000) {
Test4 = Test4 -40000;
TempMax = 0;
TempMin = 99999;
TempMaxDay = 0;
TempMinDay = 0;
RHMax = 0;
RHMin = 99999;
RHMaxDay = 0;
RHMinDay = 0;
PressTotal = 0;
PressCount = 0;
PressAvg = 0;
}
//END - clears the last days min/ and max values
Serial.print(Canada.dateTime());
Serial.print("\t");
Serial.print(time1);
Serial.print("\t");
//Serial.print(TempLive);
//Serial.print("\t");
Serial.print(TempMinDay);
Serial.print("\t");
Serial.print(TempMaxDay);
Serial.print("\t");
//Serial.print(RHLive);
//Serial.print("\t");
Serial.print(RHMinDay);
Serial.print("\t");
Serial.print(RHMaxDay);
Serial.print("\t");
//Serial.print(PressLive);
//Serial.print("\t");
//Serial.print(EtoTotal);
//Serial.print("\t");
//Serial.print(PressAvg*100);
//Serial.print("\t");
//Serial.print(Day);
//Serial.print("\t");
//Serial.print(FirstTimeParam);
//Serial.print("\t");
//Serial.print(FirstTimeEtoTotal);
//Serial.print("\t");
//Serial.print(J);
//Serial.print("\t");
//Serial.print(j*100);
//Serial.print("\t");
//Serial.print(dr*100);
//Serial.print("\t");
//Serial.print(d*100);
//Serial.print("\t");
//Serial.print(ws*100);
//Serial.print("\t");
//Serial.print(Radi1*100);
//Serial.print("\t");
//Serial.print(Radi2*100);
//Serial.print("\t");
//Serial.print(Ra);
//Serial.print("\t");
//Serial.print(N);
//Serial.print("\t");
//Serial.print(nN*100);
//Serial.print("\t");
//Serial.print(Rs);
//Serial.print("\t");
//Serial.print(Rso);
//Serial.print("\t");
//Serial.print(RsRso*100);
//Serial.print("\t");
//Serial.print(Rns);
//Serial.print("\t");
//Serial.print(oTmaxK4);
//Serial.print("\t");
//Serial.print(oTmaxK4);
//Serial.print("\t");
//Serial.print(Rnl);
//Serial.print("\t");
//Serial.print(Rn);
//Serial.print("\t");
//Serial.print(RnG);
//Serial.print("\t");
//Serial.print(Radi3);
//Serial.print("\t");
//Serial.print(gre1);
//Serial.print("\t");
//Serial.print(gre2);
//Serial.print("\t");
//Serial.print(TestTotal);
//Serial.print("\t");
Serial.print(EtoDay*100);
Serial.print("\t");
Serial.println(EtoTotal*100);
}
Comments