/* A variable called SEALEVELPRESSURE_HPA used to save the pressure at the sea level in hectopascal (is equivalent to milibar). This variable is used to estimate the altitude for a given pressure by comparing it with the sea level pressure. This example uses the default value, but for more accurate results, replace the value with the current sea level pressure at your location. */ //****************************************************** //include required libraries #include #include "SD.h" #include "DHT.h" #include #include #include #include #include //****************************************************** #define SEALEVELPRESSURE_HPA (1015.00) //replace with your network ssid and password const char* ssid = "TR-2"; const char* password = "AQW112"; const int DHTPin = 15;//DHT11 attached to ESP32 GPIO 15 const int potPin = 32;//potentiometer attached to ESP32 GPIO 32 const int LDRPin = 35;//LDR attached to ESP32 GPIO 35 const int relayPin = 25;//LDR attached to ESP32 GPIO 25 const int greenLedPin = 27;//LDR attached to ESP32 GPIO 27 const int redLedPin = 26;//LDR attached to ESP32 GPIO 26 const int buttonPin = 33;//Pushbutton attached to ESP32 GPIO 33 // create a bme object Adafruit_BME280 bme; // I2C //Adafruit_BME280 bme(BME_CS); // hardware SPI //Adafruit_BME280 bme(BME_CS, BME_MOSI, BME_MISO, BME_SCK); // software SPI //uncomment one of the lines below for whatever DHT sensor type you're using #define DHTTYPE DHT11 // DHT 11 //#define DHTTYPE DHT21 // DHT 21 (AM2301) //#define DHTTYPE DHT22 // DHT 22 (AM2302), AM2321 // Save reading number on RTC memory RTC_DATA_ATTR int readingID = 0; String dataMessage; DHT dht(DHTPin, DHTTYPE);//intialize DHT sensor File webFile; //web page file stored on the SD card String header;//variable to store the HTTP request WiFiServer server(80);//set web server port number to 80 //define NTP Client to get time WiFiUDP ntpUDP; NTPClient timeClient(ntpUDP); //variables to store temperature and humidity float tempC; float tempF; float humi; float currentTemperatureC; float currentTemperatureF; float currentHumidity; //variables to store relay and pushbutton status const char* RelayStatus[2] = {"DEVICE ON", "DEVICE OFF"}; const char* rel; const char* ButtonStatus[2] = {"BUTTON OFF", "BUTTON ON"}; const char* button; //variables to save date and time String formattedDate; String dayStamp; String timeStamp; //you can adjust the threshold value for 5v relay module activation const int thresholdValue = 2000; //************************************************************************* void setup() { Serial.begin(115200); //initialize serial communications at 115200 bps pinMode(relayPin, OUTPUT);//sets the relayPin as OUTPUT pinMode(greenLedPin, OUTPUT);//sets the greenLedPin as OUTPUT pinMode(buttonPin, INPUT);//sets the buttonPin as INPUT pinMode(redLedPin, OUTPUT);//sets the redLedPin as OUTPUT digitalWrite(relayPin, LOW);//by default device is off dht.begin();//initialize DHT sensor if (!bme.begin(0x76)) { //initialize BME280 sensor Serial.println("Could not find BME280 sensor"); while (1) {} } Serial.println("Initializing SD card..."); if (!SD.begin()) { //initialize SD card Serial.println("ERROR - SD card initialization failed!"); return; // init failed } uint8_t cardType = SD.cardType(); if (cardType == CARD_NONE) { Serial.println("No SD card attached"); return; } // If the data.txt file doesn't exist // Create a file on the SD card and write the data labels File logfile = SD.open("/data.txt"); if (!logfile) { Serial.println("File doens't exist"); Serial.println("Creating file..."); writeFile(SD, "/data.txt", "Reading ID, Date, Hour, DHT Temp *C, DHT Temp *F, DHT Humidity %, BME Temp *C, BME Temp *F, BME Hum %, BME Alt m, BME Pressure hPa, Potentiometer Pos, Luminosity, Relay status, Pusshbutton status \r\n"); } else { Serial.println("File already exists"); } logfile.close(); //initialize a NTPClient to get time timeClient.begin(); // Set offset time in seconds to adjust for your timezone, for example: // GMT +1 = 3600 // GMT +8 = 28800 // GMT -1 = -3600 // GMT 0 = 0 timeClient.setTimeOffset(10800); //connect to Wi-Fi network with SSID and password Serial.print("Connecting to "); Serial.println(ssid); WiFi.begin(ssid, password); while (WiFi.status() != WL_CONNECTED) { delay(500); Serial.print("."); } // Print local IP address and start web server Serial.println(""); Serial.println("WiFi connected."); Serial.println("IP address: "); Serial.println(WiFi.localIP()); server.begin(); } void loop() { WiFiClient client = server.available(); // Listen for incoming clients if (client) { // if new client connects boolean currentLineIsBlank = true; while (client.connected()) { if (client.available()) { // client data available to read char c = client.read(); // read 1 byte (character) from client header += c; // if the current line is blank, you got two newline characters in a row. // that's the end of the client HTTP request, so send a response: if (c == '\n' && currentLineIsBlank) { // send a standard http response header client.println("HTTP/1.1 200 OK"); // Send XML file or Web page // If client already on the web page, browser requests with AJAX the latest // sensor readings (ESP32 sends the XML file) if (header.indexOf("update_readings") >= 0) { // send rest of HTTP header client.println("Content-Type: text/xml"); client.println("Connection: keep-alive"); client.println(); // Send XML file with sensor readings sendXMLFile(client); } // When the client connects for the first time, send it the index.html file // stored in the microSD card else { // send rest of HTTP header client.println("Content-Type: text/html"); client.println("Connection: keep-alive"); client.println(); // send web page stored in microSD card webFile = SD.open("/index.html"); if (webFile) { while (webFile.available()) { // send web page to client client.write(webFile.read()); } webFile.close(); } } break; } // every line of text received from the client ends with \r\n if (c == '\n') { // last character on line of received text // starting new line with next character read currentLineIsBlank = true; } else if (c != '\r') { // a text character was received from client currentLineIsBlank = false; } } // end if (client.available()) } // end while (client.connected()) // Clear the header variable header = ""; // Close the connection client.stop(); Serial.println("Client disconnected."); } // end if (client) } // Send XML file with the latest sensor readings void sendXMLFile(WiFiClient cl) { // Read DHT sensor and update variables readDHT(); getTimeStamp(); logSDCard(); RelayModule(); buttonPress(); // Increment readingID on every new reading readingID++; // Prepare XML file cl.print(""); cl.print(""); cl.print(""); cl.print(tempC); cl.println(""); cl.print(""); cl.print(tempF); cl.println(""); cl.print(""); cl.print(humi); cl.println(""); currentTemperatureC = bme.readTemperature(); cl.print(""); cl.print(currentTemperatureC); cl.println(""); currentTemperatureF = (9.0 / 5.0) * currentTemperatureC + 32.0; cl.print(""); cl.print(currentTemperatureF); cl.println(""); currentHumidity = bme.readHumidity(); cl.print(""); cl.print(currentHumidity); cl.println(""); cl.print(""); cl.print(bme.readAltitude(SEALEVELPRESSURE_HPA)); cl.println(""); cl.print(""); cl.print(bme.readPressure() / 100.0F); cl.println(""); cl.print(""); cl.print(analogRead(potPin)); cl.println(""); cl.print(""); cl.print(analogRead(LDRPin)); cl.println(""); cl.print(""); cl.print(rel); cl.println(""); cl.print(""); cl.print(button); cl.println(""); cl.print(""); } void readDHT() { // Sensor readings may also be up to 2 seconds 'old' (its a very slow sensor) humi = dht.readHumidity(); // Read temperature as Celsius (the default) tempC = dht.readTemperature(); // Read temperature as Fahrenheit (isFahrenheit = true) tempF = dht.readTemperature(true); // Check if any reads failed and exit early (to try again). if (isnan(humi) || isnan(tempC) || isnan(tempF)) { Serial.println("Failed to read from DHT sensor!"); return; } /*Serial.print("Humidity: "); Serial.print(humi); Serial.print(" %\t Temperature: "); Serial.print(tempC); Serial.print(" *C "); Serial.print(tempF); Serial.println(" *F");*/ } // Function to get date and time from NTPClient void getTimeStamp() { while (!timeClient.update()) { timeClient.forceUpdate(); } // The formattedDate comes with the following format: // 2018-05-28T16:00:13Z // We need to extract date and time formattedDate = timeClient.getFormattedDate(); Serial.println(formattedDate); // Extract date int splitT = formattedDate.indexOf("T"); dayStamp = formattedDate.substring(0, splitT); Serial.println(dayStamp); // Extract time timeStamp = formattedDate.substring(splitT + 1, formattedDate.length() - 1); Serial.println(timeStamp); } // Write the sensor readings on the SD card void buttonPress() { int buttonStatus = digitalRead(buttonPin); if (buttonStatus == 0) { button = ButtonStatus[0]; } else { button = ButtonStatus[1]; } } void logSDCard() { dataMessage = String(readingID) + "," + String(dayStamp) + "," + String(timeStamp) + "," + String(tempC) + "," + String(tempF) + "," + String(humi) + "," + String(currentTemperatureC) + "," + String(currentTemperatureF) + "," + String(currentHumidity) + "," + String(bme.readAltitude(SEALEVELPRESSURE_HPA)) + "," + String(bme.readPressure() / 100.0F) + "," + String(analogRead(potPin)) + "," + String(analogRead(LDRPin)) + "," + String(rel) + "," + String(button)+ "\r\n"; Serial.print("Save data: "); Serial.println(dataMessage); appendFile(SD, "/data.txt", dataMessage.c_str()); } void RelayModule() { int digitalValue = digitalRead(relayPin); if (digitalValue == 0) { rel = RelayStatus[1]; } else { rel = RelayStatus[0]; } if (analogRead(LDRPin) >= thresholdValue) { digitalWrite(relayPin, LOW); digitalWrite(greenLedPin, LOW); digitalWrite(redLedPin, HIGH); Serial.println("Device is off"); } else { digitalWrite(relayPin, HIGH); digitalWrite(greenLedPin, HIGH); digitalWrite(redLedPin, LOW); Serial.println("Device is on"); } } // Write to the SD card (DON'T MODIFY THIS FUNCTION) void writeFile(fs::FS &fs, const char * path, const char * message) { Serial.printf("Writing file: %s\n", path); File file = fs.open(path, FILE_WRITE); if (!file) { Serial.println("Failed to open file for writing"); return; } if (file.print(message)) { Serial.println("File written"); } else { Serial.println("Write failed"); } file.close(); } // Append data to the SD card (DON'T MODIFY THIS FUNCTION) void appendFile(fs::FS &fs, const char * path, const char * message) { Serial.printf("Appending to file: %s\n", path); File file = fs.open(path, FILE_APPEND); if (!file) { Serial.println("Failed to open file for appending"); return; } if (file.print(message)) { Serial.println("Message appended"); } else { Serial.println("Append failed"); } file.close(); }