Senses an earthquake with MPU6050 and gets time, coordenates and other details of the event with an Adafruit GPS. All the info is sent to an HTTP server

Dependencies:   MPU6050 mbed-http MBed_Adafruit-GPS-Library

Revision:
36:32a0a71555f0
Child:
37:fcb5efa391d5
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/source/main.cpp	Thu Aug 01 03:43:28 2019 +0000
@@ -0,0 +1,325 @@
+
+#include "mbed.h"
+#include "MPU6050.h"
+#include "REF_VALUES.h"
+#include "CONSTANTS.h"
+#include "FUNCTIONS.h"
+#include "Timer.h"
+#include "MBed_Adafruit_GPS.h"
+#include "http_request.h"
+#include "network-helper.h"
+#include "mbed_mem_trace.h"
+
+/**
+* Debbuging led
+*/
+DigitalOut myled(LED1);
+
+/**
+* Puerto serial
+*/
+Serial pc(USBTX, USBRX, BAUD_RATE);
+
+/**
+* Puntero hacia el puerto serial utilizado para la comunicacion entre el GPS y el Micro
+*/
+Serial * gps_Serial;
+
+/** 
+* Objeto MPU6050
+*/
+MPU6050 mpu(PF_15, PF_14);
+
+/** 
+* Threads
+*/
+Thread sampleAccelero;
+Thread printDebug;
+Thread sendAccelero;
+Thread getCoordinates;
+
+/**
+* Mutex
+*/ 
+Mutex semaforo;
+Mutex globalVar;
+
+/** 
+* Mailboxes
+*/
+Mail<acceleration, 1> mail_box;
+Mail<acceleration, 1> mail_meass;
+
+/**
+* Variables de control
+*/
+bool earthquakeHappening = false;
+bool beenHere = false;
+
+
+
+/**
+* Handler para la utilizacion del GPS
+*/
+Adafruit_GPS myGPS(new Serial(PC_12, PD_2)); //object of Adafruit's GPS class
+
+/**
+* Codigo para el HTTP post
+*/
+void dump_response(HttpResponse* res) {
+    printf("Status: %d - %s\n", res->get_status_code(), res->get_status_message().c_str());
+
+    printf("Headers:\n");
+    for (size_t ix = 0; ix < res->get_headers_length(); ix++) {
+        printf("\t%s: %s\n", res->get_headers_fields()[ix]->c_str(), res->get_headers_values()[ix]->c_str());
+    }
+    printf("\nBody (%d bytes):\n\n%s\n", res->get_body_length(), res->get_body_as_string().c_str());
+}
+
+/**
+* Imprime los resultados de la medicion del sismo
+*/
+void print_debug(){    
+    string tweet;
+    NetworkInterface* network = connect_to_default_network_interface();
+    if (!network) {
+        printf("Cannot connect to the network, see serial output\n");
+        return ;
+    }
+    // Create a TCP socket
+    printf("\n----- Setting up TCP connection -----\n");
+
+    TCPSocket* socket = new TCPSocket();
+    nsapi_error_t open_result = socket->open(network);
+    if (open_result != 0) {
+        printf("Opening TCPSocket failed... %d\n", open_result);
+        return ;
+    }
+    
+    nsapi_error_t connect_result = socket->connect("10.60.16.220", 80);
+    if (connect_result != 0) {
+        printf("Connecting over TCPSocket failed... %d\n", connect_result);
+        return ;
+    }
+    
+    printf("Connected over TCP to httpbin.org:80\n");
+    while(true){
+        wait(1);
+        osEvent evt = mail_meass.get();
+        if (evt.status == osEventMail) {
+            acceleration *mail = (acceleration*)evt.value.p;
+            if (mail->x == 0  && mail->y == 0){
+                mail_meass.free(mail);
+                continue;
+            }
+            tweet = compute_intensity(mail->x, mail->y);
+            semaforo.lock();
+            pc.printf("%s\n\r",tweet);
+            semaforo.unlock();
+            mail_meass.free(mail);
+            pc.printf("Time: %d:%d:%d.%u\r\n", myGPS.hour, myGPS.minute, myGPS.seconds, myGPS.milliseconds);
+            pc.printf("Date: %d/%d/20%d\r\n", myGPS.day, myGPS.month, myGPS.year);
+            pc.printf("Location: %f%c, %f%c\r\n", myGPS.latitude, myGPS.lat, myGPS.longitude, myGPS.lon);
+            pc.printf("Altitude: %f\r\n", myGPS.altitude);
+            
+            // POST request to httpbin.org
+            HttpRequest* post_req = new HttpRequest(socket, HTTP_POST, "http://10.60.16.200");
+            post_req->set_header("Content-Type", "application/json");
+
+            const char body[] = "{\"hello\":\"world\"}";
+
+            HttpResponse* post_res = post_req->send(body, strlen(body));
+            if (!post_res) {
+                printf("HttpRequest failed (error code %d)\n", post_req->get_error());
+                return ;
+            }
+
+            printf("\n----- HTTP POST response -----\n");
+            dump_response(post_res);
+
+            delete post_req;
+            
+        }    
+    }   
+}
+
+
+/**
+* Interpreta la acceleracion sismica del terremoto a una escala de la intensidad del mismo.
+*/
+string compute_intensity(float xPGA, float yPGA){
+    float maxPGA;
+    
+    xPGA >= yPGA ? maxPGA = xPGA : maxPGA = yPGA;
+    
+    string result;
+    
+    if (maxPGA >= moderate.lowBound && maxPGA <= moderate.highBound)
+        result = "Earthquake detected! \t Mercalli Scale: " + moderate.scale + "\t" + moderate.damage + " Damage"; 
+        
+    else if (maxPGA >= strong.lowBound && maxPGA <= strong.highBound)
+        result = "Earthquake detected! \t Mercalli Scale: " + strong.scale + "\t" + strong.damage + " Damage";
+
+    else if (maxPGA >= veryStrong.lowBound && maxPGA <= veryStrong.highBound)
+        result = "Earthquake detected! \t Mercalli Scale: " + veryStrong.scale + "\t" + veryStrong.damage + " Damage";
+
+    else if (maxPGA >= severe.lowBound && maxPGA <= severe.highBound)
+        result = "Earthquake detected! \t Mercalli Scale: " + severe.scale + "\t" + severe.damage + " Damage";
+    
+    else if (maxPGA >= violent.lowBound && maxPGA <= violent.highBound)
+        result = "Earthquake detected! \t Mercalli Scale: " + violent.scale + "\t" + violent.damage + " Damage";
+
+    else if (maxPGA >= extreme.lowBound && maxPGA <= extreme.highBound)
+        result = "Earthquake detected! \t Mercalli Scale: " + extreme.scale + "\t" + extreme.damage + " Damage";
+        
+    else
+        result = "No Intensity recognized";
+
+    return result;
+}
+
+
+/**
+* Mide la data entregada por el acelerometro
+*/
+void measure() {
+    
+    // Ajusta la sensibilidad del sensor
+    mpu.setAcceleroRange(MPU6050_ACCELERO_RANGE_2G);
+    
+    // Configura la frecuencia de corte del filtro paso bajo
+    mpu.setBW(MPU6050_BW_5);
+   
+    // Test the connection
+    if (mpu.testConnection())
+        pc.printf("MPU6050 test passed \r\n");    
+    else
+        pc.printf("MPU6050 test failed \r\n");
+    
+    /**
+    * Array que almacena la data Raw para la acceleracion en X, Y, Z
+    */
+    float acce[3];
+    /**
+    * Aceleracion en X
+    */
+    float xAcc;
+    /**
+    * Aceleracion en Y
+    */
+    float yAcc;
+    
+
+    while(1) {    
+        // Adecua el muestreo para una frecuencia determinada 
+        wait(SAMPLE_RATE_MEASURE);
+        
+        // Procesa la data obtenida del sensor de las aceleraciones en X, Y, Z
+        mpu.getAccelero(acce);
+        
+        // Aceleracion sismica en XY (g)
+        xAcc = (float)acce[0] / (GRAVITY_CONSTANT);
+        yAcc = (float)acce[1] / (GRAVITY_CONSTANT);
+        
+        acceleration* mailAcc = mail_box.alloc();
+        
+        mailAcc->x = abs(xAcc);
+        mailAcc->y = abs(yAcc);
+        mail_box.put(mailAcc);   
+        
+        // Revisa la ocurrencia de un sismo
+        if (abs(xAcc) >= moderate.lowBound || abs(yAcc) >= moderate.lowBound && !beenHere){
+            globalVar.lock();
+            earthquakeHappening = true;
+            beenHere = true;
+            globalVar.unlock();
+        }
+    
+    }
+
+}
+
+void send_meassure(){
+    Timer tick;
+    bool meassuring = false;
+    acceleration *data;
+    acceleration maxData;
+    maxData.x = 0;
+    maxData.y = 0;
+    while (true){
+        wait_ms(200);
+        globalVar.lock();
+        if (earthquakeHappening)
+            meassuring = true;
+        globalVar.unlock();
+        while (meassuring){
+            wait_ms(50);
+            osEvent evt = mail_box.get();
+            if (evt.status == osEventMail) {
+                acceleration *mail = (acceleration*)evt.value.p;
+                data = mail;         
+                mail_box.free(mail);
+            }
+            if (data->x >= moderate.lowBound || data->y >= moderate.lowBound ){
+                tick.reset();
+                if (data->x > maxData.x || data->y > maxData.y){
+                    maxData = *data;
+                }
+            }
+            else {
+                tick.start();
+                if (tick.read_ms() <= 200)
+                    continue;
+                tick.stop();
+                meassuring = false;
+            }
+        }
+        globalVar.lock();
+        beenHere = false;
+        earthquakeHappening = false;
+        globalVar.unlock();
+        acceleration* mailAcc = mail_meass.alloc();
+        mailAcc->x = maxData.x;
+        mailAcc->y = maxData.y;
+        mail_meass.put(mailAcc); 
+        maxData.x = 0;
+        maxData.y = 0;       
+    }
+}
+   
+/**
+* Se encarga de obtener la cordenadas del Thread
+*/
+void getGPSCoordinates(){
+    
+    char c; // when read via Adafruit_GPS::read(), the class returns single character stored here
+    Timer refresh_Timer; // sets up a timer for use in loop; how often do we print GPS info?
+    const int refresh_Time = 2000; //refresh time in ms
+    
+    myGPS.begin(9600);  // sets baud rate for GPS communication; note this may be changed via Adafruit_GPS::sendCommand(char *)
+                        // a list of GPS commands is available at http://www.adafruit.com/datasheets/PMTK_A08.pdf
+    
+    myGPS.sendCommand(PMTK_SET_NMEA_OUTPUT_RMCGGA); //these commands are defined in MBed_Adafruit_GPS.h; a link is provided there for command creation
+    myGPS.sendCommand(PMTK_SET_NMEA_UPDATE_1HZ);
+    myGPS.sendCommand(PGCMD_ANTENNA);    
+    
+    refresh_Timer.start();  // starts the clock on the timer
+    
+    while(true){
+        c = myGPS.read();   // queries the GPS
+        
+        // check if we recieved a new message from GPS, if so, attempt to parse it,
+        if ( myGPS.newNMEAreceived() ) 
+            if ( !myGPS.parse(myGPS.lastNMEA()) )
+                continue;
+    }
+}
+
+
+int main()
+{
+    sampleAccelero.start(measure);
+    sendAccelero.start(send_meassure);
+    printDebug.start(print_debug);
+    getCoordinates.start(getGPSCoordinates);
+}