#include "WiFi.h" #include #include "time.h" #include #include "esp_wpa2.h" #define EAP_IDENTITY "benedicx@oregonstate.edu" #define EAP_USERNAME "benedicx@oregonstate.edu" #define EAP_PASSWORD "qazwsxedcrfvtgb" //password #include #include int thePin = 35; //Voltage divider pin(Needs to be an analog pin) const int interval = 120; //Number of data points per batch sent to the google sheet const int SERIESRESISTOR = 10000; //Resistor value in series with the temperature sensor (Ohms) const char* ssid = "eduroam"; int counter = 0; //Used only in the setup function to hault Wi-Fi connection after a certian period of time String GOOGLE_SCRIPT_ID = "AKfycbyL1knB1gI5g42_nbB0BXLPZvKIvFBGFWGKj4syQkJrTZtKMRn2HlN_cN2Yd2fgijZi"; // the deployment ID of the google apps script int count = 0; // Used to store the number of number of loop function cylcle but indexes only after "interval" loop cycles long timer = 0; // Used in conjunction with the millis function to interated the data collection cycle at each second int x = 0; // This stores the number of loop function cycles total float totalMax = 0; // Needs to be a lower number than the sensor input will typically be float totalMin = 10000000; // Needs to be a larger number than the sensor input will ever be float sum = 0; // Used to caluclate the rolling average of the data float intervalAve[720]; // Defined outside the loop function because it needs to be accessed when the 'r' command is inputed in the serial monitor //Function Definitions: String convertArrayToString(float* array, int size) { String result = ""; for (int i = 0; i < size; i++) { result += String(array[i]); if (i < size - 1) { result += ","; } } return result; } // Function converts the elements of an array into a string separated by commas(important for spliting elements later after sent to the google sheet) float rollAverage(float total, int n){ float rollAve; rollAve = (total)/n; return rollAve; } // Function takes in the total sum and divides it by the number of elements float tenAve(float* array, int t){ float ten = 0; for(int q = 0; q < t; q++){ ten += array[q]; } ten = ten/t; return ten; } // Function adds all the elements of an array and then divides by the number of elements in the array void max(float* array, float &totalMax){ for (int y = 0; y < interval; y++){ if(array[y]>totalMax){ totalMax = array[y]; } } } // Function iterates through the values of an array and compares each to a "max" value replacing the "max" value if the element is greater void min(float* array, float &totalMin){ for (int z = 0; z < interval; z++){ if(array[z] < totalMin){ totalMin = array[z]; } } } // Function iterates through the values of an array and compares each to a "min" value replacing the "min" value if the element is lesser in value void setup() { Serial.begin(115200); // Sets the rate of communication over the serial port for the devices delay(10); Serial.println(); Serial.print("Connecting to network: "); Serial.println(ssid); WiFi.disconnect(true); // Disconnects from wifi to set a new wifi connection WiFi.mode(WIFI_STA); // Initialized wifi mode WiFi.begin(ssid, WPA2_AUTH_PEAP, EAP_IDENTITY, EAP_USERNAME, EAP_PASSWORD); //Begins trying to connect to specified wifi while (WiFi.status() != WL_CONNECTED) { delay(500); Serial.print("."); counter++; if(counter>=60){ // After 30 seconds timeout - reset board ESP.restart(); } } Serial.println(""); Serial.println("WiFi connected"); } void loop() { float batch[interval]; // Array which stores the teperature data and only stores enough data for one upload float iteration[interval]; // Array which stores an index of the current cycles of the data collection loop for the current upload cycle float average[interval]; // Array which stores the values of the rolling average corresponding to the current data point float time[interval]; // Array which stores the time since the program has begun for each data point float twoMinute[interval]; memset(twoMinute, 0, sizeof(average)); memset(time, 0, sizeof(average)); for (int r = 0; r < interval + 1; r++){ iteration[r] = r + count + 1; } // This fills the iteration array with the current indexes for the current loop function cycle memset(batch, 0, sizeof(batch)); // Sets the elements of the array to 0 memset(average, 0, sizeof(average)); // Sets the elements of the array to 0 for (int x = count; x < (count + interval + 1); x++){ // The loop which implements the batch size of the upload. Allows the program to upload data once is has collected a certian amount while(millis() - timer < 1000){}; // Waits until 1 second has passed sincle last data point was colledcted if (millis() - timer == 1000){ // This is the data colloection cycle which works to iterate the for loop only after exactly 1 second has passed. float realTime = millis(); // Using to attach a time stamp to the data using the time array time[x - count - 1] = realTime/1000; // This is where the time array is filled with the millis() value and converted to seconds float ADCvalue; // Analog input from pin 35 float Voltage; // Stores the voltage at pin 35 ADCvalue = analogRead(thePin); // Reads value between 0 and 4096 at pin 35 Voltage = (ADCvalue*3.3)/(4096); // Converts analog value to voltage float T = log((SERIESRESISTOR*(3.3/Voltage)-SERIESRESISTOR)/28000)/(-0.041); // Converts voltage to temperature and stores in T using the steinhart-hart equation sum += T; // Adds the temp value to sum Serial.print("Temperature: "); Serial.print(T); Serial.println(" Celcuis"); batch[x - count - 1] = T; // Fills the batch array with the temperature data every second average[x - count - 1] = rollAverage(sum, x); // Fills the average array with the output of the rolling average function every second Serial.print("x:"); Serial.println(x); // Prints the iteration number to the serial monitor Serial.print("Rolling Average: "); Serial.println(rollAverage(sum, x)); // Prints the output of the rolling average function to the serial monitor } timer = millis(); // Resets the timer variable so that 1 second has to pass before the contents of the if statment are run again } intervalAve[(count/interval)] = tenAve(batch, interval); //Fills the interval average array with the average after the batch of data has be gather. twoMinute[1] = intervalAve[(count/interval)]; count += interval; // increments the count by the interval (120) max(batch, totalMax); // Updates the value of the "totalMax" value so that it can be display if asked for over serial min(batch, totalMin); // Updates the value of the "totalMin" value so that it can be display if asked for over serial if(Serial.available() > 0){ // checks if there was data sent over serial char message = Serial.read(); // sets the data to a single character called "message" if (message == 'r'){ Serial.print("Maximum Value Recorded: "); Serial.print(totalMax); Serial.println(" Celcius"); Serial.print("Minimum Value Recorded: "); Serial.print(totalMin); Serial.println(" Celcius"); Serial.println("Ten Minute Averages: "); for(int i = 0; i < 721; i++){ // Increments through each two minute average in the array and prints each over the serial monitor as long as it is non-zero if(intervalAve[i] != 0){ Serial.print(intervalAve[i]); Serial.println(" Celcius"); } else { break;} } } } String batchString = convertArrayToString(batch, interval); // The following lines use the convert-to-string functions to make each of the data storage arrays into strings String iterationString = convertArrayToString(iteration, interval); String averageString = convertArrayToString(average, interval); String twoMinuteString = convertArrayToString(twoMinute, interval); String timeString = convertArrayToString(time, interval); String urlFinal = "https://script.google.com/macros/s/"+GOOGLE_SCRIPT_ID+"/exec?"+"batch=" + batchString + "&count=" + iterationString + "&rollingaverage=" + averageString + "&tenminuteaverage=" + twoMinuteString + "&time=" + timeString; Serial.print("POST data to spreadsheet:"); Serial.println(urlFinal); HTTPClient http; // Declares http as type HTTPClient http.begin(urlFinal.c_str()); // begins connection and directs to the urlFinal http.setFollowRedirects(HTTPC_STRICT_FOLLOW_REDIRECTS); int httpCode = http.GET(); // Returns an execution code (should be between 200 and 500 for successful connection and execution) Serial.print("HTTP Status Code: "); Serial.println(httpCode); String payload; if (httpCode > 0) { payload = http.getString(); // Gets the response back from the location of urlFinal and prints the reply before ending Serial.println("Payload: "+payload); http.end(); } }