//ESP32 Pond Monitoring Station V1.0 /*********************************************************************** * 1. Deep Sleep, WiFi and MQTT Libraries/Definition/Variables... ***********************************************************************/ //WiFi and MQTT #include "WiFi.h" #include "PubSubClient.h" //Local Wifi const char* password = "******************"; const char* ssid = "*********"; //MQTT Server const char* mqtt_server = "hsrw.space"; const char* mqtt_username = "****"; const char* mqtt_password = "****"; const unsigned int mqtt_bufsize = 100; const char* myname = "GroupN"; WiFiClient espClient; PubSubClient mqttClient(espClient); char Buffer[5]; //Deep Sleep #include #define DS3231RTC_I2C_ADDRESS 0x68 #define I2C_SDA 21 #define I2C_SCL 22 //EEPROM #include #define EEPROM_BYTES 2 #define WIFIRESETADDRESS 0 #define MQTTRESETADDRESS 1 //Restart #define RestartPin 27 /*********************************************************************** * 2. DHT-22 ***********************************************************************/ //Definitions and Pins #define DHTTYPE DHT22 //define the DHT-xx sensor const int DHTPIN = 15; //define the Data Pin (GPIO 2) //Libraries & Objects #include DHT dht(DHTPIN, DHTTYPE); //Represents sensor //Variables float dht22AirTem = 0; //takes up new readings + final average float dht22AirTemSum = 0; //takes up the sum of readings for averaging String dht22Temperature = ""; //gives back Temperature as a String for MQTT Transmission float dht22RelHum = 0; //takes up new readings + final average float dht22RelHumSum = 0; //takes up the sum of readings for averaging String dht22Humidity = ""; //gives back Humidity as a String for MQTT Transmission const uint8_t AveragingNumberDHT22 = 5; //Number of measurements to be averaged /*********************************************************************** * 3. DS18B20 ***********************************************************************/ //Definitions and Pins const int ONE_WIRE_BUS = 14; //=GPIO 14 of the ESP32 as 1-Wire Bus //Libraries and Objects #include //Library for the 1-Wire protocol #include //Library for sending commands and receiving data DeviceAddress bottomSensorAddress = {0x28,0xC4,0xA0,0x51,0x38,0x19,0x01,0xC2}; //Address bottom sensor (sensor 1, Tape) DeviceAddress surfaceSensorAddress = {0x28,0x0B,0xDB,0x60,0x38,0x19,0x01,0xA3}; //Address surface sensor (sensor 2, w/o Tape) OneWire oneWire(ONE_WIRE_BUS); //Object representing the 1-Wire bus DallasTemperature DS18B20(&oneWire); //Object representing the sensors //Variables float bottomTem = 0.00; //for Temperature readings String bottomTemperature = ""; //for the Sring to be sent using MQTT float surfaceTem = 0.00; String surfaceTemperature = ""; const uint8_t AveragingNumberDS18B20 = 5; //Number of measurements to be averaged int RESOLUTION = 12; //Resolution of the sensor int TCONV = 750; //Conversion time for resolution = 12 int delayTime = (TCONV/pow(2, (12-RESOLUTION))) + 10; //Necessary delay time after measuring to get new values, depending on resolution /*********************************************************************** * 4. 74HC595 Shift Register ***********************************************************************/ //Shift Register Pins const int LATCHPIN = 2; const int CLOCKPIN = 4; const int DATAPIN = 0; //Shift Register Pin Array byte sensor_numbers[9] = { B00000000, //all off B00000001, //Pin 1 B00000010, //Pin 2 B00000100, //Pin 3 B00001000, //Pin 4 B00010000, //Pin 5 B00100000, //Pin 6 B01000000, //Pin 7 B10000000, //Pin 8 }; /*********************************************************************** * 5. Main Program ***********************************************************************/ void setup() { //Reset Alarm & Enable Connection Wire.begin(I2C_SDA, I2C_SCL); clearAlarm1(); EEPROM.begin(EEPROM_BYTES); Serial.begin(115200); esp_sleep_enable_ext0_wakeup(GPIO_NUM_13,0); WiFiConnect(); MQTTConnect(); //Setup Pins pinMode(LATCHPIN ,OUTPUT); pinMode(CLOCKPIN ,OUTPUT); pinMode(DATAPIN ,OUTPUT); //Take Measuremenents Serial.println("Measuring ..."); powerSwitch(1); //Turn DHT-22 ON measureDHTTemHum(AveragingNumberDHT22); powerSwitch(2); //Turn DS18B20s ON measureDS18B20Tem(AveragingNumberDS18B20); powerSwitch(0); //Turn off all shift register outputs Serial.println("DHT-22 Measurement Results: "); Serial.println("Temperature: " + dht22Temperature + " °C"); Serial.println("Relative Humidity: " + dht22Humidity + " %"); Serial.println("DS18B20 Measurement Results: "); Serial.println("Sensor 1 (Bottom) Measurement: " + bottomTemperature + " °C"); Serial.println("Sensor 2 (Surface) Measurement: " + surfaceTemperature + " °C"); Serial.println("========================================"); //Transmit data with MQTT Serial.println("Transmitting data."); dht22Temperature.toCharArray(Buffer, 6); mqttClient.publish("GroupN/Test/ESP32/Temperature/Air", Buffer); delay(500); dht22Humidity.toCharArray(Buffer, 6); mqttClient.publish("GroupN/Test/ESP32/Humidity/Air", Buffer); delay(500); bottomTemperature.toCharArray(Buffer, 6); mqttClient.publish("GroupN/Test/ESP32/Temperature/Water/Bottom", Buffer); delay(500); surfaceTemperature.toCharArray(Buffer, 6); mqttClient.publish("GroupN/Test/ESP32/Temperature/Water/Surface", Buffer); Serial.println("Going into sleep mode"); Serial.println();Serial.println(); esp_deep_sleep_start(); } void loop() { } /*********************************************************************** * 6. DS18B20 Measurement Function ***********************************************************************/ void measureDS18B20Tem (const uint8_t AveragingNumber){ DS18B20.begin(); bottomTem = 0; surfaceTem = 0; bottomTemperature = ""; surfaceTemperature = ""; for(byte i = 0; i < AveragingNumber; i++) { DS18B20.requestTemperatures(); delay(delayTime); bottomTem += DS18B20.getTempC(bottomSensorAddress); surfaceTem += DS18B20.getTempC(surfaceSensorAddress); } bottomTem /= AveragingNumber; surfaceTem /= AveragingNumber; if(bottomTem<10) bottomTemperature = "0"; bottomTemperature += bottomTem; if(surfaceTem<10) surfaceTemperature = "0"; surfaceTemperature += surfaceTem; } /*********************************************************************** * 7. DHT-22 Measurement Function ***********************************************************************/ void measureDHTTemHum (const uint8_t AveragingNumber) { dht.begin(); //activate Sensor delay(1000); //to prevent unstable status (see Datasheet) dht22AirTemSum = 0; dht22RelHumSum = 0; dht22Temperature = ""; dht22Humidity = ""; for (byte i = 0; i < AveragingNumber; i++) //take n measurements for both { do { //execute this at least once dht22AirTem = dht.readTemperature(); //measure Temperature dht22RelHum = dht.readHumidity(); //measure Humidity if (!isnan(dht22AirTem) && !isnan(dht22RelHum)) //if results are valid, add them to the sum { dht22AirTemSum += dht22AirTem; dht22RelHumSum += dht22RelHum; } else delay(2000); //if measurement is invalid, it has to be repeated. Sensor must not heat up } while (isnan(dht22AirTem) || isnan(dht22RelHum)); //if results were invalid, repeat the loop if (i < (AveragingNumber - 1)) //after the last measurement, there is no delay needed anymore delay(2000); } dht22AirTem = dht22AirTemSum / AveragingNumber; //averaging the measurements to get more accurate results if(dht22AirTem<10) //if the Temperature is below 10°C, add a 0 to the front of the String dht22Temperature = '0'; dht22Temperature = dht22Temperature + dht22AirTem; dht22RelHum = dht22RelHumSum / AveragingNumber; if(dht22RelHum<10) dht22Humidity = '0'; dht22Humidity = dht22Humidity + dht22RelHum; } /*********************************************************************** * 8. 74HC595 Shift Register Function ***********************************************************************/ void powerSwitch(byte pin){ digitalWrite(LATCHPIN, LOW); shiftOut(DATAPIN, CLOCKPIN, MSBFIRST, sensor_numbers[pin]); digitalWrite(LATCHPIN, HIGH); } /*********************************************************************** * 9. DS3231 Deep Sleep Alarm Reset ***********************************************************************/ void clearAlarm1(){ Wire.beginTransmission(DS3231RTC_I2C_ADDRESS); Wire.write(0x0F); Wire.write(B00000000); Wire.endTransmission(); } /*********************************************************************** * 10. WiFi Connection Function ***********************************************************************/ void WiFiConnect(){ byte WiFiResets = EEPROM.read(WIFIRESETADDRESS); unsigned long Timer = millis()+1000; Serial.print("Connecting with WiFi"); WiFi.begin(ssid, password); unsigned long Timeout = millis()+30000; while(WiFi.status() !=WL_CONNECTED){ if(millis()>Timer){ Timer= millis()+1000; Serial.print("."); } if(millis()>Timeout){ if(WiFiResets ==2){ EEPROM.write(WIFIRESETADDRESS, 0); EEPROM.commit(); Serial.println(); Serial.println("Could not connect to MQTT Broker 3 times. Going into deep sleep."); esp_deep_sleep_start(); } else{ WiFiResets++; EEPROM.write(WIFIRESETADDRESS, WiFiResets); EEPROM.commit(); Serial.println(); Serial.println("Could not connect to MQTT Broker. Restarting MCU."); digitalWrite(RestartPin, HIGH); } } } EEPROM.write(WIFIRESETADDRESS, 0); EEPROM.commit(); Serial.println(); Serial.println("Successfully connected to WiFi"); } /*********************************************************************** * 11. MQTT Connection Function ***********************************************************************/ void MQTTConnect(){ byte MQTTResets = EEPROM.read(MQTTRESETADDRESS); unsigned long Timer = millis()+1000; Serial.print("Connecting with MQTT Broker"); mqttClient.setBufferSize (mqtt_bufsize); mqttClient.setServer(mqtt_server, 1883); mqttClient.connect(myname,mqtt_username,mqtt_password); unsigned long Timeout = millis()+30000; while(!mqttClient.connected()){ if(millis()>Timer){ Timer= millis()+1000; Serial.print("."); } if(millis()>Timeout){ if(MQTTResets ==2){ EEPROM.write(MQTTRESETADDRESS, 0); EEPROM.commit(); Serial.println(); Serial.println("Could not connect to MQTT Broker 3 times. Going into deep sleep."); esp_deep_sleep_start(); } else{ MQTTResets++; EEPROM.write(MQTTRESETADDRESS, MQTTResets); EEPROM.commit(); Serial.println(); Serial.println("Could not connect to MQTT Broker. Restarting MCU."); digitalWrite(RestartPin, HIGH); } } mqttClient.connect(myname,mqtt_username,mqtt_password); } EEPROM.write(MQTTRESETADDRESS, 0); EEPROM.commit(); Serial.println(); Serial.println("Successfully connected to MQTT Broker"); }