diff --git a/Arduino/labsage_v1.1_6.ino b/Arduino/labsage_v1.1_6.ino new file mode 100644 index 0000000..0b9ddb1 --- /dev/null +++ b/Arduino/labsage_v1.1_6.ino @@ -0,0 +1,488 @@ +/****************************************************************************************************************************** + * Date: 28/02/2023 + * Filename: LabSage_v1.1.5 + * Description: ESP Multitasking + EMS + * Update - Changing thresholds, re-timing tasks - Resetting GAS threshold as constant value due to large difference + *****************************************************************************************************************************/ +// INCLUDE LIBRARIES +#include // Install TaskScheduler Arduino Library +#include // Install WiFiManager Library +#include // Install Firebase ESP8266 library (Mobitz?) +#include +#include +#include // Install DHT11 Library and Adafruit Unified Sensor Library +#include +#include +#include // Install Adafruit ADXL345 accelerometer library + +// FIREBASE RTDB PATH AND KEY +#define FIREBASE_HOST "https://smartlab-9b83e-default-rtdb.firebaseio.com/" +#define FIREBASE_AUTH "AIzaSyCiO5owTmUgosDyjL0_SqpxRoAwgKtn5-o" + +// SETTING PINS FOR SENSORS +#define LED D1 +#define DHTPIN D2 // Connect Data pin of DHT to D2 +#define GASPIN A0 // Gas sensor analog pin +#define BUZZERPIN D7 // Connect LED to D7 +#define SDA D5 +#define SCL D6 + +// DHT VARIABLE SET +#define DHTTYPE DHT11 + +// OBJECT DECLARATIONS +Scheduler runner; +WiFiManager wm; +DHT dht(DHTPIN, DHTTYPE); +Adafruit_ADXL345_Unified accel = Adafruit_ADXL345_Unified(12345); + +//MQ2 parameter for LPG/Smoke sensing +float gasSensor_volt; +float RS; +const float R0 = 2.12; +const float b = 1.5120222; +const float m = -0.33975668; +float RS_R0_ratio; +float ppm_log; +float ppm; + +// VARIABLE DEFINITION +float t, h, g; +String buzz = "0"; +String coll = "0"; +float x, y, z; +String PATH = "Devices/"; +String UID = ""; +float sum = 0; +int k = 0; +// THRESHOLD VALUES +const float COLLISION_THRESHOLD = 10.0; // Too sensitive perhaps? +const float SMOKE_THRESHOLD = 15000; // NEEDS TO BE UPLOADED TO THE BOARD YET!!! + +// DEFINE FIREBASE DATA OBJECT +FirebaseData firebaseData; +FirebaseData buzzerData; + +FirebaseJson json; + +// FUNCTION DECLARATION +void dhtSetup(void); +void gasSetup(void); +void ambiRead(void); +void accelSetup(void); +void accelRead(void); +void sensorUpdate(void); +void upload(void); +void uploadAlert(void); +void sensorReset(void); +void reconnection(void); + +// TASK SCHEDULE FUNCTIONS +void task1Callback() { // Sensor update + // code for task 1 + sensorUpdate(); +} + +void task2Callback() { // Sensor value upload + // code for task 2 + if (WiFi.status() == WL_CONNECTED) { + upload(); + } + else { + Serial.println("Connection Lost!"); + digitalWrite(LED, !digitalRead(LED)); + Serial.println("Please Reconnect to a different WiFi.\nStarting Soft API..."); + reconnection(); + } + } + +void task3Callback(){ // Reset receive and execute + if (WiFi.status() == WL_CONNECTED){ + if (Firebase.getString(buzzerData, PATH + "/reset") && buzzerData.stringData() == "1") { //Read from firebase for application + Serial.println("Call to reset"); + sensorReset(); + if (Firebase.setString(firebaseData, PATH + "/reset", "0")) + { + Serial.println("PASSED"); + Serial.println("PATH: " + firebaseData.dataPath()); + Serial.println("TYPE: " + firebaseData.dataType()); + Serial.println("ETag: " + firebaseData.ETag()); + Serial.println("------------------------------------"); + Serial.println(); + } + else + { + Serial.println("FAILED"); + Serial.println("REASON: " + firebaseData.errorReason()); + Serial.println("------------------------------------"); + Serial.println(); + } + uploadAlert(); + } + if (buzz == "1" || coll== "1"){ + uploadAlert(); + } + } + else { + Serial.println("Connection Lost!"); + digitalWrite(LED, !digitalRead(LED)); + Serial.println("Please Reconnect to a different WiFi.\nStarting Soft API..."); + reconnection(); + } +} + +Task t1(1000, TASK_FOREVER, &task1Callback); // Task rate: Once every second +Task t2(60000, TASK_FOREVER, &task2Callback); // Task rate: Once every minute +Task t3(3000, TASK_FOREVER, &task3Callback); // Task rate: Once every 3 seconds + +// SETUP +void setup(){ + pinMode(LED, OUTPUT); + digitalWrite(LED, LOW); + pinMode(BUZZERPIN, OUTPUT); + Serial.begin(9600); + dhtSetup(); + gasSetup(); + accelSetup(); + UID = ESP.getChipId(); // Extract Unique Chip ID for authentication and identity purposes + Serial.printf("ESP8266 Unique Chip id = %s\n", UID); // For hex representation, use %08X + Serial.println(); + Serial.println("Opening WiFi AP"); +// wm.resetSettings(); // Comment out before deployment + bool res; + wm.setConnectTimeout(60); + wm.setConfigPortalTimeoutCallback(reconnection); + wm.setWiFiAutoReconnect(true); + res = wm.autoConnect("SMI_LBS_ESP"); // auto generated AP name from chipid + if (!res) { + Serial.println("Failed to connect"); + } + else { + //if you get here you have connected to the WiFi + Serial.println("Connected"); + } + Firebase.begin(FIREBASE_HOST, FIREBASE_AUTH); // Begin Firebase Server + Firebase.reconnectWiFi(true); + + Serial.println(PATH.concat(UID)); // Dynamic database path allocation + digitalWrite(LED, HIGH); + runner.init(); // Initialise Scheduler, add tasks to it, and then enable the tasks for multitasking + runner.addTask(t1); + runner.addTask(t2); + runner.addTask(t3); + t1.enable(); + t2.enable(); + t3.enable(); +} + +// MAIN LOOP CODE +void loop() { + runner.execute(); // Run the tasks simultaneously +} + +void reconnection(void) { // Re-establishing network with new Wi-Fi using Soft AP + bool res = wm.autoConnect(); + if (!res) { + Serial.println("Failed to connect"); + } + else { + Serial.println("Connected"); + } +} + +void accelSetup(void) { // Setup Accelerometer + Serial.println("Accelerometer Test"); Serial.println(""); + + // Initialise I2C communication as MASTER + Wire.begin(SDA, SCL); + + if (!accel.begin()) { + Serial.println("Failed to initialize ADXL345 sensor."); + while (1); + } + accel.setRange(ADXL345_RANGE_16_G); // Setting Max Range + // Get accelerometer data + sensors_event_t event; + accel.getEvent(&event); + // Assign current values to states + x = event.acceleration.x; + y = event.acceleration.y; + z = event.acceleration.z; + Serial.println("Accelerometer Ready!"); Serial.println(""); +} + +void accelRead(void) { // Read Accelerometer + // Get accelerometer data + sensors_event_t event; + accel.getEvent(&event); + + // Print the accelerometer data to serial monitor + Serial.print("Acceleration: "); + Serial.print(event.acceleration.x); + Serial.print(" m/s^2 "); + Serial.print(event.acceleration.y); + Serial.print(" m/s^2 "); + Serial.print(event.acceleration.z); + Serial.println(" m/s^2 "); + if (isnan(event.acceleration.x) || isnan(event.acceleration.y) || isnan(event.acceleration.z)) { + Serial.println(F("Failed to read from Accelerometer!")); + return; + } + // Check if there is a collision + if ((abs(event.acceleration.x - x)) > COLLISION_THRESHOLD || + (abs(event.acceleration.y - y)) > COLLISION_THRESHOLD || + (abs(event.acceleration.z - z)) > COLLISION_THRESHOLD) { + Serial.println("Collision detected!"); + coll = "1"; + tone(BUZZERPIN, 100); + } + // Assign current values to states + x = event.acceleration.x; + y = event.acceleration.y; + z = event.acceleration.z; +} + +void dhtSetup(void) { // Setup DHT11 + Serial.println(F("DHT11 setting up...")); + dht.begin(); + Serial.println("DHT11 ready!"); +} + +void gasSetup(void) { // Setup MQ-2 Smoke Sensor + Serial.println("Gas Sensor setting up..."); + pinMode(GASPIN, INPUT_PULLUP); + Serial.println("Gas Sensor ready!"); + Serial.printf("\nSmoke Threshold: %f ppm\n", SMOKE_THRESHOLD); + Serial.println(""); +} + +void ambiRead(void) { // Temp, Humidity, Gas reading + // Read relative humidity in % (the default) + h = dht.readHumidity(); + + // Read temperature as Celsius (the default) + t = dht.readTemperature(); + // Read gas sensor analog data + float gasSensorValue = analogRead(GASPIN); + gasSensor_volt = gasSensorValue / 1024 * 5.0; + RS = ((5 - gasSensor_volt) / gasSensor_volt); + RS_R0_ratio = RS / R0; + ppm_log = ((log (RS_R0_ratio) - b) / m); + ppm = pow (10, ppm_log); + g = ppm; + + // Check if any reads failed and exit early (to try again). + if (isnan(h) || isnan(t)) { + Serial.println(F("Failed to read from DHT sensor!")); + return; + } + if(isnan(g)){ + Serial.println(F("Failed to read from Gas sensor!")); + return; + } +// Check if there is a fire/smoke + if (g > SMOKE_THRESHOLD) { + sum += g; + k++; + Serial.println("Smoke detected!"); + buzz = "1"; + tone(BUZZERPIN, 400); + } + else { + if(k<=10){ + buzz = "0"; + if (coll == "0") { + noTone(BUZZERPIN); + }} + } + Serial.print(F("Humidity: ")); + Serial.print(h); + Serial.print(F("% Temperature: ")); + Serial.print(t); + Serial.print(F("C PPM:")); + Serial.print(g); + Serial.println(); + + +} + +void sensorUpdate(void) { + ambiRead(); + accelRead(); +} + +void sensorReset(void) { + coll = "0"; + buzz = "0"; + noTone(BUZZERPIN); + sum = 0; + k = 0; +} + +void upload(void) { + if (Firebase.setFloat(firebaseData, PATH + "/temperature", t)) + { + Serial.println("PASSED"); + Serial.println("PATH: " + firebaseData.dataPath()); + Serial.println("TYPE: " + firebaseData.dataType()); + Serial.println("ETag: " + firebaseData.ETag()); + Serial.println("------------------------------------"); + Serial.println(); + } + else + { + Serial.println("FAILED"); + Serial.println("REASON: " + firebaseData.errorReason()); + Serial.println("------------------------------------"); + Serial.println(); + } + + if (Firebase.setFloat(firebaseData, PATH + "/humidity", h)) + { + Serial.println("PASSED"); + Serial.println("PATH: " + firebaseData.dataPath()); + Serial.println("TYPE: " + firebaseData.dataType()); + Serial.println("ETag: " + firebaseData.ETag()); + Serial.println("------------------------------------"); + Serial.println(); + } + else + { + Serial.println("FAILED"); + Serial.println("REASON: " + firebaseData.errorReason()); + Serial.println("------------------------------------"); + Serial.println(); + } + if (Firebase.setFloat(firebaseData, PATH + "/ppm", g)) + { + Serial.println("PASSED"); + Serial.println("PATH: " + firebaseData.dataPath()); + Serial.println("TYPE: " + firebaseData.dataType()); + Serial.println("ETag: " + firebaseData.ETag()); + Serial.println("------------------------------------"); + Serial.println(); + } + else + { + Serial.println("FAILED"); + Serial.println("REASON: " + firebaseData.errorReason()); + Serial.println("------------------------------------"); + Serial.println(); + } + + if (Firebase.setFloat(firebaseData, PATH + "/x", x)) + { + Serial.println("PASSED"); + Serial.println("PATH: " + firebaseData.dataPath()); + Serial.println("TYPE: " + firebaseData.dataType()); + Serial.println("ETag: " + firebaseData.ETag()); + Serial.println("------------------------------------"); + Serial.println(); + } + else + { + Serial.println("FAILED"); + Serial.println("REASON: " + firebaseData.errorReason()); + Serial.println("------------------------------------"); + Serial.println(); + } + if (Firebase.setFloat(firebaseData, PATH + "/y", y)) + { + Serial.println("PASSED"); + Serial.println("PATH: " + firebaseData.dataPath()); + Serial.println("TYPE: " + firebaseData.dataType()); + Serial.println("ETag: " + firebaseData.ETag()); + Serial.println("------------------------------------"); + Serial.println(); + } + else + { + Serial.println("FAILED"); + Serial.println("REASON: " + firebaseData.errorReason()); + Serial.println("------------------------------------"); + Serial.println(); + } + if (Firebase.setFloat(firebaseData, PATH + "/z", z)) + { + Serial.println("PASSED"); + Serial.println("PATH: " + firebaseData.dataPath()); + Serial.println("TYPE: " + firebaseData.dataType()); + Serial.println("ETag: " + firebaseData.ETag()); + Serial.println("------------------------------------"); + Serial.println(); + } + else + { + Serial.println("FAILED"); + Serial.println("REASON: " + firebaseData.errorReason()); + Serial.println("------------------------------------"); + Serial.println(); + } +} + +void uploadAlert(void){ + if (Firebase.setString(firebaseData, PATH + "/buzzer", buzz)) + { + Serial.println("PASSED"); + Serial.println("PATH: " + firebaseData.dataPath()); + Serial.println("TYPE: " + firebaseData.dataType()); + Serial.println("ETag: " + firebaseData.ETag()); + Serial.println("------------------------------------"); + Serial.println(); + } + else + { + Serial.println("FAILED"); + Serial.println("REASON: " + firebaseData.errorReason()); + Serial.println("------------------------------------"); + Serial.println(); + } + if (Firebase.setString(firebaseData, PATH + "/collision", coll)) + { + Serial.println("PASSED"); + Serial.println("PATH: " + firebaseData.dataPath()); + Serial.println("TYPE: " + firebaseData.dataType()); + Serial.println("ETag: " + firebaseData.ETag()); + Serial.println("------------------------------------"); + Serial.println(); + } + else + { + Serial.println("FAILED"); + Serial.println("REASON: " + firebaseData.errorReason()); + Serial.println("------------------------------------"); + Serial.println(); + } +} +/* +void startCustomConfigPortal() { + WiFiManager wifiManager; + wifiManager.setConfigPortalTimeout(120); + wifiManager.setMinimumSignalQuality(-1); + const char * pass = "SM1ota#W"; //"46EAD57A89F1D240CBD7704B6FAD544C"; //"46ead57a89f1d240cbd7704b6fad544c"; + WiFiManagerParameter password("", "Developer Options Password", "", 40); + wifiManager.addParameter(&password); + + WiFiManagerParameter customHtmlOptions("
Info  Update"); + const char * c1 = customHtmlOptions.getValue(); + wifiManager.setCustomHeadElement(c1); + + if (!wifiManager.startConfigPortal("Custom Config Portal")) { + Serial.println("Failed to connect and hit timeout"); + delay(3000); + ESP.reset(); + delay(5000); + } + + const char * uPass = password.getValue(); + Serial.println(); + if (strcmp(uPass, pass) == 0) { + WiFiManagerParameter customHtmlDeveloperOptions("
Info  Update"); + const char * c = customHtmlDeveloperOptions.getValue(); + wifiManager.setCustomHeadElement(c); + } else { + wifiManager.setCustomHeadElement(""); + wifiManager.startConfigPortal("Custom Config Portal"); + } +} +*/