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

source/main.cpp

Committer:
Alvaro13
Date:
2019-08-01
Revision:
38:0813e461b835
Parent:
37:fcb5efa391d5

File content as of revision 38:0813e461b835:


#include "mbed.h"
#include "MPU6050.h"
#include "REF_VALUES.h"
#include "CONSTANTS.h"
#include "FUNCTIONS.h"
#include "Timer.h"
#include "MBed_Adafruit_GPS.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


/**
* Imprime los resultados de la medicion del sismo
*/
void print_debug(){    
    string tweet;
    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);
            
        }    
    }   
}


/**
* 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);
}