/*---Librerías---*/
#include <WiFi.h> //habilita la funcionalidad de Wi-Fi
#include <PubSubClient.h> //permite la comunicación a travez del protocolo MQTT (ejm. mqtt_client.loop();)
#include <Wire.h> //la comunicación con dispositivos a través del protocolo I2C
#include <MPU6050_light.h> //sirve como una interfaz para facilitar la comunicación con el sensor MPU6050
/*---Variables---*/
#define AD0 16 //definición pin 16
MPU6050 mpu(Wire); //inicializa el objeto I2C para establecer la comunicación con el sensor MPU6050
float temp; //temperatura
float a_x; //aceleración en X
float a_y; //aceleración en Y
float a_z; //aceleración en Z
unsigned long t_act; //tiempo actual
unsigned long t_pre = millis(); //temporizador en milisegundos
const unsigned long t_read = 5000; //tiempo se tomará una lectura
/*---Configuración de red WIFI---*/
const char* wifi_ssid = "Wokwi-GUEST"; //nombre de la red predefinida
const char* wifi_pass = ""; //contraseña en blanco predefinida
WiFiClient wifi_cl; //creación del cliente para conectarse a una red WIFI
PubSubClient mqtt_client(wifi_cl); //inicializa un cliente MQTT para la comunicación
/*---Configuración de Adafruit IO---*/
const char* mqtt_server = "io.adafruit.com"; //página adafruit
const char* mqtt_user = "jeyko"; //nombre de usuario
const int mqtt_port = 1883; //puerto MQTT por defecto 1883
const char* mqtt_pass = "aio_AWZz40vDgvM2BQm3vNxqh7oh7B8R"; //llave de acceso
const char* adafruit_t = "jeyko/feeds/unir2024.temp"; //categoría temperatura
const char* adafruit_a_x = "jeyko/feeds/unir2024.a_x"; //categoría aceleración en X
const char* adafruit_a_y = "jeyko/feeds/unir2024.a_y"; //categoría aceleración en Y
const char* adafruit_a_z = "jeyko/feeds/unir2024.a_z"; //categoría aceleración en Z
/*---Inicialización funciones---*/
void conn_wifi(); //conexión WIFI
void conn_mqtt(); //conexión MQTT
void read_mpu(float &read_temp, float &read_a_x, float &read_a_y, float &read_a_z); //lectura MPU
void print_screen(float read_temp, float read_a_x, float read_a_y, float read_a_z); //impresión por pantalla
void print_adafruit(float read_temp, float read_a_x, float read_a_y, float read_a_z); //impresión plataforma adafruit
/*---Función de inicialización---*/
void setup() {
Serial.begin(115200); //configura la velocidad de la comunicación a una velocidad de 115200 bits por segundo
Wire.begin(); //configura y habilita el bus I2C en el microcontrolador (pines por defecto: SDA = 21 y SCL = 22)
// Inicialización del pin AD0
pinMode(AD0, OUTPUT); //configura el pin AD0 para que actúe como una salida digital
digitalWrite(AD0, HIGH); //pone el pin AD0 en un estado alto (activo)
// Inicialización del sensor MPU6050:
Serial.print("Inicializando el sensor MPU6050"); //imprime en pantalla información
while (!mpu.begin()) { //ejecuta hasta que la inicialización sea exitosa
Serial.print("."); //indica que espera la inicialización ha fallado y se imprime un punto
delay(500); //espera 500 milisegundos antes de intentar inicializar el sensor nuevamente
}
Serial.println(" ---> Sensor activado"); //imprime en pantalla información
delay(2000); //espera 2000 milisegundos después de inicializar el sensor
conn_wifi(); //llama a la función para establecer una conexión WIFI
mqtt_client.setServer(mqtt_server, mqtt_port); //configura el servidor MQTT
conn_mqtt(); //llama a la función para establecer una conexión con un servidor MQTT
}
/*---Función principal de configuración---*/
void loop() {
if (WiFi.status() != WL_CONNECTED){ //verifica si el dispositivo está conectado a la red WIFI, sino intenta reconectarse al WIFI
conn_wifi(); //llama a la función para establecer una conexión WIFI
conn_mqtt(); //llama a la función para establecer una conexión con un servidor MQTT
}
else if (!mqtt_client.connected()) { //verifica si el cliente MQTT no está conectado
conn_mqtt(); //llama a la función para establecer una conexión con un servidor MQTT
}
mqtt_client.loop(); //mantiene la conexión activa con el servidor MQTT, gestionando las reconexiones automáticas si la conexión se pierde
t_act = millis(); //obtiene el tiempo actual que ha transcurrido desde que el programa loop() comenzó a ejecutarse
if(t_act - t_pre >= t_read) { //comprueba si ha pasado un cierto intervalo de tiempo desde que se ejecutó el programa
t_pre = t_act; //actualiza t_pre con el valor actual de millis()
read_mpu(temp, a_x, a_y, a_z); //llama a la función para leer datos del sensor MPU
print_screen(temp, a_x, a_y, a_z); //llama a la función para mostrar datos del sensor MPU
print_adafruit(temp, a_x, a_y, a_z); //llama a la función para publicar los datos del sensor MPU en adafruit
}
}
/*---Función de conexion WIFI---*/
void conn_wifi() {
delay(10); //espera 10 milisegundos para iniciar conexión a la red WIFI
Serial.print("Iniciando conexión a la red WIFI"); //imprime en pantalla información
WiFi.mode(WIFI_STA); // modo estación donde el ESP32 busca y se conecta a un punto de acceso WIFI existente
WiFi.begin(wifi_ssid, wifi_pass); //inicia el proceso de conexión usando credenciales (nombre de red, contraseña)
while (WiFi.status() != WL_CONNECTED) { //verifica el estado de la conexión WIFI mientras el dispositivo no esté conectado
delay(500); //espera 500 milisegundos para colver a verificar el estado de la conexión
Serial.print("."); //indica que espera la conexión y se imprime un punto
}
Serial.println(" ---> Estado conectado"); //imprime en pantalla información y salto de línea
Serial.print("Nombre de la red: "); //imprime en pantalla información
Serial.println(wifi_ssid); //imprime nombre de red y salto de línea
Serial.print("Dirección IP: "); //imprime en pantalla información
Serial.println(WiFi.localIP()); //imprime dirección IP y salto de línea
delay(4000); //espera 4000 milisegundos para volver a imprimir los datos de conexión
}
/*---Función de conexion al servidor MQTT---*/
void conn_mqtt() {
while (!mqtt_client.connected()) { //ejecuta repetidamente mientras el cliente MQTT no esté conectado
Serial.print("Conectando al servidor MQTT"); //imprime en pantalla información
String id_client = "Nombre_Id_cliente-"; //declara variable para nombre del cliente MQTT
id_client += String(random(0xffff), HEX); //genera un número aleatorio en formato hexadecimal y concatena con la variable anterior
if (mqtt_client.connect(id_client.c_str(), mqtt_user, mqtt_pass)) { //intenta conectar el cliente al servidor MQTT, retorna true si la conexión es exitosa
Serial.println(" ---> Conexión exitosa"); //imprime en pantalla información
Serial.print("Nombre del servidor MQTT: "); //imprime en pantalla información
Serial.println(mqtt_server); //imprime nombre del servidor MQTT y salto de línea
mqtt_client.subscribe(adafruit_t); //suscribir a un tema relacionado con datos de temperatura en la plataforma adafruit
mqtt_client.subscribe(adafruit_a_x); //suscribir a un tema relacionado con datos de acelerómetro X en la plataforma adafruit
mqtt_client.subscribe(adafruit_a_y); //suscribir a un tema relacionado con datos de acelerómetro Y en la plataforma adafruit
mqtt_client.subscribe(adafruit_a_z); //suscribir a un tema relacionado con datos de acelerómetro Z en la plataforma adafruit
Serial.println("Se ha suscrito a los temas: Temperatura, Acelerómetro X, Acelerómetro Y, Acelerómetro Z"); //imprime en pantalla información
delay(4000); //espera 4000 milisegundos para volver a imprimir los datos de conexión
}
// En el caso que falle la conexión
else {
Serial.println(""); //imprime en pantalla información
Serial.print("La conexión ha fallado, el estado actual del servidor MQTT es: "); //imprime en pantalla información
Serial.println(mqtt_client.state()); //imprime el estado actual del cliente MQTT y salto de línea
Serial.println("Intentando..."); //imprime en pantalla información
delay(5000); //espera 5000 milisegundos para volver a intentar la conexión
}
}
}
/*---Función de lectura de valores de temperatura y aceleración del sensor MPU6050---*/
void read_mpu(float &read_temp, float &read_a_x, float &read_a_y, float &read_a_z) {
digitalWrite(AD0, LOW); //selecciona el sensor MPU6050 activando su línea de selección y habilita para la comunicación
mpu.update(); //actualiza los valores internos del sensor MPU6050
read_temp = mpu.getTemp(); //lee la temperatura actual del sensor y la almacena en la variable
read_a_x = mpu.getAccX(); //lee la aceleración en el eje X y la almacena en la variable
read_a_y = mpu.getAccY(); //lee la aceleración en el eje Y y la almacena en la variable
read_a_z = mpu.getAccZ(); //lee la aceleración en el eje Z y la almacena en la variable
digitalWrite(AD0, HIGH); //deselecciona el sensor MPU6050 desactivando su línea de selección
}
/*---Función que imprime en el monitor una serie los valores de temperatura y aceleración leídos del sensor---*/
void print_screen(float read_temp, float read_a_x, float read_a_y, float read_a_z) {
Serial.println("=|=|=|=|=|=|=|=|=|=|=|=|=|=|=|=|=|=|=|=|=|=|=|=|=|=|=|=|=|=|=|=");
Serial.print(F("Temperatura = ")); //imprime en pantalla información
Serial.print(read_temp, 1); //imprime el valor de la temperatura con un decimal
Serial.print(F("°C, Acelerómetro = (")); //imprime en pantalla información
Serial.print(read_a_x, 2); //imprime la componente X de la aceleración con dos decimales
Serial.print(", "); //imprime coma
Serial.print(read_a_y, 2); //imprime la componente Y de la aceleración con dos decimales
Serial.print(", "); //imprime coma
Serial.print(read_a_z, 2); //imprime la componente X de la aceleración con dos decimales
Serial.println(") g"); //imprime en pantalla información
}
/*---Función que publica los datos de los sensores en la plataforma Adafruit IO---*/
void print_adafruit(float read_temp, float read_a_x, float read_a_y, float read_a_z){
///utiliza el cliente MQTT para publicar los datos en los feeds adafruit_t, adafruit_a_x, adafruit_a_y, adafruit_a_z, de adafruit
mqtt_client.publish(adafruit_t, String(read_temp, 1).c_str()); //convierte la lectura de temperatura a una cadena de caracteres con 1 decimal
mqtt_client.publish(adafruit_a_x, String(read_a_x, 2).c_str()); //convierte las lecturas de aceleración en X a cadenas de caracteres con 2 decimales
mqtt_client.publish(adafruit_a_y, String(read_a_y, 2).c_str()); //convierte las lecturas de aceleración en Y a cadenas de caracteres con 2 decimales
mqtt_client.publish(adafruit_a_z, String(read_a_z, 2).c_str()); //convierte las lecturas de aceleración en Z a cadenas de caracteres con 2 decimales
}