// ================================================================
// CENTINELA LoRa — FIRMWARE: NODO EMISOR (E01)
// Rol: Monitoreo de inclinación y humedad + Alerta Temprana
// ================================================================
#include <SPI.h>
#include <LoRa.h>
#include <Adafruit_MPU6050.h>
#include <Adafruit_Sensor.h>
#include <Wire.h>
// --- Configuración de Red (Según Guía Técnica) ---
#define NODO_ID 1 // ID de este nodo [cite: 87]
#define DESTINO_ID 101 // ID del Repetidor (R01) [cite: 88]
// --- Pines de Hardware (Según Tabla de Conexiones) ---
#define PIN_POT_HUM 34 // Potenciómetro (Simula Humedad)
#define PIN_LED_ALR 25 // LED de Alerta
#define PIN_SDA 21 // I2C SDA
#define PIN_SCL 22 // I2C SCL
// --- Umbrales de Alerta (Según Documento de Proyecto) ---
#define UMBRAL_HUM 90 // Alerta si Humedad > 90% [cite: 35]
#define UMBRAL_INC 2.0 // Alerta si Inclinación > 2 grados [cite: 20]
Adafruit_MPU6050 mpu;
void setup() {
Serial.begin(115200);
pinMode(PIN_LED_ALR, OUTPUT);
Serial.println("\n--- CENTINELA LORA: DESPERTANDO ---");
// 1. Inicializar I2C y MPU6050
Wire.begin(PIN_SDA, PIN_SCL);
if (!mpu.begin()) {
Serial.println("[ERROR] No se encontró el sensor MPU6050");
}
// 2. Inicializar LoRa (Pines estándar para simulación ESP32)
LoRa.setPins(18, 23, 26);
if (!LoRa.begin(915E6)) {
Serial.println("[AVISO] Hardware LoRa no detectado (Normal en Wokwi)");
}
}
void loop() {
// --- LECTURA DE SENSORES ---
// Humedad: Mapeo del potenciómetro (0-4095) a porcentaje (0-100)
int valorPot = analogRead(PIN_POT_HUM);
int humedad = map(valorPot, 0, 4095, 0, 100);
// Inclinación: Lectura del acelerómetro
sensors_event_t a, g, temp;
mpu.getEvent(&a, &g, &temp);
float incX = abs(a.acceleration.x); // Usamos X como eje de inclinación principal
// --- LÓGICA DE ALERTA ---
bool alerta = (humedad >= UMBRAL_HUM || incX >= UMBRAL_INC);
Serial.printf("[LECTURA] INC: %.2f | HUM: %d%% | ", incX, humedad);
if (alerta) {
digitalWrite(PIN_LED_ALR, HIGH);
Serial.println("ESTADO: !ALERTA CRITICA!"); // [cite: 113]
// Generar el Payload (Formato: FROM,TO,INC,HUM,ALR)
String payload = "FROM:" + String(NODO_ID) +
",TO:" + String(DESTINO_ID) +
",INC:" + String(incX) +
",HUM:" + String(humedad) +
",ALR:1";
enviarDatos(payload);
} else {
digitalWrite(PIN_LED_ALR, LOW);
Serial.println("ESTADO: NORMAL");
}
Serial.println("[SLEEP] Próximo ciclo en 8 segundos..."); // Tiempo reducido para demo
delay(8000);
}
void enviarDatos(String mensaje) {
// --- EL TRUCO PARA WOKWI ---
// Imprimimos el mensaje ANTES de intentar enviarlo por radio
Serial.println("--------------------------------------------------");
Serial.print("[TX] Payload enviado -> ");
Serial.println(mensaje); // <--- COPIA ESTA LÍNEA PARA EL GATEWAY [cite: 116, 117]
Serial.println("--------------------------------------------------");
// Intento de envío real (fallará en simulación pero el código sigue)
LoRa.beginPacket();
LoRa.print(mensaje);
LoRa.endPacket();
}