El presente artículo describe como conectar y usar múltiples sensores de temperatura Analog Device DS18B20 concurrentemente. Uno de los aspectos de este sensor que es deseable, es la interfaz de 1-Cable que tiene un protocolo de comunicación con verificación de integridad de data CRC. El sensor de de temperatura Analog Device DS18B20 deriva su consumo de energia eléctrica de la linea 1-Cable eliminando la necesidad de usar la típica fuente de potencia externa para un sensor. Con un código de identificación de 64-Bit en ROM,

múltiples sensores pueden concurrentemente compartir la linea de comunicación de 1-Cable. Un controlador puede monitorear múltiples sensores distribuidos en una area extensa. Aplicaciones que se pueden beneficiar de estas carácteristicas incluyen, monitoreo de temperatura, control de temperatura dentro de edificios, equipo industrial, maquinaria, procesos y sistemas de control.
Las características principales de los sensores de temperatura Analog Device DS18B20 son las siguientes:
• Unique 1-Wire® Interface Requires Only One Port Pin for Communication
• Reduce Component Count with Integrated Temperature Sensor and EEPROM
• Measures Temperatures from -55°C to +125°C (-67°F to +257°F)
• ±0.5°C Accuracy from -10°C to +85°C
• Programmable Resolution from 9 Bits to 12 Bits (Configuration Register)
• No External Components Required Parasitic Power Mode Requires Only 2 Pins for Operation (DQ and GND)
• Simplifies Distributed Temperature-Sensing Applications with Multidrop Capability
• Each Device Has a Unique 64-Bit Serial Code Stored in On-Board ROM
• Flexible User-Definable Nonvolatile (NV) Alarm Settings with Alarm Search Command Identifies Devices with Temperatures Outside Programmed Limits
• Available in 8-Pin SO (150 mils), 8-Pin µSOP, and 3-Pin TO-92 Packages
Un total de 3 sensores de temperatura Analog Device DS18B20 fueron usados en este demo en el formato físico TO-92 mostrado a continuación
El diagrama de bloque correspondiente al sensor de temperatura Analog Device DS18B20 es el siguiente,
La funcionalidad principal del sensor de temperatura Analog Device DS18B20 es directamente medir la temperatura y reportarla digitalmente en la linea 1-Cable. La resolución del sensor de temperatura es configurable por el usuario entre 9, 10, 11 o 12 bits (Registro de Configuración), correspondiente a incrementos de 5°C, 0.25°C, 0.125°C, y 0.0625°C, respectivamente. La resolución cuando se inicialmente se prende el sensor es de 12-bit. El sensor de temperatura DS18B20 provee la data de la temperatura en unidades de grados Celsius; para aplicaciones que requieran unidades en Fahrenheit, una tabla de conversión o rutina de conversión es necesaria, La temperatura esta almacenada en formato de complemento de 2 de 16-bit extendidiendo el signo (16-bit sign-extended two’s complement) en los registros de temperatura como se muestra en la siguiente tabla,
El sensor de temperatura Analog Device DS18B20 se puede alimentar como tradicionalemente se hace, con una fuente de potencia externa conectandose al pin VDD como se muestra en el próximo diagrama de bloque si es necesario,
El sensor de temperatura Analog Device DS18B20 tiene una memoria interna como se ilustra a continuación,
La siguiente configuración fue usada en este demo con la Raspberry Pico 2 W, provee 3.3 V via Pin 36, referencia “ground” via Pin 38, los 3 sensores de temperatura Analog Devices DS18B20 y una resistencia de pull-up en la linea de 3.3 V en el GPIO 15 (Pin 20) como parte de la linea de data en 1-Cable,
Un total de 3 sensores de temperatura Analog Devices DS18B20 comparten la linea 1-Cable para demonstrar la capacidad de comunicar data concurrentemente. Una plataforma de Raspberry Pico 2 W fue usada con una máquina de estados finitos PIO en el archivo onewire_library.pio para crear un protocolo de comunicación especializado de 1-Cable y accesado por la aplicación usando C SDK. Aqui esta el archivo onewire_library.pio que define la máquina de estados finitos PIO usada en este demo,
;
; Copyright (c) 2023 mjcross
;
; SPDX-License-Identifier: BSD-3-Clause
;
; Implements a Maxim 1-Wire bus with a GPIO pin.
;
; Place data words to be transmitted in the TX FIFO and read the results from the
; RX FIFO. To reset the bus execute a jump to 'reset_bus' using the opcode from
; the provided function.
;
; At 1us per cycle as initialised below the timings are those recommended by:
; https://www.analog.com/en/technical-articles/1wire-communication-through-software.html
;
; Notes:
; (1) The code will stall with the bus in a safe state if the FIFOs are empty/full.
; (2) The bus must be pulled up with an external pull-up resistor of about 4k.
; The internal GPIO resistors are too high (~50k) to work reliably for this.
; (3) Do not connect the GPIO pin directly to a bus powered at more than 3.3V.
.program onewire
.side_set 1 pindirs
PUBLIC reset_bus:
set x, 28 side 1 [15] ; pull bus low 16
loop_a: jmp x-- loop_a side 1 [15] ; 29 x 16
set x, 8 side 0 [6] ; release bus 7
loop_b: jmp x-- loop_b side 0 [6] ; 9 x 7
mov isr, pins side 0 ; read all pins to ISR (avoids autopush) 1
push side 0 ; push result manually 1
set x, 24 side 0 [7] ; 8
loop_c: jmp x-- loop_c side 0 [15] ; 25 x 16
.wrap_target
PUBLIC fetch_bit:
out x, 1 side 0 ; shift next bit from OSR (autopull) 1
jmp !x send_0 side 1 [5] ; pull bus low, branch if sending '0' 6
send_1: ; send a '1' bit
set x, 2 side 0 [8] ; release bus, wait for slave response 9
in pins, 1 side 0 [4] ; read bus, shift bit to ISR (autopush) 5
loop_e: jmp x-- loop_e side 0 [15] ; 3 x 16
jmp fetch_bit side 0 ; 1
send_0: ; send a '0' bit
set x, 2 side 1 [5] ; continue pulling bus low 6
loop_d: jmp x-- loop_d side 1 [15] ; 3 x 16
in null, 1 side 0 [8] ; release bus, shift 0 to ISR (autopush) 9
.wrap
;; (17 instructions)
% c-sdk {
static inline void onewire_sm_init (PIO pio, uint sm, uint offset, uint pin_num, uint bits_per_word) {
// create a new state machine configuration
pio_sm_config c = onewire_program_get_default_config (offset);
// Input Shift Register configuration settings
sm_config_set_in_shift (
&c,
true, // shift direction: right
true, // autopush: enabled
bits_per_word // autopush threshold
);
// Output Shift Register configuration settings
sm_config_set_out_shift (
&c,
true, // shift direction: right
true, // autopull: enabled
bits_per_word // autopull threshold
);
// configure the input and sideset pin groups to start at `pin_num`
sm_config_set_in_pins (&c, pin_num);
sm_config_set_sideset_pins (&c, pin_num);
// configure the clock divider for 1 usec per instruction
float div = clock_get_hz (clk_sys) * 1e-6;
sm_config_set_clkdiv (&c, div);
// apply the configuration and initialise the program counter
pio_sm_init (pio, sm, offset + onewire_offset_fetch_bit, &c);
// enable the state machine
pio_sm_set_enabled (pio, sm, true);
}
static inline uint onewire_reset_instr (uint offset) {
// encode a "jmp reset_bus side 0" instruction for the state machine
return pio_encode_jmp (offset + onewire_offset_reset_bus) | pio_encode_sideset (1, 0);
}
%}
La aplicación en main.c que usa este máquina de estado PIO es,
/**
* Copyright (c) 2023 mjcross
*
* SPDX-License-Identifier: BSD-3-Clause
**/
#include <stdio.h>
#include "pico/stdlib.h"
#include "pico/binary_info.h"
#include "onewire_library.h" // onewire library functions
#include "ow_rom.h" // onewire ROM command codes
#include "ds18b20.h" // ds18b20 function codes
// Demonstrates the PIO onewire driver by taking readings from a set of
// ds18b20 1-wire temperature sensors.
int main() {
stdio_init_all();
PIO pio = pio0;
uint gpio = 15;
OW ow;
uint offset;
// add the program to the PIO shared address space
if (pio_can_add_program (pio, &onewire_program)) {
offset = pio_add_program (pio, &onewire_program);
// claim a state machine and initialise a driver instance
if (ow_init (&ow, pio, offset, gpio)) {
// find and display 64-bit device addresses
int maxdevs = 10;
uint64_t romcode[maxdevs];
int num_devs = ow_romsearch (&ow, romcode, maxdevs, OW_SEARCH_ROM);
printf("Found %d devices\n", num_devs);
for (int i = 0; i < num_devs; i += 1) {
printf("\t%d: 0x%llx\n", i, romcode[i]);
}
putchar ('\n');
while (num_devs > 0) {
// start temperature conversion in parallel on all devices
// (see ds18b20 datasheet)
ow_reset (&ow);
ow_send (&ow, OW_SKIP_ROM);
ow_send (&ow, DS18B20_CONVERT_T);
// wait for the conversions to finish
while (ow_read(&ow) == 0);
// read the result from each device
for (int i = 0; i < num_devs; i += 1) {
ow_reset (&ow);
ow_send (&ow, OW_MATCH_ROM);
for (int b = 0; b < 64; b += 8) {
ow_send (&ow, romcode[i] >> b);
}
ow_send (&ow, DS18B20_READ_SCRATCHPAD);
int16_t temp = 0;
temp = ow_read (&ow) | (ow_read (&ow) << 8);
printf ("\t%d: %f C", i, temp / 16.0);
//Convert from C to F (Simple conversion for test purposes only)
float K1 = 1.8;
float K2 = 32.0;
float temp_F = temp*K1/16.0 + K2;
printf ("\t%d: %f F", i, temp_F);
}
putchar ('\n');
}
} else {
puts ("could not initialise the driver");
}
} else {
puts ("could not add the program");
}
while(true);
}
El programa fue compilado y programado en la plataforma Raspberry Pico 2 W como sigue a continuación,
DigiKey_Coffee_Cup # make -j8
DigiKey_Coffee_Cup # picotool load pio_onewire.uf2
Un terminal de minicom fue usado para monitorear las lecturas de temperatura en unidades de Celsius de 3 sensores de temperatura Analog Devices DS18B20.
DigiKey_Coffee_Cup # minicom -D /dev/ttyACM0
El Sparkfun Logic Analyzer que fue instalado en este enlace, fue usado para monitorar el protocolo de comunicación 1-Cable mostrado a continuación. Las lecturas de temperatura de estos 3 sensores de temperatura Analog Devices DS18B20 son obtenidos periódicamente como se ve a continuación,
El codigo de 64-Bit de identificación en ROM para cada uno de los 3 sensores de temperatura Analog Devices DS18B20 fueron confirmados por el téminal de minicom y también por la capura del mostrada previamente Sparkfun Logic Analyzer. La siguiente captura del Sparkfun Logic Analyzer that was setup in this link before muestra una magnificacion de la capa a nivel de red del sensor en el decoficador de protocolo de comunicación 1-Cable usando el sensor de temperatura DS28EA00 Analog Devices DS28EA00 que es similar el DS18B20, el proceso de Reset y detección de presencia, el comando ROM (0x55) (solamente el esclavo con la identificación correcta contesta; mientras que los otros esclavos en la line 1-Cable esperan por el pulse de inicialización (reset)). También se puede observar el primer sensor identificado de los 3 sensores de temperatura Analog Devices DS18B20 que comparten la linea 1-Cable,
El Sparkfun Logic Analyzer tiene muchos decoficadores definidos tales como el1-Cable (link layer), el 1-Cable (network layer), y en este caso se uso el decoficador interno similar al 1-Cable del sensor de temperatura Analog Devices DS28EA00 mostrado anteriormente. El Sparkfun Logic Analyzer facilita el diseño, las pruebas, y diagnóstico cuando sea necesario de este tipo de sistemas.
Se demonstro como conectar 3 sensores de temperatura Analog Devices DS18B20 en la linea 1-Cable usando la Raspberry Pico 2 W y el C SDK. El sensor de temperatura DS18B20 es una excelente desición para diseños que requieran sensores distribuidos en los que hayan restricciones de alambrado. El modo parasítico de potencia requiere un total de solamente 2 Pins para su operación (DQ and GND) y esto simplifica el diseño de estos sistemas. Este versátil sensor de temperatura Analog Devices DS18B20 esta disponible en DigiKey.
Otro sensor de temperatura con características similares es el Analog Devices DS28EA00
con una mejora implementación de la interfaz de 1-Cable con histéresis y un filtro de transientes, con 2 programables GPIO, con transición de estados de cadenas de sensores para detectar automáticamente la presencia física de estos sensores en su red. El sensor de temperatura Analog Devices DS28EA00 esta también disponible en DigiKey. Que tenga un buen día.
Este artículo está disponible en inglés aquí.
This article is available in english here.








