Midiendo temperatura con el DS18B20 y Micropython

En este completo tutorial veremos las características principales del sensor de temperatura digital DS18B20, sus conexiones y formas de alimentación, tanto si usamos un solo sensor como si conectamos varios. También como podemos acceder a él empleando Micropython para hacer mediciones, las librerías y métodos necesarios en tres plataformas distintas: el ESP8266, ESP32 y la Raspberry Pi Pico.

Medición de temperatura

La temperatura es probablemente la magnitud física que con mas frecuencia se mide, ya sea como una variable ambiental (la temperatura ambiente de un cuarto o la del aire en el exterior), como parte de un proceso (como la temperatura de un horno industrial) o para evitar daños por sobrecalentamiento (como cuando se mide la temperatura de un motor eléctrico).

Según sea el caso, sobre todo por el rango de temperaturas que vayamos a medir, tenemos a nuestra disposición una amplia variedad de sensores diferentes.

Si queremos hacer mediciones sencillas por debajo de 120 grados, podemos emplear sensores basados en semiconductores, como los populares LM35 o TMP35 que entregan un voltaje proporcional al valor de la temperatura o el DS18B20 que veremos en este artículo que nos entrega directamente a la salida un valor binario.

Si queremos medir temperaturas mayores, hasta 500 grados deberemos utilizar sensores como las RTD, resistencias variables con la temperatura como el conocido Pt100 o termocuplas si la temperatura es aún mayor.

Fig. 1. De izquierda a derecha: LM35, Pt100 y termocupla (no a escala)

El DS18B20

Descripción

El DS18B20 es un sensor de temperatura o termómetro diseñado por la empresa Dallas Semiconductor que entrega en su salida el valor de temperatura medido en un formato digital empleando el protocolo OneWire, creado por la misma empresa. Este protocolo utiliza un único pin de datos para el envío y recepción de información, lo que ahorra considerablemente la cantidad de conexiones.

El DS18B20 también puede derivar su alimentación del pin de datos, reduciendo a sólo dos (datos y GND) la cantidad de conexiones necesarias. Tiene una resolución configurable de 9 a 12 bits y posee un código o identificador único de 48 bits que permite la conexión de varios sensores en la misma línea de datos.

Características

  • Tensión de alimentación: 3V a 5V.
  • Mide temperaturas de -55 ºC a +125 ºC.
  • La resolución de la medición se puede configurar entre 9, 10, 11 y 12 bits (0.5°C, 0.25°C, 0.125°C y 0.0625°C).
  • Tiempo máximo de conversión: 750 mili segundos.
  • Disponible en varios encapsulados (8-Pin SO, 8-Pin µSOP y TO-92).
  • Utiliza el protocolo One Wire.
  • Puede ser alimentado desde el pin de datos (Modo Parasite).
  • Posee un código de identificación único de 48 bits.
Fig. 2. Encapsulados y pines del 18B20 (Fuente: Dallas)

Alimentación

El DS18B20 puede alimentarse de dos formas.

La conexión “normal” es suministrando la alimentación a través de los pines GND (negativo) y VDD (Positivo) de una tensión de alimentación entre 3 y 5 Voltios.

La otra posibilidad es la denominada “Modo Parasite” o parásito, en la que el DS18B20 deriva su alimentación desde el pin DQ, el pin de datos (este pin siempre debe estar conectado a VDD a través de una resistencia de Pull-up) que carga un pequeño capacitor en el interior del chip.

Este modo tiene la ventaja de que nos permite ahorrar un cable, lo cual puede ser importante si tenemos varios sensores conectados a una distancia considerable, pero también tiene sus inconvenientes (requiere mas corriente a través del pull-up y no se recomienda para temperaturas superiores a los 100 ºC). En este modo, el pin VDD debe estar unido a GND.

Fig. 3. Modo de alimentación Normal
Fig. 4. Modo de alimentación Parasite

Conexión de varios sensores

Si se necesita medir la temperatura en varios puntos diferentes empleando mas de un 18B20, se puede interconectar todos a través de la misma línea de datos (DQ). Como cada uno de los sensores tiene una identificación diferente, pueden ser direccionados de manera individual para hacer las lecturas de temperatura.

En ese caso no se debe conectar una resistencia de pull-up en cada sensor, sino que debe utilizarse una sola.

Fig. 5. Conexión de varios DS18B20

DS18B20 versión sumergible

El DS18B20 es comercializado por Dallas en los encapsulados que se ven en la Fig. 2, pero también puede encontrarse en el mercado uno montado en una vaina de aluminio con un cable adosado que se comercializa como “waterproof DS18B20” o DS18B20 sumergible, que puede emplearse para realizar mediciones de temperatura de líquidos.

Fig. 6. DS18B20 sumergible y en encapsulado TO92

La versión sumergible cuenta con 3 conductores, usualmente de colores Rojo, Negro y Amarillo con la siguiente asignación:

Fig. 7. Cable del sensor sumergible

Conexiones para ESP8266

A continuación pueden verse las conexiones entre un sensor DS18B20 y una D1MINI con el esp8266. El sensor se alimenta desde GND y la salida de 3,3V de la placa y el pin DQ se conecta a D2 (GPIO4) y al positivo a través de la resistencia de pull-up de 4K7 ohms.

Fig. 8. Conexión del DS18B20 a un ESP8266

Conexiones para ESP32

En la siguiente imagen puede verse como conectar el sensor a una placa con un ESP32. La salida DQ del DS18B20 se conecta al GPIO4, igual que en ESP8266, sólo que en este caso corresponde al pin D4 de la placa. La alimentación del sensor también se toma de GND y la salida de 3V3.

Fig. 9 conexión del DS18B20 al ESP32

Conexiones para Raspberry Pi Pico

Finalmente estas son las conexiones en el caso de que usen una Raspberry Pi Pico. Otra vez el pin DQ del sensor se conecta a GPIO4 y la alimentación a GND y 3,3 Voltios.

Fig. 10 conexión del DS18B20 a la Raspberry Pi Pico

El programa

Veamos dos versiones de un programa para mostrar el uso del DS18B20. El primero será uno mínimo y el segundo incluirá control de excepciones.

El mismo código funciona sin modificaciones en las 3 placas, la D1 mini, la ESP32 y la Pico, una muestra de la portabilidad de Micropython y su capacidad de correr sobre distintas plataformas.

Como en los tres casos usamos el mismo pin (GPIO4) no es necesaria ninguna adaptación del software al hardware y el resto es común para todas las placas empleadas.

Versión mínima

El código puede verse a continuación. Empecemos con el análisis:

Módulos

En las líneas 1 y 2 se importa el módulo Pin y el método sleep del módulo time, como hemos hecho muchas otras veces.

En la línea 4 se importa el módulo onewire, que tiene las funciones de bajo nivel de este protocolo.

A continuación en la línea 5 importamos la clase DS18X20 desde el módulo ds18x20, que ya viene incluido en Micropython. Esta clase implementa los métodos necesarios para acceder al DS18B20 y emplea para ello el módulo onewire que importamos antes.

Luego en la línea 7 se importa el módulo binascii que incluye métodos para convertir números binarios (o hexadecimales) a texto.

Objetos

Una vez incluidos todos los módulos necesarios, en la línea 9 creamos un objeto ow de la clase Onewire asociado con el pin GPIO4, preparando ese pin para usar ese protocolo.

En la línea 11 creamos otro objeto, esta vez uno llamado sensor, de la clase 18X20 asociado al objeto ow del pin 4, dejando ya configurado el hardware para comunicarse con el sensor.

from machine import Pin
from time import sleep

import onewire
from ds18x20 import DS18X20

import binascii

ow = onewire.OneWire(Pin(4)) #Prepara GPIO4 para usar con OneWire

sensor = DS18X20(ow) #define un sensor en ese pin

direcciones = sensor.scan()  #Lee el ID del sensor conectado
id=direcciones[0]

#Pasa el ID a formato de texto e imprime
idHex = binascii.hexlify(bytearray(id)) 
print ("ID=",idHex)

#Lee e imprime la temperatura cada 1 segundo
while (True):
    sensor.convert_temp ()
    sleep (1)
    temperatura = sensor.read_temp (id)
    print (temperatura)


En la línea 13 se escanean los sensores que puedan estar conectados empleando el método scan (). Este método devuelve una lista con los identificadores (ID) o direcciones de todos los sensores que se hayan encontrado conectados. Como en este ejemplo usamos sólo uno, su dirección se puede recuperar leyendo el primer (y único) elemento de la lista con direcciones [0]. A continuación en la línea 14 se imprime el ID recuperado directamente como un bytearray, lo que a veces puede ser difícil de interpretar.

Por eso en la línea 17 se pasa ese identificador a un texto en hexadecimal con la función hexlify para interpretarlo mejor y en la línea 18 se lo imprime.

Lo que veremos tendrá este formato:

28fab77997190368

El 28 hexadecimal inicial es común a todos los DS18B20 e identifica el tipo de sensor (hay otros dispositivos que también usan el protocolo OneWire y tienen otros códigos). Los siguientes 6 bytes (48 bits) conforman el identificador de este chip en particular y el último es un CRC o suma de control de todos los anteriores, totalizando 8 bytes o 64 bits.

Bucle

Finalmente, en la línea 21 se inicia un bucle infinito dentro del cual se lee e imprime la temperatura. Esto se hace llamando primero al método convert_temp () que le indica al sensor que realice una medición y luego al método read_temp (id) para leer el valor medido (convert_temp no emplea un identificador, le indica a todos los DS18B20 que hubiera conectados que hagan una medición) . Entre las dos operaciones siempre debemos hacer un retardo de al menos 750 mili segundos para dar tiempo al sensor a que complete la medición.

Versión con control de excepciones

Si nuestro sensor se desconecta, se daña o simplemente se corta un cable, seguramente las funciones que utilizamos para leerlo generarán un error o excepción, haciendo que el programa se detenga. Esto es admisible cuando estamos probando el código porque vemos el error en la consola de Micropython, pero es intolerable si nuestro equipo está funcionando solo, de manera autónoma. En este caso siempre debemos ser capaces de manejar este tipo de errores, detectándolos y tomando alguna acción tal como encender un led, dar un mensaje de error en un display, etc.

El siguiente programa aprovecha la estructura try – except – else de Micropython (en realidad es original de Python) para capturar los errores que pudieran ocurrir y al menos imprimir un mensaje de notificación.

from machine import Pin
import onewire
from ds18x20 import DS18X20
from time import sleep

import binascii

ow = onewire.OneWire(Pin(4)) #Prepara GPIO4 para usar con OneWire

sensor = DS18X20(ow) #define un sensor en ese pin

direcciones = sensor.scan()  #Lee el ID del sensor conectado
id=direcciones[0]

#Pasa el ID a formato de texto e imprime
idHex = binascii.hexlify(bytearray(id)) 
print ("ID=",idHex)

#Lee e imprime la temperatura cada 1 segundo
while (True):
    
    try:
        sensor.convert_temp ()
        sleep (1)
        temperatura = sensor.read_temp (id)
        
    except:
        print ("Error en sensor!")
        sleep (1)
        
    else:
        print (temperatura)

Lectura de varios sensores

Como vimos mas arriba se pueden conectar varios sensores, compartiendo la misma línea de datos y empleando una sola resistencia de pull-up, como se ve en la Fig. 5. En el programa, deberemos tener cuidado de identificar correctamente el ID de cada sensor para conocer de cual de ellos proviene cada una de las mediciones realizadas. Para ello sería util utilizar un programa como el que vimos mas arriba, primero con un sensor y luego con el otro, y tomar nota del ID de cada uno.

Fig. 11. Los dos sensores conectados a una D1 mini

A modo de ejemplo conectaré dos DS18B20, uno en encapsulado TO-92, que mide la temperatura ambiente y uno sumergible para medir la temperatura de un líquido. Corriendo el programa anterior para obtener el ID de cada uno tendremos lo siguiente.

Para el sensor que mide la temperatura ambiente:

Fig. 12. Lectura del ID de un sensor

Y para el sensor que mide la temperatura del líquido:

Fig. 13. Lectura del ID del otro sensor

Con estos valores podemos escribir otro programa que direccione a cada sensor en particular y muestre el valor de temperatura correspondiente:

from machine import Pin
import onewire
from ds18x20 import DS18X20
from time import sleep

import binascii

ow = onewire.OneWire(Pin(4)) #Prepara GPIO4 para usar con OneWire

sensor = DS18X20(ow) #define un sensor en ese pin

idAmbiente = binascii.unhexlify("28fab77997190368")
idLiquido  = binascii.unhexlify("287436150600002a")

print ("ID Ambiente=",idAmbiente)
print ("ID Liquido =",idLiquido)

#Lee e imprime la temperatura cada 1 segundo
while (True):
    #Leer temperatura ambiente
    sensor.convert_temp ()
    sleep (1)
    temperatura = sensor.read_temp (idAmbiente)
    print ("T ambiente=",temperatura)
    
    #Leer temperatura del liquido
    sensor.convert_temp ()
    sleep (1)
    temperatura = sensor.read_temp (idLiquido)
    print ("T liquido=",temperatura)
           

No lo analizaré completamente, pero se puede ver en las líneas 12 y 13 las declaraciones de las dos variables con los ID de los dos sensores y en el bucle principal se lee la temperatura de cada uno con la variable que corresponda.

En este programa se usa la función unhexlify del módulo binascii, que hace lo contrario a hexlify, es decir, pasa de un texto a un bytearray (un bytearray no es otra cosa que una lista de bytes).

Conclusiones

En este artículo vimos que es el DS18B20, sus principales características y formas de conexión. También las librerías y métodos que debemos emplear para realizar mediciones de temperatura en Micropython, tanto si empleamos un solo sensor como si utilizamos varios para medir distintas temperaturas. El DS18B20 es un sensor muy popular y como vimos, fácil de utilizar y necesita muy pocas conexiones. Su capacidad de trabajar sobre una sola línea de datos ahorra muchas conexiones, sobre todo cuando empleamos varios sensores.

Espero que el tutorial les sea de utilidad para incluir este chip en sus proyectos. Como siempre, cualquier duda o sugerencia pueden dejarla mas abajo en la sección de comentarios.

Mas info

Hoja de datos del DS18B20

Deja un comentario

Este sitio usa Akismet para reducir el spam. Aprende cómo se procesan los datos de tus comentarios.

Habilitar notificaciones OK No, gracias