Differences

This shows you the differences between two versions of the page.

Link to this comparison view

iothings:proiecte:2023:earthquakedetector [2024/01/15 12:36]
stefania.frunza
iothings:proiecte:2023:earthquakedetector [2024/01/16 00:07] (current)
stefania.frunza [Hardware]
Line 4: Line 4:
   * Master: AAC   * Master: AAC
   * Academic year: 2023-2024   * Academic year: 2023-2024
 +  * Source files: {{:​iothings:​proiecte:​2023:​earthquake_alg.zip|}}
 +  * [[https://​ctipub-my.sharepoint.com/:​p:/​g/​personal/​stefania_frunza_stud_acs_upb_ro/​EarzChLzdI5HsabqWMbrtRUBHImtb95MCGP3-NyDnDz_sA?​e=MOVfD3|Presentation slides]]
 +  * [[https://​youtu.be/​qQ3m6rQsA1Q|Demo]]
  
 =====Introduction===== =====Introduction=====
Line 11: Line 14:
 ===Project Description=== ===Project Description===
 The idea of this project is to gather measurements from a MPU-6050 sensor (with an accelerometer and a gyroscope) and to process the data in order to detect the occurrence of an earthquake. When an earthquake is detected, the following things will happen: The idea of this project is to gather measurements from a MPU-6050 sensor (with an accelerometer and a gyroscope) and to process the data in order to detect the occurrence of an earthquake. When an earthquake is detected, the following things will happen:
-  * on a website ​in the LAN the "​Earthquake detected"​ message will be displayed+  * on a webpage ​in the LAN the "​Earthquake detected"​ message will be displayed
   * on the connected LCD the "​Earthquake detected"​ message will be displayed   * on the connected LCD the "​Earthquake detected"​ message will be displayed
   * a notification will be sent on the user's phone   * a notification will be sent on the user's phone
Line 18: Line 21:
 =====Architecture===== =====Architecture=====
 ====System overview==== ====System overview====
-{{:​iothings:​proiecte:​2023:​eqd_overview.png?​500|}}+{{:​iothings:​proiecte:​2023:​eqd_overview.png?​800|}}
  
 ====Hardware==== ====Hardware====
 ===Components=== ===Components===
   * Board   * Board
-    * **NodeMCU-32S** - based on the ESP-WROOM-32 module that integrates WIFI and Bluetooth+    * [[https://​ardushop.ro/​ro/​home/​1449-nodemcu-32s-38.html?​search_query=esp32&​results=22|NodeMCU-32S - based on the ESP-WROOM-32 module that integrates WIFI and Bluetooth]]
  
   * Sensor:   * Sensor:
-    * **MPU-6050** - an integrated circuit with accelerometer,​ gyroscope and temperature sensor with an I2C interface+    * [[https://​ardushop.ro/​ro/​electronica/​179-modul-giroscop-accelerometru-3-axe.html|MPU-6050 - an integrated circuit with accelerometer,​ gyroscope and temperature sensor with an I2C interface]]
  
   * LCD:   * LCD:
-    * **LCD 16x2** - an LCD screen with yellow-green backlighting and an I2C interface+    * [[https://​ardushop.ro/​ro/​electronica/​36-lcd-1602.html|LCD 16x2 - an LCD screen with yellow-green backlighting and an I2C interface]]
  
   * Breadboard   * Breadboard
Line 37: Line 40:
  
 ===Circuit Diagram=== ===Circuit Diagram===
-In order to use the Earthquake Detector system, the ESP32 board has to be connected to a power source. The hardware assembly should be positioned in a place free from unwanted moves (e.g. tram or elevator trepidations). Depending on the needs, the user can access the website ​in the LAN that will signalize the occurrence of an earthquake. Anyway, When an earthquake is detected, the user will receive a notification on the phone and will be able to visualize the moment of occurrence in the database.+In order to use the Earthquake Detector system, the ESP32 board has to be connected to a power source. The hardware assembly should be positioned in a place free from unwanted moves (e.g. tram or elevator trepidations). Depending on the needs, the user can access the webpage ​in the LAN that will signalize the occurrence of an earthquake. Anyway, When an earthquake is detected, the user will receive a notification on the phone and will be able to visualize the moment of occurrence in the database.
  
-{{:​iothings:​proiecte:​2023:​eqd_diagram.png|}}+{{:​iothings:​proiecte:​2023:​eqd_diagram.png?750|}}
  
 The Pinout scheme of the ESP32 board that I used is the following: The Pinout scheme of the ESP32 board that I used is the following:
Line 49: Line 52:
  
 ====Software==== ====Software====
-===Earthquake Detection algorithm=== +{{:​iothings:​proiecte:​2023:​eqd_flow_2_.png|}}
-TBD+
  
 +===Setup function===
  
-===Code & Structure=== +The first step is to initialize the MPU-6050 sensor, the SPIFFS (since the html code is uploaded on the board'​s SPIFFS), the LCD and to connect the board to Wi-Fi. Also, because we use a notification system and InluxDB, we had to sync time, then we check the InfluxDB server connection. Then, we start the server for HTTP requests and create a handler for web server events.
-TBD+
  
-==Arduino== +<code C> 
-TBD+void setup() { 
 +  Serial.begin(115200);​ 
 +  initMPU();​ 
 +  initSPIFFS();​ 
 +  initWiFi();​ 
 +  initLCD();
  
-==Web app== +  configTime(gmtOffset_sec,​ daylightOffset_sec,​ ntpServer);​ 
-TBD+ 
 +  sensor.addTag("​device",​ "​ESP32"​);​ 
 +  sensor.addTag("​location",​ "​office"​);​ 
 +  sensor.addTag("​WiFi_Name",​ WIFI_NAME);​ 
 + 
 +  // Accurate time is necessary for certificate validation and writing in batches 
 +  // For the fastest time sync find NTP servers in your area: https://​www.pool.ntp.org/​zone/​ 
 +  // Syncing progress and the time will be printed to Serial. 
 +  timeSync(TZ_INFO,​ ntpServer, "​time.nis.gov"​);​ 
 + 
 +  // Check server connection 
 +  if (client.validateConnection()) { 
 +    Serial.print("​Connected to InfluxDB: "); 
 +    Serial.println(client.getServerUrl());​ 
 +  } else { 
 +    Serial.print("​InfluxDB connection failed: "); 
 +    Serial.println(client.getLastErrorMessage());​ 
 +  } 
 + 
 +  server.on("/",​ HTTP_GET, [](AsyncWebServerRequest *request){ 
 +    request->​send(SPIFFS,​ "/​index.html",​ "​text/​html"​);​ 
 +  }); 
 + 
 +  server.serveStatic("/",​ SPIFFS, "/"​);​ 
 + 
 +  // Handle Web Server Events 
 +  events.onConnect([](AsyncEventSourceClient *client){ 
 +     
 +    if(client->​lastId()){ 
 +      Serial.printf("​Client reconnected! Last message ID that it got is: %u\n", client->​lastId());​ 
 +    } 
 +    client->​send("​{\"​message\":​ \"​hello!\"​}",​ NULL, millis(), 10000); 
 +  }); 
 +  server.addHandler(&​events);​ 
 + 
 +  server.begin();​ 
 + 
 +
 +</​code>​ 
 + 
 +===Loop function=== 
 +We start the loop function by making the first read of the MPU-6050 sensor'​s data. This way we get the data against which we will compare the following readings, always storing data from 2 consecutive readings. If the difference between any of the gyroscope or accelerometer'​s data is over a threshold, then an earthquake has been detected. In this case the following actions will take place: 
 +  * an event will be sent in order to make a POST request to the webpage with the information "​Earthquake detected":​ 
 +<code C> 
 +events.send("​Earthquake_detected","​eqd",​millis());​ 
 +</​code>​ 
 +  * a notification will be sent to the user's phone, to warn him about the occurrence of an earthquake:​ 
 +<code C> 
 +sendNotification();​ 
 +</​code>​ 
 +  * the LCD screen will display the message "​Earthquake detected":​ 
 +<code C> 
 +    lcd.backlight();​ 
 +    lcd.setCursor(0,​ 0); 
 +    lcd.print(" ​  ​Earthquake ​  "​);​ 
 +    lcd.setCursor(0,​ 1); 
 +    lcd.print(" ​   detected ​   ");  
 +    //... 
 +    delay(5000);​ 
 +    lcd.clear();​ 
 +</​code>​ 
 +  * add information to the database: 
 +<code C> 
 +    // Store measured value into point 
 +    sensor.clearFields();​ 
 +    // Report RSSI of currently connected network 
 +    sensor.addField("​event",​ "​Earthquake occured"​);​ 
 +    // Print what are we exactly writing 
 +    Serial.print("​Writing:​ "); 
 +    Serial.println(client.pointToLineProtocol(sensor));​ 
 +    // If no Wifi signal, try to reconnect it 
 +    // Write point 
 +    if (!client.writePoint(sensor)) { 
 +      Serial.print("​InfluxDB write failed: "); 
 +      Serial.println(client.getLastErrorMessage());​ 
 +    } 
 +</​code>​ 
 +  * print on the Serial about the occurrence of the earthquake and show the subtraction'​s results between old and new MPU's readings. 
 +This is the body of loop function: 
 +<code C> 
 +void loop() { 
 + 
 +  old_a = a; 
 +  old_g = g; 
 +  old_temp = temp; 
 + 
 +  mpu.getEvent(&​a,​ &g, &​temp);​ 
 + 
 +  if((old_a.acceleration.x == 0) && (old_a.acceleration.y == 0) && (old_a.acceleration.z == 0) &&  
 +     ​(old_g.gyro.x == 0) && (old_g.gyro.y == 0) && (old_g.gyro.z == 0)) { 
 + 
 +    Serial.println("​a.acceleration.x = " + String(a.acceleration.x));​ 
 +    Serial.println("​a.acceleration.y = " + String(a.acceleration.y));​ 
 +    Serial.println("​a.acceleration.z = " + String(a.acceleration.z));​ 
 +    Serial.println("​g.gyro.x = " + String(g.gyro.x));​ 
 +    Serial.println("​g.gyro.y = " + String(g.gyro.y));​ 
 +    Serial.println("​g.gyro.z = " + String(g.gyro.z));​ 
 + 
 +    return; 
 +  } 
 + 
 +  if((abs(g.gyro.x - old_g.gyro.x) >= gyroTh) ||  
 +     ​(abs(g.gyro.y - old_g.gyro.y) >= gyroTh) || 
 +     ​(abs(g.gyro.z - old_g.gyro.z) >= gyroTh) || 
 +     ​(abs(a.acceleration.x - old_a.acceleration.x) >= accTh) ||  
 +     ​(abs(a.acceleration.y - old_a.acceleration.y) >= accTh) ||  
 +     ​(abs(a.acceleration.z - old_a.acceleration.z) >= accTh)) { 
 + 
 +     
 +    events.send("​Earthquake_detected","​eqd",​millis());​ 
 +    sendNotification();​ 
 +     
 + 
 +    lcd.backlight();​ 
 +    lcd.setCursor(0,​ 0); 
 +    lcd.print(" ​  ​Earthquake ​  "​);​ 
 +    lcd.setCursor(0,​ 1); 
 +    lcd.print(" ​   detected ​   ");  
 + 
 +    // Store measured value into point 
 +    sensor.clearFields();​ 
 +    // Report RSSI of currently connected network 
 +    sensor.addField("​event",​ "​Earthquake occured"​);​ 
 +    // Print what are we exactly writing 
 +    Serial.print("​Writing:​ "); 
 +    Serial.println(client.pointToLineProtocol(sensor));​ 
 +    // If no Wifi signal, try to reconnect it 
 +    // Write point 
 +    if (!client.writePoint(sensor)) { 
 +      Serial.print("​InfluxDB write failed: "); 
 +      Serial.println(client.getLastErrorMessage());​ 
 +    } 
 +     
 +    Serial.println("​Earthquake detected."​);​ 
 +    Serial.println("​g.gyro.x - old_g.gyro.x = " + String(g.gyro.x - old_g.gyro.x));​ 
 +    Serial.println("​g.gyro.y - old_g.gyro.y = " + String(g.gyro.y - old_g.gyro.y));​ 
 +    Serial.println("​g.gyro.z - old_g.gyro.z = " + String(g.gyro.z - old_g.gyro.z));​ 
 +     
 +    Serial.println("​a.acceleration.x - old_a.acceleration.x = " + String(a.acceleration.x - old_a.acceleration.x));​ 
 +    Serial.println("​a.acceleration.y - old_a.acceleration.y = " + String(a.acceleration.y - old_a.acceleration.y));​ 
 +    Serial.println("​a.acceleration.z - old_a.acceleration.z = " + String(a.acceleration.z - old_a.acceleration.z));​ 
 + 
 +    a.acceleration.x = old_a.acceleration.x;​ 
 +    a.acceleration.y = old_a.acceleration.y;​ 
 +    a.acceleration.z = old_a.acceleration.z;​ 
 +    g.gyro.x = old_g.gyro.x;​ 
 +    g.gyro.y = old_g.gyro.y;​ 
 +    g.gyro.z = old_g.gyro.z;​ 
 +     
 +    delay(5000);​ 
 +    lcd.clear();​ 
 +  } else { 
 +    events.send("​No_earthquake_detected","​neqd",​millis());​ 
 +    delay(100);​ 
 +  } 
 +
 +</​code>​ 
 + 
 +===sendNotification() function=== 
 +For sending notifications,​ we used the Pushover App, which allows you to receive notifications from custom applications. It offers a free 30-day trial period, so it was just enough for developing this project. I created a Pushover account and then a new application. With the generated API Token and user key we were able to send notifications to users' devices. 
 +<code C> 
 +void sendNotification() { 
 +  // Make HTTPS POST request to send notification 
 +  if (WiFi.status() == WL_CONNECTED) { 
 +    // Create a JSON object with notification details 
 +    // Check the API parameters: https://​pushover.net/​api 
 +    StaticJsonDocument<​512>​ notification;​  
 +    notification["​token"​] = apiToken; //​required 
 +    notification["​user"​] = userToken; //​required 
 +    notification["​message"​] = "​Earthquake detected at " + getLocalTime();​ //​required 
 +    notification["​title"​] = "BAD NEWS"; //​optional 
 +    notification["​url"​] = "";​ //​optional 
 +    notification["​url_title"​] = "";​ //​optional 
 +    notification["​html"​] = "";​ //​optional 
 +    notification["​priority"​] = "";​ //​optional 
 +    notification["​sound"​] = "";​ //​optional 
 +    notification["​timestamp"​] = "";​ //​optional 
 + 
 +    // Serialize the JSON object to a string 
 +    String jsonStringNotification;​ 
 +    serializeJson(notification,​ jsonStringNotification);​ 
 + 
 +    // Create a WiFiClientSecure object 
 +    WiFiClientSecure client; 
 +    // Set the certificate 
 +    client.setCACert(PUSHOVER_ROOT_CA);​ 
 + 
 +    // Create an HTTPClient object 
 +    HTTPClient https; 
 + 
 +    // Specify the target URL 
 +    https.begin(client,​ pushoverApiEndpoint);​ 
 + 
 +    // Add headers 
 +    https.addHeader("​Content-Type",​ "​application/​json"​);​ 
 + 
 +    // Send the POST request with the JSON data 
 +    int httpResponseCode = https.POST(jsonStringNotification);​ 
 + 
 +    // Check the response 
 +    if (httpResponseCode > 0) { 
 +      Serial.printf("​HTTP response code: %d\n", httpResponseCode);​ 
 +      String response = https.getString();​ 
 +      Serial.println("​Response:"​);​ 
 +      Serial.println(response);​ 
 +    } else { 
 +      Serial.printf("​HTTP response code: %d\n", httpResponseCode);​ 
 +    } 
 + 
 +    // Close the connection 
 +    https.end();​ 
 +  } 
 +
 +</​code>​ 
 + 
 +===Web app==
 +The times when I was running away from web developing have finally come to an end. With a very simple interface and some JavaScript code, we managed to send the information to the webpage in real time and show a message accordingly to the occurrence of an earthquake. 
 +<code html> 
 +<​!DOCTYPE html> 
 +<html lang="​en">​ 
 +<​head>​ 
 +    <meta charset="​UTF-8">​ 
 +    <meta name="​viewport"​ content="​width=device-width,​ initial-scale=1.0">​ 
 +    <link rel="​icon"​ href="/​favicon.ico"​ type="​image/​x-icon">​ 
 + 
 +    <​title>​ESP32 MPU-6050 Earthquake Detection</​title>​ 
 +    <​style>​ 
 +        body { 
 +            font-family:​ Arial, sans-serif;​ 
 +            text-align: center; 
 +            margin: 50px; 
 +        } 
 + 
 +        h1 { 
 +            color: #333; 
 +        } 
 + 
 +        #status { 
 +            font-size: 24px; 
 +            margin-top: 20px; 
 +        } 
 + 
 +        .earthquake { 
 +            color: red; 
 +        } 
 + 
 +        .no-earthquake { 
 +            color: green; 
 +        } 
 +    </​style>​ 
 +</​head>​ 
 +<​body>​ 
 +    <​h1>​ESP32 MPU-6050 Earthquake Detection</​h1>​ 
 +    <div id="​status"​ class="​no-earthquake">​No earthquake detected</​div>​ 
 + 
 +    <​script>​ 
 +        if (!!window.EventSource) { 
 +         var source = new EventSource('/​events'​);​ 
 +          
 +         ​source.addEventListener('​open',​ function(e) { 
 +          console.log("​Events Connected"​);​ 
 +         }, false); 
 +         ​source.addEventListener('​error',​ function(e) { 
 +          if (e.target.readyState != EventSource.OPEN) { 
 +            console.log("​Events Disconnected"​);​ 
 +          } 
 +         }, false); 
 +          
 +         ​source.addEventListener('​message',​ function(e) { 
 +          console.log("​message",​ e.data); 
 +         }, false); 
 +          
 +         ​source.addEventListener('​eqd',​ function(e) { 
 +          console.log("​eqd",​ e.data); 
 +          document.getElementById('​status'​).innerText = '​Earthquake detected';​ 
 +          document.getElementById('​status'​).classList.add('​earthquake'​);​ 
 +          document.getElementById('​status'​).classList.remove('​no-earthquake'​);​ 
 +         }, false); 
 +          
 +         ​source.addEventListener('​neqd',​ function(e) { 
 +          console.log("​neqd",​ e.data); 
 +          document.getElementById('​status'​).innerText = 'No earthquake detected';​ 
 +          document.getElementById('​status'​).classList.remove('​earthquake'​);​ 
 +          document.getElementById('​status'​).classList.add('​no-earthquake'​);​ 
 +         }, false); 
 +        } 
 +        </​script>​ 
 + 
 +</​body>​ 
 +</​html>​ 
 +</​code>​
  
 =====Results===== =====Results=====
-TBD+===Web interface=== 
 +When no earthquake is detected, this is how the webpage looks like: 
 + 
 +{{:​iothings:​proiecte:​2023:​webpage_neqd.png?​500|}} 
 + 
 +When an earthquake is detected, this is how the webpage looks like: 
 + 
 +{{:​iothings:​proiecte:​2023:​webpage_eqd.png?​500|}} 
 + 
 +===Notifications=== 
 +In the notification bar, the notification about the occurrence of an earthquake will look like this: 
 + 
 +{{:​iothings:​proiecte:​2023:​notification_bar_eqd.jpeg?​300|}} 
 + 
 +In the Pushover App, the notification history will be stored like this: 
 + 
 +{{:​iothings:​proiecte:​2023:​notification_list_eqd.jpeg?​500|}} 
 + 
 +===InfluxDB=== 
 +This is how are stored the events in InfluxDB: 
 + 
 +{{:​iothings:​proiecte:​2023:​influxdb_eqd.png?​800|}} 
 + 
 +=====Conclusion and Future Work===== 
 +This project can accomplish its purpose if there are some others conditions met. For example, the board with the sensor must be placed in a stable place, free from unwanted moves (e.g. tram or elevator trepidations). Otherwise, it is possible to return false positive results. However, the algorithm used in earthquake detection is a simplistic one and is also prone to wrong results.
  
-=====Conclusion===== +I tried to add MQTT to this project, in order to make the results more accessible for a large number of clients. I will keep this in mind as a future development for this project. Also, I would like to improve the detection algorithm, so that it will take into account readings from the IMU sensor over a larger amount of time (2 seconds, so we can compare the mean of these readings with a threshold).
-TBD+
  
 =====References===== =====References=====
iothings/proiecte/2023/earthquakedetector.1705315010.txt.gz · Last modified: 2024/01/15 12:36 by stefania.frunza
CC Attribution-Share Alike 3.0 Unported
www.chimeric.de Valid CSS Driven by DokuWiki do yourself a favour and use a real browser - get firefox!! Recent changes RSS feed Valid XHTML 1.0