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:
- 36:32a0a71555f0
- Child:
- 37:fcb5efa391d5
File content as of revision 36:32a0a71555f0:
#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);
}
