//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 #include #include #include #include #include #include "Adafruit_BME680.h" #include //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); }