Principiante20 min

ESP32 + Sensor de humedad resistivo

Código completo y diagrama de conexión para enviar lecturas de humedad del suelo a Bloomit por WiFi, con un LED como indicador visual de cada lectura.

Hardware necesario

  • ESP32 DevKit V1 (o cualquier WROOM-32)
  • Sensor de humedad resistivo YL-69 o FC-28
  • LED de 5mm (cualquier color)
  • Resistencia de 220Ω
  • Protoboard y cables jumper
  • Cable micro-USB
  • Arduino IDE con soporte ESP32

Cómo funciona el circuito

El sensor resistivo mide la humedad del suelo como una variación de resistencia eléctrica: cuanta más humedad, menor resistencia, mayor voltaje en el pin analógico. El ESP32 lee ese voltaje con su ADC de 12 bits (valores de 0 a 4095) y lo convierte a porcentaje para enviarlo a Bloomit.

El LED sirve como indicador visual sin necesidad de tener la PC conectada: un parpadeo al leer, tres parpadeos rápidos cuando el dato se envió correctamente, LED encendido un segundo si hay error de red.

Diagrama de conexión

GNDESP32DevKit V1 / WROOM-323.3VGNDGPIO 34GPIO 2Sensor HumedadResistivo (YL-69 / FC-28)SondasVCCGNDAO220ΩLEDVCCGNDSeñal analógicaControl LED
ESP32ComponentePinCable
3.3VSensor YL-69VCCRojo
GNDSensor YL-69GNDNegro
GPIO 34Sensor YL-69AO (Analog Out)Amarillo
GPIO 2Resistencia 220Ω →Ánodo LED (+)Azul
GNDCátodo LED (−)Negro

Nota: el sensor YL-69 funciona a 3.3V y 5V. Usamos 3.3V para no exceder el límite de los pines ADC del ESP32. El pin DO (digital out) no se conecta en este tutorial.

Obtener el device token

Antes de cargar el código, necesitás el token del dispositivo. Con tu cuenta en bloomit.app, registrá el dispositivo desde el panel o via API:

# 1. Login → obtenés el userToken
curl -X POST https://user.api.bloomit.app/auth/login \
  -H "Content-Type: application/json" \
  -d '{"email":"tu@email.com","password":"tupassword"}'

# 2. Registrar dispositivo → obtenés el deviceToken
curl -X POST https://device.api.bloomit.app/register \
  -H "Authorization: Bearer <userToken>" \
  -H "Content-Type: application/json" \
  -d '{"name":"ESP32 Maceta Ventana","metadata":{"location":"living"}}'

# Respuesta: { "deviceToken": "eyJhbGci...", "deviceId": "abc123" }
# Guardá el deviceToken — lo pegás en el código

Código completo

Copiá este sketch en Arduino IDE. Reemplazá SSID, PASSWORD y DEVICE_TOKEN con tus datos.

#include <WiFi.h>
#include <HTTPClient.h>
#include <ArduinoJson.h>

// ── Configuración ──────────────────────────────────────
const char* SSID         = "tu_red_wifi";
const char* PASSWORD     = "tu_password";
const char* DEVICE_TOKEN = "eyJhbGci..."; // tu deviceToken de bloomit.app

const int LED_PIN    = 2;   // GPIO 2 (LED integrado en muchas placas)
const int SENSOR_PIN = 34;  // GPIO 34 — solo lectura analógica (ADC1)

// Calibración del sensor resistivo
// Medí el valor en seco (sensor en aire) y en húmedo (sensor en agua)
const int SENSOR_DRY = 4095;  // valor en aire → 0% humedad
const int SENSOR_WET = 1500;  // valor en agua → 100% humedad

// ── Setup ──────────────────────────────────────────────
void setup() {
  Serial.begin(115200);
  pinMode(LED_PIN, OUTPUT);

  // Señal de inicio: 2 parpadeos largos
  for (int i = 0; i < 2; i++) {
    digitalWrite(LED_PIN, HIGH); delay(500);
    digitalWrite(LED_PIN, LOW);  delay(300);
  }

  Serial.print("Conectando a WiFi");
  WiFi.begin(SSID, PASSWORD);
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.println(" OK — IP: " + WiFi.localIP().toString());

  // WiFi conectado: 3 parpadeos rápidos
  for (int i = 0; i < 3; i++) {
    digitalWrite(LED_PIN, HIGH); delay(100);
    digitalWrite(LED_PIN, LOW);  delay(100);
  }
}

// ── Lectura del sensor ─────────────────────────────────
int readHumidity() {
  // Promediamos 5 lecturas para estabilizar el valor
  long sum = 0;
  for (int i = 0; i < 5; i++) {
    sum += analogRead(SENSOR_PIN);
    delay(10);
  }
  int raw = sum / 5;
  int humidity = map(raw, SENSOR_DRY, SENSOR_WET, 0, 100);
  return constrain(humidity, 0, 100);
}

// ── Envío a Bloomit ────────────────────────────────────
bool sendToBloomit(int humidity) {
  if (WiFi.status() != WL_CONNECTED) {
    WiFi.reconnect();
    delay(3000);
    return false;
  }

  HTTPClient http;
  http.begin("https://device.api.bloomit.app/sense");
  http.addHeader("Authorization", "Bearer " + String(DEVICE_TOKEN));
  http.addHeader("Content-Type", "application/json");

  StaticJsonDocument<128> doc;
  doc["sensorType"] = "soil_humidity";
  doc["value"]      = humidity;

  String body;
  serializeJson(doc, body);

  int code = http.POST(body);
  http.end();

  Serial.printf("POST /sense → %d | humedad: %d%%\n", code, humidity);
  return code == 200;
}

// ── Loop ───────────────────────────────────────────────
void loop() {
  // Parpadeo simple: iniciando lectura
  digitalWrite(LED_PIN, HIGH); delay(200);
  digitalWrite(LED_PIN, LOW);

  int humidity = readHumidity();
  bool ok = sendToBloomit(humidity);

  if (ok) {
    // 3 parpadeos rápidos: dato enviado correctamente
    for (int i = 0; i < 3; i++) {
      digitalWrite(LED_PIN, HIGH); delay(100);
      digitalWrite(LED_PIN, LOW);  delay(100);
    }
  } else {
    // LED encendido 1 s: error de red
    digitalWrite(LED_PIN, HIGH); delay(1000);
    digitalWrite(LED_PIN, LOW);
    Serial.println("Error al enviar — reintentando en próximo ciclo");
  }

  // Esperar 1 hora antes de la siguiente lectura
  // Con plan free (25 lecturas/dispositivo/día) una por hora es el límite ideal
  delay(3600000UL);
}

Señales del LED

  • 2 parpadeos lentos (500ms)
    Inicio del setupEl programa arrancó correctamente
  • 3 parpadeos rápidos (100ms) al inicio
    WiFi conectadoLa red está lista
  • 1 parpadeo (200ms) antes de cada envío
    Leyendo sensorCapturando la lectura analógica
  • 3 parpadeos rápidos tras lectura
    Envío exitosoEl dato llegó a Bloomit (HTTP 200)
  • LED 1 segundo fijo
    Error de redNo se pudo conectar o el POST falló

Calibrar el sensor

Los sensores resistivos varían entre unidades. Para obtener lecturas precisas, calibrá con tu sensor específico:

  1. Cargá el sketch con los valores por defecto (DRY=4095, WET=1500).
  2. Abrí el Monitor Serial (115200 baud). Dejá el sensor en el aire y anotá el valor raw → ese es tu SENSOR_DRY.
  3. Sumergí las sondas completamente en agua y anotá el nuevo valor raw → ese es tu SENSOR_WET.
  4. Actualizá las constantes en el código y volvé a cargar.

Para depurar, agregá esta línea dentro de readHumidity() antes del return:

Serial.printf("raw: %d  →  humedad: %d%%\n", raw, humidity);

Cargar a la placa

  1. En Arduino IDE, seleccioná la placa: Tools → Board → ESP32 Arduino → ESP32 Dev Module.
  2. Seleccioná el puerto COM correcto en Tools → Port.
  3. Instalá las librerías si no las tenés: ArduinoJson de Benoit Blanchon (Library Manager).
  4. Hacé click en Upload (→). Si el ESP32 no arranca la carga, presioná el botón BOOT mientras aparece "Connecting…".
  5. Una vez cargado, el LED parpadea 2 veces y luego 3 veces cuando conecta al WiFi.

Ver los datos en Bloomit

Abrí bloomit.app, navegá a tu dispositivo y vas a ver la lectura más reciente de soil_humidity y el gráfico de tendencia de los últimos 7 días. Si asignaste una especie de planta al dispositivo, el panel muestra el estado de salud en colores según los umbrales recomendados.

¿Te trabaste en algún paso?

Sumate al grupo de Telegram de Bloomit: ahí te ayudamos a resolver errores de cableado, compilación o conexión. Hay gente armando los mismos proyectos que vos.

Unirme al grupo

Bloomit

¿Todo funcionando? Abrí el panel

Registrá tu cuenta gratis, conectá el dispositivo y los datos aparecen en tiempo real. Hardware Bloomit listo para usar en bloomit.com.ar.