DCDevicecamp
Menú

ESP32 + DHT22, enviando datos en minutos.

Receta Arduino completa para DHT22 con MQTT/TLS. Genera la credencial, configura el Wi-Fi y flashea la placa.

1. Instala las librerías

Instala “esp32 by Espressif Systems”, “PubSubClient by Nick O’Leary” y “DHT sensor library” desde Arduino IDE. Acepta las dependencias que solicite.

2. Conecta el sensor

El sketch usa GPIO 4 para datos. Cambia DHT_PIN si tu placa utiliza otro pin y sigue el pinout de tu módulo concreto.

Métricas enviadas: temperature, humidity

3. Genera una credencial real

Crea un dispositivo en Devicecamp y elige ESP32 Arduino. Selecciona este sensor antes de copiar o descargar el sketch; la versión generada incluye la identidad y los topics MQTT exactos.

4. Revisa la plantilla pública

MQTT_CLIENT_ID, MQTT_USERNAME y MQTT_PASSWORD son marcadores en esta página pública.

// Devicecamp ESP32 MQTT/TLS starter
// Install "esp32 by Espressif Systems" and "PubSubClient by Nick O'Leary".
// Also install "DHT sensor library" and its prompted dependencies.
// This file contains a live device credential. Do not commit or share it.

#include <WiFi.h>
#include <WiFiClientSecure.h>
#include <PubSubClient.h>
#include <time.h>
#include <math.h>
#include <DHT.h>

const char WIFI_SSID[] = "YOUR_WIFI_SSID";
const char WIFI_PASSWORD[] = "YOUR_WIFI_PASSWORD";

const char MQTT_HOST[] = "mqtt.devicecamp.app";
const uint16_t MQTT_PORT = 8883;
const char MQTT_CLIENT_ID[] = "MQTT_CLIENT_ID";
const char MQTT_USERNAME[] = "MQTT_USERNAME";
const char MQTT_PASSWORD[] = "MQTT_PASSWORD";
const char TELEMETRY_TOPIC[] = "v1/devices/DEVICE_ID/telemetry";
const char STATUS_TOPIC[] = "v1/devices/DEVICE_ID/status";

const char DEVICECAMP_CA[] PROGMEM = R"EOF(
-----BEGIN CERTIFICATE-----
MIIFazCCA1OgAwIBAgIRAIIQz7DSQONZRGPgu2OCiwAwDQYJKoZIhvcNAQELBQAwTzELMAkGA1UE
BhMCVVMxKTAnBgNVBAoTIEludGVybmV0IFNlY3VyaXR5IFJlc2VhcmNoIEdyb3VwMRUwEwYDVQQD
EwxJU1JHIFJvb3QgWDEwHhcNMTUwNjA0MTEwNDM4WhcNMzUwNjA0MTEwNDM4WjBPMQswCQYDVQQG
EwJVUzEpMCcGA1UEChMgSW50ZXJuZXQgU2VjdXJpdHkgUmVzZWFyY2ggR3JvdXAxFTATBgNVBAMT
DElTUkcgUm9vdCBYMTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAK3oJHP0FDfzm54r
Vygch77ct984kIxuPOZXoHj3dcKi/vVqbvYATyjb3miGbESTtrFj/RQSa78f0uoxmyF+0TM8ukj1
3Xnfs7j/EvEhmkvBioZxaUpmZmyPfjxwv60pIgbz5MDmgK7iS4+3mX6UA5/TR5d8mUgjU+g4rk8K
b4Mu0UlXjIB0ttov0DiNewNwIRt18jA8+o+u3dpjq+sWT8KOEUt+zwvo/7V3LvSye0rgTBIlDHCN
Aymg4VMk7BPZ7hm/ELNKjD+Jo2FR3qyHB5T0Y3HsLuJvW5iB4YlcNHlsdu87kGJ55tukmi8mxdAQ
4Q7e2RCOFvu396j3x+UCB5iPNgiV5+I3lg02dZ77DnKxHZu8A/lJBdiB3QW0KtZB6awBdpUKD9jf
1b0SHzUvKBds0pjBqAlkd25HN7rOrFleaJ1/ctaJxQZBKT5ZPt0m9STJEadao0xAH0ahmbWnOlFu
hjuefXKnEgV4We0+UXgVCwOPjdAvBbI+e0ocS3MFEvzG6uBQE3xDk3SzynTnjh8BCNAw1FtxNrQH
usEwMFxIt4I7mKZ9YIqioymCzLq9gwQbooMDQaHWBfEbwrbwqHyGO0aoSCqI3Haadr8faqU9GY/r
OPNk3sgrDQoo//fb4hVC1CLQJ13hef4Y53CIrU7m2Ys6xt0nUW7/vGT1M0NPAgMBAAGjQjBAMA4G
A1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBR5tFnme7bl5AFzgAiIyBpY
9umbbjANBgkqhkiG9w0BAQsFAAOCAgEAVR9YqbyyqFDQDLHYGmkgJykIrGF1XIpu+ILlaS/V9lZL
ubhzEFnTIZd+50xx+7LSYK05qAvqFyFWhfFQDlnrzuBZ6brJFe+GnY+EgPbk6ZGQ3BebYhtF8GaV
0nxvwuo77x/Py9auJ/GpsMiu/X1+mvoiBOv/2X/qkSsisRcOj/KKNFtY2PwByVS5uCbMiogziUwt
hDyC3+6WVwW6LLv3xLfHTjuCvjHIInNzktHCgKQ5ORAzI4JMPJ+GslWYHb4phowim57iaztXOoJw
TdwJx4nLCgdNbOhdjsnvzqvHu7UrTkXWStAmzOVyyghqpZXjFaH3pO3JLF+l+/+sKAIuvtd7u+Nx
e5AW0wdeRlN8NwdCjNPElpzVmbUq4JUagEiuTDkHzsxHpFKVK7q4+63SM1N95R1NbdWhscdCb+ZA
JzVcoyi3B43njTOQ5yOf+1CceWxG1bQVs5ZufpsMljq4Ui0/1lvh+wjChP4kqKOJ2qxq4RgqsahD
YVvTH9w7jXbyLeiNdd8XM2w9U/t7y0Ff/9yi0GE44Za4rF2LN9d11TPAmRGunUHBcnWEvgJBQl9n
JEiU0Zsnvgc/ubhPgXRR4Xq37Z0j4r7g1SgEEzwxA57demyPxgcYxn/eR44/KJ4EBs+lVDR3veyJ
m+kXQ99b21/+jh5Xos1AnX5iItreGCc=
-----END CERTIFICATE-----
)EOF";

WiFiClientSecure tls;
PubSubClient mqtt(tls);
const uint8_t DHT_PIN = 4;  // Change this to the GPIO used by your board.
DHT dht(DHT_PIN, DHT22);

unsigned long lastPublishAt = 0;
unsigned long nextReconnectAt = 0;
unsigned long reconnectDelayMs = 1000;
const unsigned long PUBLISH_INTERVAL_MS = 60000;

void connectWiFi() {
  WiFi.mode(WIFI_STA);
  WiFi.setAutoReconnect(true);
  WiFi.begin(WIFI_SSID, WIFI_PASSWORD);
  Serial.print("Connecting to Wi-Fi");
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.println(" connected");
}

void syncClock() {
  // Certificate validation needs a reasonably correct clock.
  configTime(0, 0, "pool.ntp.org", "time.nist.gov");
  Serial.print("Synchronizing clock");
  time_t now = time(nullptr);
  while (now < 1700000000) {
    delay(500);
    Serial.print(".");
    now = time(nullptr);
  }
  Serial.println(" ready");
}

void connectMQTT() {
  if (mqtt.connected() || millis() < nextReconnectAt) return;

  const bool connected = mqtt.connect(
    MQTT_CLIENT_ID,
    MQTT_USERNAME,
    MQTT_PASSWORD,
    STATUS_TOPIC,
    1,
    true,
    "{\"status\":\"offline\"}"
  );

  if (connected) {
    Serial.println("MQTT connected");
    mqtt.publish(STATUS_TOPIC, "{\"status\":\"online\"}", true);
    reconnectDelayMs = 1000;
    return;
  }

  Serial.printf("MQTT failed, state=%d; retry in %lu ms\n",
    mqtt.state(), reconnectDelayMs);
  nextReconnectAt = millis() + reconnectDelayMs;
  reconnectDelayMs = min(reconnectDelayMs * 2, 60000UL);
}

void publishReading() {
  const float temperature = dht.readTemperature();
  const float humidity = dht.readHumidity();
  if (isnan(temperature) || isnan(humidity)) {
    Serial.println("DHT22 read failed");
    return;
  }
  const String localIP = WiFi.localIP().toString();
  char payload[192];
  snprintf(payload, sizeof(payload),
    "{\"metrics\":{\"temperature\":%.1f,\"humidity\":%.1f},\"metadata\":{\"local_ip\":\"%s\"}}",
    temperature, humidity, localIP.c_str());

  if (mqtt.publish(TELEMETRY_TOPIC, payload)) {
    Serial.printf("Published: %s\n", payload);
  } else {
    Serial.println("Publish failed");
  }
}

void setup() {
  Serial.begin(115200);
  dht.begin();
  connectWiFi();
  syncClock();
  tls.setCACert(DEVICECAMP_CA);
  mqtt.setServer(MQTT_HOST, MQTT_PORT);
  mqtt.setBufferSize(512);
  mqtt.setKeepAlive(30);
  mqtt.setSocketTimeout(10);
}

void loop() {
  if (WiFi.status() != WL_CONNECTED) {
    WiFi.reconnect();
    delay(100);
    return;
  }

  connectMQTT();
  mqtt.loop();

  const unsigned long now = millis();
  if (mqtt.connected() &&
      (lastPublishAt == 0 || now - lastPublishAt >= PUBLISH_INTERVAL_MS)) {
    publishReading();
    lastPublishAt = now;
  }
}

5. Flashea y comprueba

Configura WIFI_SSID y WIFI_PASSWORD, carga el sketch y abre el monitor serie a 115200 baudios. “Published” confirma el envío; las métricas aparecerán en el workbench tras el primer payload aceptado.