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
Diff: source/main.cpp
- Revision:
- 36:32a0a71555f0
- Child:
- 37:fcb5efa391d5
diff -r 4b847971db1b -r 32a0a71555f0 source/main.cpp --- /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); +}