¿Cómo instalar un sensor de temperatura DS18B20 con el ESP32 y Arduino IDE? Guía Completa (Sensor Único, Múltiples Sensores y Servidor Web)

Libro Guía del Microcontrolador ESP32

Esta es una guía en profundidad para el sensor de temperatura DS18B20 con el ESP32 usando Arduino IDE. Te mostraremos cómo cablear el sensor, instalar las librerías necesarias y escribir el código para obtener las lecturas de uno y múltiples sensores. Finalmente, construiremos un servidor web sencillo para mostrar las lecturas del sensor.

¿Qué es el sensor de temperatura DS18B20?

El DS18B20 es un sensor de temperatura digital con protocolo one-wire. Esto significa que solo requiere una línea de datos (y GND) para comunicarse con tu ESP32. Puede alimentarse mediante una fuente de alimentación externa o puede obtener su energía de la línea de datos (llamado “modo parásito”), lo que elimina la necesidad de una fuente de alimentación externa.

Cada sensor de temperatura DS18B20 tiene un código de serie único de 64 bits. Esto te permite cablear múltiples sensores al mismo cable de datos. Así, puedes obtener la temperatura de múltiples sensores usando solo un GPIO. El DS18B20 también está disponible en versión impermeable, lo que lo hace ideal para proyectos al aire libre, acuarios, sistemas de riego o cualquier aplicación donde el sensor deba estar en contacto con líquidos.

Aquí tienes un resumen de las especificaciones más relevantes del DS18B20:

Se comunica mediante bus one-wire. Rango de alimentación: 3,0 V a 5,5 V. Rango de temperatura de funcionamiento: -55 ºC a +125 ºC. Precisión de ±0,5 ºC (entre el rango -10 ºC a 85 ºC). Para más información, consulta el datasheet del DS18B20.

Componentes necesarios

Para seguir este tutorial necesitas: una placa ESP32, uno o varios sensores de temperatura DS18B20 (versión impermeable), una resistencia de 4,7 kΩ, cables jumper y una protoboard.

Esquema de conexión: ESP32 con DS18B20

Como mencionamos antes, el sensor DS18B20 puede alimentarse a través del pin VDD (modo normal), o puede obtener su energía de la línea de datos (modo parásito). Puedes elegir cualquiera de los dos modos.

Modo parásito: el sensor se alimenta exclusivamente desde la línea de datos, eliminando la necesidad de conectar el pin VCC a 3,3 V. La resistencia pull-up de 4,7 kΩ sigue siendo obligatoria. Este modo es útil cuando quieres minimizar el cableado, ya que solo necesitas dos cables (datos y GND) para que el sensor funcione.

Modo normal: el sensor se alimenta con 3,3 V a través del pin VCC, además de la línea de datos y GND. Este modo es más robusto y recomendado para distancias largas o entornos con ruido eléctrico, ya que garantiza una alimentación estable al sensor.

Preparar Arduino IDE

Vamos a programar el ESP32 usando Arduino IDE, así que asegúrate de tener el complemento ESP32 instalado antes de continuar.

Instalar las librerías necesarias

Para interactuar con el sensor DS18B20, necesitas instalar la librería One Wire de Paul Stoffregen y la librería Dallas Temperature. Sigue los siguientes pasos para instalar esas librerías:

1. Abre tu Arduino IDE y ve a Programa > Incluir Librería > Gestionar Librerías. El Gestor de Librerías debería abrirse.

2. Escribe “onewire” en el cuadro de búsqueda e instala la librería OneWire de Paul Stoffregen.

3. Después, busca “Dallas” e instala la librería DallasTemperature de Miles Burton.

Después de instalar las librerías, reinicia tu Arduino IDE.

Código para un solo sensor DS18B20

Después de instalar las librerías necesarias, puedes subir el código al ESP32. El siguiente código lee la temperatura del sensor DS18B20 y muestra las lecturas en el Monitor Serie de Arduino IDE:

/*
  Rui Santos
  Detalles completos del proyecto en https://RandomNerdTutorials.com
*/

#include <OneWire.h>
#include <DallasTemperature.h>

// GPIO al que está conectado el DS18B20
const int oneWireBus = 4;     

// Configura una instancia oneWire para comunicarse con cualquier dispositivo OneWire
OneWire oneWire(oneWireBus);

// Pasa nuestra referencia oneWire al sensor Dallas Temperature
DallasTemperature sensors(&oneWire);

void setup() {
  // Inicia el Monitor Serie
  Serial.begin(115200);
  // Inicia el sensor DS18B20
  sensors.begin();
}

void loop() {
  sensors.requestTemperatures(); 
  float temperatureC = sensors.getTempCByIndex(0);
  float temperatureF = sensors.getTempFByIndex(0);
  Serial.print(temperatureC);
  Serial.println("ºC");
  Serial.print(temperatureF);
  Serial.println("ºF");
  delay(5000);
}

Hay muchas formas diferentes de obtener la temperatura de los sensores DS18B20. Sin embargo, si estás usando solo un sensor, esta es una de las formas más fáciles y sencillas.

Cómo funciona el código paso a paso

Empieza incluyendo las librerías OneWire y DallasTemperature. Se crean las instancias necesarias para el sensor de temperatura. El sensor de temperatura está conectado al GPIO 4.

En el setup(), se inicializa el Monitor Serie a 115200 baudios y se inicializa el sensor DS18B20.

Antes de obtener realmente la temperatura, necesitas llamar al método requestTemperatures(). Después, obtén la temperatura en Celsius usando el método getTempCByIndex(). O usa getTempFByIndex() para obtener la temperatura en Fahrenheit.

Los métodos getTempCByIndex() y getTempFByIndex() aceptan el índice del sensor de temperatura. Como estamos usando solo un sensor, su índice es 0. Si quieres leer más de un sensor, usas el índice 0 para un sensor, el índice 1 para otro, y así sucesivamente.

Finalmente, se imprimen los resultados en el Monitor Serie. Se solicitan nuevas lecturas de temperatura cada 5 segundos.

Demostración

Después de subir el código, deberías obtener las lecturas de tu sensor mostradas en el Monitor Serie.

Obtener temperatura de múltiples sensores DS18B20

El sensor DS18B20 se comunica usando protocolo one-wire y cada sensor tiene un código de serie único de 64 bits, así que puedes leer la temperatura de múltiples sensores usando solo un GPIO. Solo necesitas cablear todas las líneas de datos juntas.

Código para múltiples DS18B20

Después, sube el siguiente código. Escanea todos los dispositivos en el GPIO 4 e imprime la temperatura de cada uno. Este sketch está basado en un ejemplo proporcionado por la librería DallasTemperature:

/*
  Rui Santos
  Detalles completos del proyecto en https://RandomNerdTutorials.com
*/

#include <OneWire.h>
#include <DallasTemperature.h>

// El cable de datos está conectado al GPIO 4
#define ONE_WIRE_BUS 4

// Configura una instancia oneWire para comunicarse con cualquier dispositivo OneWire
OneWire oneWire(ONE_WIRE_BUS);

// Pasa nuestra referencia oneWire a Dallas Temperature
DallasTemperature sensors(&oneWire);

// Número de dispositivos de temperatura encontrados
int numberOfDevices;

// Usaremos esta variable para almacenar la dirección de un dispositivo encontrado
DeviceAddress tempDeviceAddress; 

void setup(){
  // inicia el puerto serie
  Serial.begin(115200);
  
  // Inicia la librería
  sensors.begin();
  
  // Obtiene un recuento de dispositivos en el bus
  numberOfDevices = sensors.getDeviceCount();
  
  // Localiza dispositivos en el bus
  Serial.print("Locating devices...");
  Serial.print("Found ");
  Serial.print(numberOfDevices, DEC);
  Serial.println(" devices.");

  // Recorre cada dispositivo, imprime la dirección
  for(int i=0;i<numberOfDevices; i++){
    // Busca la dirección en el bus
    if(sensors.getAddress(tempDeviceAddress, i)){
      Serial.print("Found device ");
      Serial.print(i, DEC);
      Serial.print(" with address: ");
      printAddress(tempDeviceAddress);
      Serial.println();
    } else {
      Serial.print("Found ghost device at ");
      Serial.print(i, DEC);
      Serial.print(" but could not detect address. Check power and cabling");
    }
  }
}

void loop(){ 
  sensors.requestTemperatures(); // Envía el comando para obtener temperaturas
  
  // Recorre cada dispositivo, imprime los datos de temperatura
  for(int i=0;i<numberOfDevices; i++){
    // Busca la dirección en el bus
    if(sensors.getAddress(tempDeviceAddress, i)){
      // Muestra el ID del dispositivo
      Serial.print("Temperature for device: ");
      Serial.println(i,DEC);
      // Imprime los datos
      float tempC = sensors.getTempC(tempDeviceAddress);
      Serial.print("Temp C: ");
      Serial.print(tempC);
      Serial.print(" Temp F: ");
      Serial.println(DallasTemperature::toFahrenheit(tempC)); // Convierte tempC a Fahrenheit
    }
  }
  delay(5000);
}

// función para imprimir una dirección de dispositivo
void printAddress(DeviceAddress deviceAddress) {
  for (uint8_t i = 0; i < 8; i++){
    if (deviceAddress[i] < 16) Serial.print("0");
      Serial.print(deviceAddress[i], HEX);
  }
}

Demostración

En este ejemplo, estamos usando tres sensores de temperatura DS18B20. Esto es lo que obtenemos en el Monitor Serie de Arduino IDE.

Mostrar las lecturas del DS18B20 en un servidor web

Para construir el servidor web usaremos la librería ESPAsyncWebServer, que proporciona una forma sencilla de construir un servidor web asíncrono. Construir un servidor web asíncrono tiene varias ventajas. Recomendamos echar un vistazo rápido a la documentación de la librería en su página de GitHub.

Instalar las librerías ESPAsyncWebServer y AsyncTCP

Necesitas instalar las siguientes librerías en tu Arduino IDE para construir el servidor web para este proyecto: la libería ESPAsyncWebServer de ESP32Async y la libería AsyncTCP de ESP32Async. Puedes instalar esas librerías en el Gestor de Librerías de Arduino IDE. Ve a Programa > Incluir Librería > Gestionar Librerías y busca los nombres de las librerías.

Código del servidor web asíncrono con DS18B20

Abre tu Arduino IDE y copia el siguiente código:

/*
  Rui Santos & Sara Santos - Random Nerd Tutorials
  Detalles completos del proyecto en https://RandomNerdTutorials.com
*/

// Importa las librerías requeridas
#ifdef ESP32
  #include <WiFi.h>
  #include <ESPAsyncWebServer.h>
#else
  #include <Arduino.h>
  #include <ESP8266WiFi.h>
  #include <Hash.h>
  #include <ESPAsyncTCP.h>
  #include <ESPAsyncWebServer.h>
#endif
#include <OneWire.h>
#include <DallasTemperature.h>

// El cable de datos está conectado al GPIO 4
#define ONE_WIRE_BUS 4

// Configura una instancia oneWire para comunicarse con cualquier dispositivo OneWire
OneWire oneWire(ONE_WIRE_BUS);

// Pasa nuestra referencia oneWire al sensor Dallas Temperature
DallasTemperature sensors(&oneWire);

// Variables para almacenar los valores de temperatura
String temperatureF = "";
String temperatureC = "";

// Variables del temporizador
unsigned long lastTime = 0;  
unsigned long timerDelay = 30000;

// Reemplaza con las credenciales de tu red
const char* ssid = "REPLACE_WITH_YOUR_SSID";
const char* password = "REPLACE_WITH_YOUR_PASSWORD";

// Crea el objeto AsyncWebServer en el puerto 80
AsyncWebServer server(80);

String readDSTemperatureC() {
  // Llama a sensors.requestTemperatures() para emitir una temperatura global y peticiones a todos los dispositivos en el bus
  sensors.requestTemperatures(); 
  float tempC = sensors.getTempCByIndex(0);

  if(tempC == -127.00) {
    Serial.println("Failed to read from DS18B20 sensor");
    return "--";
  } else {
    Serial.print("Temperature Celsius: ");
    Serial.println(tempC); 
  }
  return String(tempC);
}

String readDSTemperatureF() {
  // Llama a sensors.requestTemperatures() para emitir una temperatura global y peticiones a todos los dispositivos en el bus
  sensors.requestTemperatures(); 
  float tempF = sensors.getTempFByIndex(0);

  if(int(tempF) == -196){
    Serial.println("Failed to read from DS18B20 sensor");
    return "--";
  } else {
    Serial.print("Temperature Fahrenheit: ");
    Serial.println(tempF);
  }
  return String(tempF);
}

const char index_html[] PROGMEM = R"rawliteral(
<!DOCTYPE HTML><html>
<head>
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.7.2/css/all.css" integrity="sha384-fnmOCqbTlWIlj8LyTjo7mOUStjsKC4pOpQbqyi7RrhN7udi9RwhKkMHpvLbHG9Sr" crossorigin="anonymous">
  <style>
    html {
     font-family: Arial;
     display: inline-block;
     margin: 0px auto;
     text-align: center;
    }
    h2 { font-size: 3.0rem; }
    p { font-size: 3.0rem; }
    .units { font-size: 1.2rem; }
    .ds-labels{
      font-size: 1.5rem;
      vertical-align:middle;
      padding-bottom: 15px;
    }
  </style>
</head>
<body>
  <h2>ESP DS18B20 Server</h2>
  <p>
    <i class="fas fa-thermometer-half" style="color:#059e8a;"></i> 
    <span class="ds-labels">Temperature Celsius</span> 
    <span id="temperaturec">%TEMPERATUREC%</span>
    <sup class="units">&deg;C</sup>
  </p>
  <p>
    <i class="fas fa-thermometer-half" style="color:#059e8a;"></i> 
    <span class="ds-labels">Temperature Fahrenheit</span> 
    <span id="temperaturef">%TEMPERATUREF%</span>
    <sup class="units">&deg;F</sup>
  </p>
</body>
<script>
setInterval(function ( ) {
  var xhttp = new XMLHttpRequest();
  xhttp.onreadystatechange = function() {
    if (this.readyState == 4 && this.status == 200) {
      document.getElementById("temperaturec").innerHTML = this.responseText;
    }
  };
  xhttp.open("GET", "/temperaturec", true);
  xhttp.send();
}, 10000) ;
setInterval(function ( ) {
  var xhttp = new XMLHttpRequest();
  xhttp.onreadystatechange = function() {
    if (this.readyState == 4 && this.status == 200) {
      document.getElementById("temperaturef").innerHTML = this.responseText;
    }
  };
  xhttp.open("GET", "/temperaturef", true);
  xhttp.send();
}, 10000) ;
</script>
</html>)rawliteral";

// Reemplaza el placeholder con los valores del DS18B20
String processor(const String& var){
  //Serial.println(var);
  if(var == "TEMPERATUREC"){
    return temperatureC;
  }
  else if(var == "TEMPERATUREF"){
    return temperatureF;
  }
  return String();
}

void setup(){
  // Puerto serie para propósitos de depuración
  Serial.begin(115200);
  Serial.println();
  
  // Inicia la librería DS18B20
  sensors.begin();

  temperatureC = readDSTemperatureC();
  temperatureF = readDSTemperatureF();

  // Conecta a Wi-Fi
  WiFi.begin(ssid, password);
  Serial.println("Connecting to WiFi");
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.println();
  
  // Imprime la dirección IP local del ESP32
  Serial.println(WiFi.localIP());

  // Ruta para la raíz / página web
  server.on("/", HTTP_GET, [](AsyncWebServerRequest *request){
    request->send(200, "text/html", index_html, processor);
  });
  server.on("/temperaturec", HTTP_GET, [](AsyncWebServerRequest *request){
    request->send(200, "text/plain", temperatureC.c_str());
  });
  server.on("/temperaturef", HTTP_GET, [](AsyncWebServerRequest *request){
    request->send(200, "text/plain", temperatureF.c_str());
  });
  // Inicia el servidor
  server.begin();
}
 
void loop(){
  if ((millis() - lastTime) > timerDelay) {
    temperatureC = readDSTemperatureC();
    temperatureF = readDSTemperatureF();
    lastTime = millis();
  }  
}

Inserta las credenciales de tu red en las siguientes variables y el código funcionará inmediatamente:

const char* ssid = "REPLACE_WITH_YOUR_SSID";
const char* password = "REPLACE_WITH_YOUR_PASSWORD";

Cómo funciona el código del servidor web

Importar las librerías

Primero, se importan las librerías requeridas para la placa ESP32.

Instanciar el sensor DS18B20

Se define el GPIO al que está conectado el pin de datos del DS18B20. En este caso, está conectado al GPIO 4. Se instancian las instancias necesarias para inicializar el sensor.

Configurar las credenciales de red

Se insertan las credenciales de red en las variables correspondientes, para que el ESP32 pueda conectarse a tu red local. Se crea un objeto AsyncWebServer en el puerto 80.

Funciones de lectura de temperatura

Después, creamos dos funciones para leer la temperatura. La función readDSTemperatureC() devuelve las lecturas en grados Celsius. En caso de que el sensor no sea capaz de obtener una lectura válida, devuelve -127. Así que tenemos una sentencia if que devuelve dos guiones (--) en caso de que el sensor falle al obtener las lecturas. La función readDSTemperatureF() funciona de forma similar pero devuelve las lecturas en grados Fahrenheit. Las lecturas se devuelven como tipo string. Para convertir un float a un string, usa la función String().

Construir la página web

El siguiente paso es construir la página web. El HTML y CSS necesarios para construir la página web se guardan en la variable index_html. En el texto HTML tenemos TEMPERATUREC y TEMPERATUREF entre signos %. Este es un placeholder para los valores de temperatura. Esto significa que este texto %TEMPERATUREC% es como una variable que será reemplazada por el valor real de temperatura del sensor. Los placeholders en el texto HTML deben ir entre signos %.

La función processor()

Ahora, necesitamos crear la función processor(), que reemplazará los placeholders en nuestro texto HTML con los valores reales de temperatura. Cuando se solicita la página web, comprobamos si el HTML tiene algún placeholder. Si encuentra el placeholder %TEMPERATUREC%, devolvemos la temperatura en Celsius llamando a la función readDSTemperatureC() creada antes. Si el placeholder es %TEMPERATUREF%, devolvemos la temperatura en Fahrenheit.

La función setup()

En el setup(), se inicializa el Monitor Serie para propósitos de depuración. Se inicializa el sensor de temperatura DS18B20. Se conecta a tu red local y se imprime la dirección IP del ESP32.

Finalmente, se añaden las siguientes líneas de código para manejar el servidor web. Cuando hacemos una petición en la URL raíz, enviamos el texto HTML que está almacenado en la variable index_html. También necesitamos pasar la función processor, que reemplazará todos los placeholders con los valores correctos.

Necesitamos añadir dos manejadores adicionales para actualizar las lecturas de temperatura. Cuando recibimos una petición en la URL /temperaturec, simplemente necesitamos enviar el valor actualizado de temperatura. Es texto plano, y debería enviarse como char, así que usamos el método c_str(). El mismo proceso se repite para la temperatura en Fahrenheit. Por último, podemos iniciar el servidor.

La función loop()

Como este es un servidor web asíncrono, no necesitamos escribir nada en el loop() para manejar las peticiones, ya que toda la lógica ocurre en los callbacks registrados. Sin embargo, en este ejemplo el loop() sí se usa para actualizar periódicamente las variables globales de temperatura, que luego son servidas por los handlers. Cada 30 segundos se leen nuevas temperaturas y se actualizan las variables temperatureC y temperatureF.

Demostración

Después de subir el código, abre el Monitor Serie de Arduino IDE a 115200 baudios. Pulsa el botón RST integrado en el ESP32 y después de unos segundos debería aparecer tu dirección IP.

En tu red local, abre un navegador y escribe la dirección IP del ESP32. Ahora puedes ver la temperatura en Celsius y Fahrenheit en tu servidor web. Las lecturas del sensor se actualizan automáticamente sin necesidad de refrescar la página web.

Conclusión: lo que has aprendido

Esperamos que este tutorial te haya resultado útil. El DS18B20 es uno de los sensores de temperatura más versátiles y fiables del mercado maker, y combinado con el ESP32 te permite construir sistemas de monitorización térmica de uno o múltiples puntos con un solo GPIO.

La capacidad de leer múltiples sensores por el mismo cable es una de las grandes ventajas del protocolo one-wire. Con tres cables (VCC, GND y datos) y una sola resistencia pull-up, puedes monitorizar la temperatura de varias habitaciones, un acuario con varios puntos de medición, un sistema de calefacción con múltiples zonas, o cualquier aplicación que requiera lecturas de temperatura distribuidas.

La versión impermeable del DS18B20 amplía aún más las posibilidades, permitiéndote medir la temperatura del agua en piscinas, estanques, acuarios, sistemas de riego o incluso en el suelo para agricultura. El servidor web asíncrono que has construido te permite consultar todas esas lecturas desde cualquier dispositivo de tu red, con actualizaciones automáticas cada 30 segundos.

Este proyecto es la base de cualquier sistema de monitorización térmica profesional, y con los conocimientos que has adquirido, puedes escalarlo fácilmente para incluir decenas de sensores, integración con MQTT, alertas por correo o Telegram, registro en tarjeta SD y cualquier otra funcionalidad que necesites.

Vistas: 0

Descubre más desde CIBERED

Suscríbete y recibe las últimas entradas en tu correo electrónico.

Scroll al inicio