/*
Actividad 2: Protocolos de comunicación en IoT y transmisión de datos vía MQTT
Partes 2 y 3: Aplicación de Protocolo MQTT Utilizando Wokwi y Transmisión de Datos a Adafruit.io
SERGIO MARTINEZ VAZQUEZ
El objetivo de este programa es transmitir los datos obtenidos por el
sensor MPU6050 a la plataforma Adafruit. El sensor toma datos mediante un acelerometro,
giroscopio y un termometro; una aplicacion general de este programa seria la toma de datos
para monitorear el estado de un motor y asi mediante tecnicas de IA y Big Data poder
predecir cuando es necesario realizar los mantenimientos.
*/
// Llamar las librerias a utilizar
#include <Adafruit_MPU6050.h> //Para el uso del sensor MPU6050
#include <Adafruit_Sensor.h> // Para el uso de sensores en Adafruit
#include <Wire.h> // Para comunicarse en protocolo serie
#include <WiFi.h> // Libreria para conectar wifi
#include "Adafruit_MQTT.h" // Libreria para conectar a Adafruit
#include "Adafruit_MQTT_Client.h" // Libreria para conectar a Adafruit
// Credenciales para conectar a Adafruit
#define AIO_SERVER "io.adafruit.com" // Pagina de Adafruit
#define AIO_SERVERPORT 1883 // Puerto del servidor (1883 por defecto)
#define AIO_USERNAME "SMtzV" // USUARIO DE ADAFRUIT
#define AIO_KEY "aio_PiXR97MsVJo63WP5nBA9Zvmpe851" // CLAVE DE USUARIO
WiFiClient client; //Conexión Mqtt
// Conexion al servidor de Adafruit
Adafruit_MQTT_Client mqtt (&client, AIO_SERVER, AIO_SERVERPORT, AIO_USERNAME, AIO_KEY);
// Configuracion de los topics a publicar o transmitir los datos a ADAFRUIT
Adafruit_MQTT_Publish A_x = Adafruit_MQTT_Publish(&mqtt, AIO_USERNAME"/feeds/AccX"); // AcelX
Adafruit_MQTT_Publish A_y = Adafruit_MQTT_Publish(&mqtt, AIO_USERNAME"/feeds/AccY"); // AcelY
Adafruit_MQTT_Publish A_z = Adafruit_MQTT_Publish(&mqtt, AIO_USERNAME"/feeds/AccZ"); // AcelZ
Adafruit_MQTT_Publish G_x = Adafruit_MQTT_Publish(&mqtt, AIO_USERNAME"/feeds/GyrX"); // GiroX
Adafruit_MQTT_Publish G_y = Adafruit_MQTT_Publish(&mqtt, AIO_USERNAME"/feeds/GyrY"); // GiroY
Adafruit_MQTT_Publish G_z = Adafruit_MQTT_Publish(&mqtt, AIO_USERNAME"/feeds/GyrZ"); // GiroZ
Adafruit_MQTT_Publish T = Adafruit_MQTT_Publish(&mqtt, AIO_USERNAME"/feeds/TenC"); // Temperatura
// Conexion a Internet del ESP32
#define wifi "Wokwi-GUEST" // Red
#define pass "" // Contraseña
#define canal 6 // Canal
// Configuracion del display mediante librerias Adafruit
#include <Adafruit_SSD1306.h>
#include <Adafruit_GFX.h>
// Configuracion del display
#define SCREEN_WIDTH 128 // OLED display width, in pixels
#define SCREEN_HEIGHT 64 // OLED display height, in pixels
#define OLED_RESET 4
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire);
Adafruit_MPU6050 mpu;
// Programa para verificar la conexion al display
void setup(void) {
Serial.begin(115200);
if(!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) { // Address 0x3C for 128x32
Serial.println(F("SSD1306 allocation failed"));
for(;;); // Don't proceed, loop forever
}
// Inicializacion del display
display.clearDisplay();
display.setTextSize(2);
display.setTextColor(WHITE,0);
display.setCursor(35,10);
display.print("ESP32");
display.setCursor(25,40);
display.print("MPU6050");
display.display();
// Verificacion del estatus del sensor MPU6050
if (!mpu.begin()) {
Serial.println("Failed to find MPU6050 chip"); //SI el sensor no se encuentra
while (1) {
delay(10);
}
}
Serial.println();
Serial.print("Conectando a"); // Si el sensor se encuentra conectado
Serial.println(wifi);
// Configuracion de la muestra de datos del acelerometro
mpu.setAccelerometerRange(MPU6050_RANGE_2_G); // Limite del rango a 2 veces la gravedad
mpu.setGyroRange(MPU6050_RANGE_250_DEG); // Limite del rango a 250°
mpu.setFilterBandwidth(MPU6050_BAND_21_HZ);
Serial.println("");
delay(1000);
// Verificacion a la conexion a la red
WiFi.begin("Wokwi-GUEST", "", 6);
while(WiFi.status()!= WL_CONNECTED){
Serial.print(".");
delay(100);
}
Serial.println(" Conectado exitosamente!");
}
// Funcionalidad principal
void loop() {
/* Obtencion de datos y configuracion de las variables */
sensors_event_t a, g, temp; // a para Aceleracion, g para giroscopio y temp para temperatura
mpu.getEvent(&a, &g, &temp); // Recolecta datos del MPU6050 y los refrencia a las variables previas
// Limpieza de datos del display
display.clearDisplay();
display.setTextSize(1);
display.setTextColor(WHITE,0);
display.setCursor(0,0);
//Desplegamos los datos del acelerometro
display.println("Axel:");
display.print(a.acceleration.x/10); // Valores en veces la gravedad de la Tierra
display.print(",");
display.print(a.acceleration.y/10);
display.print(",");
display.println(a.acceleration.z/10);
display.println("");
// Desplegamos los datos del giroscopio
display.println("Gyro:"); //Los datos los da en radianes
display.print(g.gyro.x);
display.print(",");
display.print(g.gyro.y);
display.print(",");
display.print(g.gyro.z);
// Desplegamos los datos del temometro
display.println("Temp: "); // Valores en Celsius
display.print(temp.temperature);
display.print("Grados C");
display.display();
delay(10);
/* Publicacion de los datos obteneidos en adafruit*/
// Aceleracion en X *****************************************************
MQTT_connect();
Serial.print(("\n Valores de A (X)"));
//Aquí ponemos los feed que se vana recuperar
Serial.print(a.acceleration.x/10);
Serial.print("....");
if (! A_x.publish(a.acceleration.x/10)){
Serial.print(F("Fallo")); //Puedes pasar strings almacenados en memoria flash a Serial.print() encapsulándolos con F()
}else{
Serial.print(F("ok"));
}
delay(1000);//No olvidar este retraso, tiene limite de datos recibidos adafruit.
// Aceleracion en Y *****************************************************
MQTT_connect();
Serial.print(("\n Valores de A (Y)"));
//Aquí ponemos los feed que se vana recuperar
Serial.print(a.acceleration.y/10);
Serial.print("....");
if (! A_y.publish(a.acceleration.y/10)){
Serial.print(F("Fallo")); //Puedes pasar strings almacenados en memoria flash a Serial.print() encapsulándolos con F()
}else{
Serial.print(F("ok"));
}
delay(1000);//No olvidar este retraso, tiene limite de datos recibidos adafruit.
// Aceleracion en Z *****************************************************
MQTT_connect();
Serial.print(("\n Valores de A (Z)"));
//Aquí ponemos los feed que se vana recuperar
Serial.print(a.acceleration.z/10);
Serial.print("....");
if (! A_z.publish(a.acceleration.z/10)){
Serial.print(F("Fallo")); //Puedes pasar strings almacenados en memoria flash a Serial.print() encapsulándolos con F()
}else{
Serial.print(F("ok"));
}
delay(1000);//No olvidar este retraso, tiene limite de datos recibidos adafruit.
/* ########################################################################################*/
// Valores obtenidos por el giroscopio en X ******************************
MQTT_connect();
Serial.print(("\n Giro (X)"));
//Aquí ponemos los feed que se vana recuperar
Serial.print(g.gyro.x);
Serial.print("....");
if (! G_x.publish(g.gyro.x)){
Serial.print(F("Fallo")); //Puedes pasar strings almacenados en memoria flash a Serial.print() encapsulándolos con F()
}else{
Serial.print(F("ok"));
}
delay(1000);//No olvidar este retraso, tiene limite de datos recibidos adafruit.
// Valores obtenidos por el giroscopio en Y ******************************
MQTT_connect();
Serial.print(("\n Giro (Y)"));
//Aquí ponemos los feed que se vana recuperar
Serial.print(g.gyro.y);
Serial.print("....");
if (! G_y.publish(g.gyro.y)){
Serial.print(F("Fallo")); //Puedes pasar strings almacenados en memoria flash a Serial.print() encapsulándolos con F()
}else{
Serial.print(F("ok"));
}
delay(1000);//No olvidar este retraso, tiene limite de datos recibidos adafruit.
// Valores obtenidos por el giroscopio en Z ******************************
MQTT_connect();
Serial.print(("\n Giro (Z)"));
//Aquí ponemos los feed que se vana recuperar
Serial.print(g.gyro.z);
Serial.print("....");
if (! G_z.publish(g.gyro.z)){
Serial.print(F("Fallo")); //Puedes pasar strings almacenados en memoria flash a Serial.print() encapsulándolos con F()
}else{
Serial.print(F("ok"));
}
delay(1000);//No olvidar este retraso, tiene limite de datos recibidos adafruit.
/* ########################################################################################*/
// Valores obtenidos por el Termometro ******************************
MQTT_connect();
Serial.print(("\n Temperatura (°C)"));
//Aquí ponemos los feed que se vana recuperar
Serial.print(temp.temperature);
Serial.print("....");
if (! T.publish(temp.temperature)){
Serial.print(F("Fallo")); //Puedes pasar strings almacenados en memoria flash a Serial.print() encapsulándolos con F()
}else{
Serial.print(F("ok"));
}
delay(1000);//No olvidar este retraso, tiene limite de datos recibidos adafruit.
delay(5000); //Delay general para evitar limitar a Adafruit
}
// NO olvidar añadir al código, la función MQTT_connect()
void MQTT_connect(){
int8_t ret;
if(mqtt.connected()){
return;
}
Serial.print("Conectando a MQTT");
uint8_t retries = 3; // ciclos que se demora en volverlo a intentar
while(ret = mqtt.connect()!=0){
Serial.println(mqtt.connectErrorString(ret));
Serial.println(" Reintentando conectar a MQTT en 5 segundos...");
mqtt.disconnect(); //metodo interno que tiene la libreria
delay (5000);
if(retries == 0){
while(1);
}
}
Serial.println(" Conectado!!!");
}