// 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óncon dispositivos a través del protocolo I2C.
#include <MPU6050_light.h> // Proporciona funciones específicas para gobernar el 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_min = 5000; // Periodo de tiempo mínimo entre muestras.
// 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 = "PER9205_Grupo1";
const char* mqtt_llave = "aio_atNO37LRCKYZPAcnEkAAzZWBaDzQ";
// Temas del proyecto:
const char* subtopic_temp = "PER9205_Grupo1/feeds/temp";
const char* subtopic_acel_x = "PER9205_Grupo1/feeds/acel-x";
const char* subtopic_acel_y = "PER9205_Grupo1/feeds/acel-y";
const char* subtopic_acel_z = "PER9205_Grupo1/feeds/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();
float leer_mpu();
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.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 es 1883 para MQTT).
conecta_mqtt(); // Se ejecuta la función conecta_mqtt para inicializar la conexión con el broker 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_CONNECTION_LOST){
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.
// Se verifica el tiempo transcurrido desde la última lectura y, en caso que sea igual o superior al mínimo indicado en la declaración de variables,
// obtiene las lecturas del sensor, las imprime por consola y las publica a los temas que corresponda:
tiempo_actual = millis();
if(tiempo_actual - tiempo_previo >= frecuencia_muestreo_min) {
tiempo_previo = tiempo_actual;
temp, acel_x, acel_y, acel_z = leer_mpu();
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 que 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) {
;
}
// 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 a los temas y se imprimen 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, Aceleración X, Aceleración Y y Aceleración 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);
}
}
}
// FUNCIÓN leer_mpu (LECTURA DEL SENSOR):
float leer_mpu() {
// Selección del sensor MPU6050:
digitalWrite(AD0, LOW);
// Lectura de los parámetros actualizados de temperatura y aceleración:
mpu.update();
temp = mpu.getTemp();
acel_x = mpu.getAccX();
acel_y = mpu.getAccY();
acel_z = mpu.getAccZ();
// Deselección del sensor MPU6050:
digitalWrite(AD0, HIGH);
// Devolución de valores:
return temp, acel_x, acel_y, acel_z;
}
// FUNCIÓN imprimir_lecturas (IMPRESIÓN DE LAS LECTURAS POR CONSOLA):
void imprimir_lecturas(float lect_temp, float lect_acel_x, float lect_acel_y, float lect_acel_z) {
Serial.println("===========================================================");
Serial.print(F("Temperatura = "));
// Impresión de la temperatura, con 1 decimal:
Serial.print(lect_temp, 1);
Serial.print(F("°C, Aceleración = ("));
// Impresión de las diferentes fuerzas que componen la aceleración, con 2 decimales:
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");
}
// FUNCIÓN publicar_lecturas (PUBLICACIÓN DE LAS LECTURAS A LOS TEMAS CORRESPONDIENTES):
void publicar_lecturas(float lect_temp, float lect_acel_x, float lect_acel_y, float lect_acel_z) {
// Publicación de los datos convertidos a cadena de caracteres en formato C, con los decimales que se requiera en cada caso:
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());
}