// IMPORTACIÓN DE LIBRERÍAS:
#include <WiFi.h> // Facilita la gestión de la conectividad a redes WiFi.
#include <PubSubClient.h> // Permite la suscripción a temas y publicación de mensajes a través de MQTT.
#include <Wire.h> // Facilita la comunicación con dispositivos a través del protocolo I2C.
#include <MPU6050_light.h> // Proporciona funciones específicas para gobernar sensor MPU6050.
// ASIGNACIÓN DE PINES:
#define AD0 16
// DECLARACIÓN DE VARIABLES:
MPU6050 mpu(Wire); // Asociación del objeto mpu a la comunicación I2C.
float temp;
float acel_x;
float acel_y;
float acel_z;
unsigned long tiempo_actual;
unsigned long tiempo_previo = millis(); // Temporizador actualizado.
const unsigned long frecuencia_muestreo = 5000; // Frecuencia de muestreo deseada.
// Credenciales de la red WiFi:
const char* wifi_ssid = "Wokwi-GUEST";
const char* wifi_contra = "";
// Detalles del broker MQTT:
const char* mqtt_servidor = "io.adafruit.com";
const char* mqtt_usuario = "oalroa";
const char* mqtt_llave = "aio_uySU60QGOustwk9DazDTR471Jn0B";
// Temas del proyecto:
const char* subtopic_temp = "oalroa/feeds/actividad.temp";
const char* subtopic_acel_x = "oalroa/feeds/actividad.acel-x";
const char* subtopic_acel_y = "oalroa/feeds/actividad.acel-y";
const char* subtopic_acel_z = "oalroa/feeds/actividad.acel-z";
// CREACIÓN DEL CLIENTE DE RED
WiFiClient wifi_cliente;
PubSubClient mqtt_cliente(wifi_cliente);
// DECLARACIÓN DE FUNCIONES DE USUARIO:
void conecta_wifi();
void conecta_mqtt();
void leer_mpu(float &lect_temp, float &lect_acel_x, float &lect_acel_y, float &lect_acel_z);
void imprimir_lecturas(float lect_temp, float lect_acel_x, float lect_acel_y, float lect_acel_z);
void publicar_lecturas(float lect_temp, float lect_acel_x, float lect_acel_y, float lect_acel_z);
// FUNCIÓN setup (CONFIGURACIÓN):
void setup() {
// Inicialización de la comunicación serial a 115.200 bits por segundo:
Serial.begin(115200);
// Inicialización de la comunicación I2C (pines por defecto: SDA = 21 y SCL = 22):
Wire.begin();
// Inicialización del pin AD0, en estado HIGH para deseleccionar el sensor MPU6050:
pinMode(AD0, OUTPUT);
digitalWrite(AD0, HIGH);
// Inicialización del sensor MPU6050:
Serial.print("Inicializando el sensor MPU6050");
while (!mpu.begin()) {
Serial.print(".");
delay(500);
}
Serial.println(" ---> INICIALIZADO");
delay(2000);
conecta_wifi(); // Se ejecuta la función conecta_wifi para inicializar la conexión a la red WiFi.
mqtt_cliente.setServer(mqtt_servidor, 1883); // Configuración del servidor MQTT, indicando el dominio del mismo y el puerto (por defecto para MQTT es 1883).
conecta_mqtt();
}
// FUNCIÓN loop (PROGRAMA PRINCIPAL):
void loop() {
// En caso que se haya perdido la conexión a la red WiFi, se debe volver a conectar a ella y al broker MQTT, mediante las funciones conecta_wifi y conecta_mqtt:
if (WiFi.status() != WL_CONNECTED){
conecta_wifi();
conecta_mqtt();
}
// En caso que no haya conexión con el broker MQTT, se debe volver a conectar al mismo mediante la función conecta_mqtt:
else if (!mqtt_cliente.connected()) {
conecta_mqtt();
}
mqtt_cliente.loop(); // Función loop de la librería PubSubClient para mantener la conexión con el broker MQTT, ayudar en su reconexión y gestionar mensajes entrantes.
tiempo_actual = millis();
if(tiempo_actual - tiempo_previo >= frecuencia_muestreo) {
tiempo_previo = tiempo_actual;
leer_mpu(temp, acel_x, acel_y, acel_z);
imprimir_lecturas(temp, acel_x, acel_y, acel_z);
publicar_lecturas(temp, acel_x, acel_y, acel_z);
}
}
// FUNCIÓN conecta_wifi (CONEXIÓN A LA RED WiFi):
void conecta_wifi() {
// Inicio del proceso de conexión a la red WiFi:
delay(10);
Serial.print("Conectando a la red WiFi");
WiFi.mode(WIFI_STA); // Modo estación, en el microcontrolador ESP32 busca y se conecta a un punto de acceso WiFi.
WiFi.begin(wifi_ssid, wifi_contra); // Inicia la conexión de la red WiFi especificada, según las credenciales indicadas.
// Espera a la conexión de la red WiFi:
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
// Mensaje de éxito en la conexión a la red WiFi e información sobre la dirección IP:
Serial.println(" ---> CONECTADO");
Serial.print("Nombre de red: ");
Serial.println(wifi_ssid);
Serial.print("Dirección IP: ");
Serial.println(WiFi.localIP());
delay(4000);
}
// FUNCIÓN conecta_mqtt (CONEXIÓN AL BROKER MQTT):
void conecta_mqtt() {
// Bucle en ejecución hasta que se conecte al broker MQTT:
while (!mqtt_cliente.connected()) {
// Inicio del proceso de conexión al broker MQTT:
Serial.print("Conectando al broker MQTT");
// Generación de un nombre de identificación del cliente MQTT:
String id_cliente = "NombreIdCliente-";
id_cliente += String(random(0xffff), HEX);
// Intento de conexión con el broker MQTT.
// En caso afirmativo, se indica el nombre del servidor MQTT, se suscribe al tema y se imprime por pantalla:
if (mqtt_cliente.connect(id_cliente.c_str(), mqtt_usuario, mqtt_llave)) {
Serial.println(" ---> CONECTADO");
Serial.print("Nombre del servidor: ");
Serial.println(mqtt_servidor);
mqtt_cliente.subscribe(subtopic_temp);
mqtt_cliente.subscribe(subtopic_acel_x);
mqtt_cliente.subscribe(subtopic_acel_y);
mqtt_cliente.subscribe(subtopic_acel_z);
Serial.println("Suscrito a los temas: Temperatura, Acelerómetro X, Acelerómetro Y y Acelerómetro Z");
delay(4000);
}
// En caso negativo, se indica el estado actual del broker MQTT y se espera 5 segundos para intentarlo de nuevo:
else {
Serial.println("");
Serial.print("Conexión fallida, estado actual del broker MQTT: ");
Serial.println(mqtt_cliente.state());
Serial.println("Nuevo intento en 5 segundos");
delay(5000);
}
}
}
void leer_mpu(float &lect_temp, float &lect_acel_x, float &lect_acel_y, float &lect_acel_z) {
// Selección del sensor MPU6050:
digitalWrite(AD0, LOW);
// Lectura de los parámetros actualizados de temperatura y aceleración:
mpu.update();
lect_temp = mpu.getTemp();
lect_acel_x = mpu.getAccX();
lect_acel_y = mpu.getAccY();
lect_acel_z = mpu.getAccZ();
// Deselección del sensor MPU6050:
digitalWrite(AD0, HIGH);
}
void imprimir_lecturas(float lect_temp, float lect_acel_x, float lect_acel_y, float lect_acel_z) {
Serial.println("===========================================================");
Serial.print(F("Temperatura = "));
Serial.print(lect_temp, 1);
Serial.print(F("°C, Acelerómetro = ("));
Serial.print(lect_acel_x, 2);
Serial.print(", ");
Serial.print(lect_acel_y, 2);
Serial.print(", ");
Serial.print(lect_acel_z, 2);
Serial.println(") g");
}
void publicar_lecturas(float lect_temp, float lect_acel_x, float lect_acel_y, float lect_acel_z) {
mqtt_cliente.publish(subtopic_temp, String(lect_temp, 1).c_str());
mqtt_cliente.publish(subtopic_acel_x, String(lect_acel_x, 2).c_str());
mqtt_cliente.publish(subtopic_acel_y, String(lect_acel_y, 2).c_str());
mqtt_cliente.publish(subtopic_acel_z, String(lect_acel_z, 2).c_str());
}