← Índice del curso

Comunicación entre Dispositivos · Tema 21 · 1-Wire

1-Wire: un cable de datos

I²C ahorró pines pasando a dos hilos. 1-Wire va un paso más lejos: un único cable de datos, más la masa, para hablar con decenas de dispositivos, que además pueden alimentarse de esa misma línea. A cambio, todo se hace con tiempos medidos en microsegundos. Vamos a ver cómo se logra: el pulso de reset y la presencia, los intervalos de tiempo en los que viaja cada bit, el número de serie único de 64 bits que reemplaza a las direcciones, el algoritmo con el que el maestro descubre qué hay conectado y cómo se arma una red de sensores de temperatura DS18B20.

01 · Un solo hilo

Un cable para todos

1-Wire lo creó Dallas Semiconductor (hoy parte de Analog Devices, antes Maxim) para dispositivos baratos y chicos que se conectan con la menor cantidad de cables posible: sensores de temperatura, identificadores electrónicos (llaves de acceso tipo iButton), memorias pequeñas, interruptores. El nombre es literal: un hilo de datos. Siempre hace falta además una referencia de masa, de modo que un dispositivo se conecta con dos conductores, y hasta con uno solo y la tierra del entorno en algunas aplicaciones, pero el bus es una única línea compartida para entrada, salida, reloj y, si se quiere, alimentación.

Para lograrlo, el protocolo hace tres cosas distintas de lo que vimos hasta ahora:

  • No tiene reloj aparte. Los bits se codifican en cuánto tiempo el maestro mantiene la línea en bajo. Todo se mide en microsegundos y los dispositivos usan un oscilador interno para interpretar esos tiempos.
  • No hay direcciones configurables. Cada dispositivo viene con un número de serie único de 64 bits grabado en fábrica, y el maestro lo usa como dirección. No hay pines que configurar ni choques de direcciones, pero hay que descubrir qué números hay en la red.
  • El maestro lleva el control de cada bit. Un dispositivo nunca habla por iniciativa propia (salvo para anunciar su presencia después de un reset): siempre responde dentro de un intervalo que inicia el maestro.
Comparación con los otros buses de pocos hilos.
UARTSPII²C1-Wire
Conductores2 (TX, RX) + masa3 + CS por esclavo + masa2 + masa1 (DQ) + masa
RelojNoSí, línea aparteSí, línea aparteNo: tiempos en la propia línea
Identidad de cada dispositivo—Línea CSDirección de 7 bits (configurable)ROM única de 64 bits
Alimentación por la líneaNoNoNoSí (modo parásito)
Velocidad típicahasta ~1 Mbit/s1 a 50 Mbit/s0,1 a 1 Mbit/s~15 kbit/s
Alcance habitualmetroscentímetrosdecenas de cmdecenas de metros

1-Wire es el más lento de todos, a propósito: está pensado para leer una temperatura cada tanto, no para mover datos. A cambio ofrece cables largos y baratos, sin direcciones que configurar y con la posibilidad de colgar muchos sensores de un solo par de cables.

02 · Cableado

La línea y la alimentación

Red 1-Wire con tres sensores Un microcontrolador maneja una única línea de datos DQ con una resistencia de pull-up de 4,7 kiloohms a la alimentación. Tres sensores DS18B20 se conectan en paralelo a esa línea y comparten masa. En el modo alimentado externamente, cada sensor también conecta su VDD a la alimentación; en el modo parásito, VDD va a masa. Microcontrolador 1 pin (GPIO 4) colector abierto DS18B20 ROM A DQ · GND · VDD DS18B20 ROM B DQ · GND · VDD DS18B20 ROM C DQ · GND · VDD VDD (3,3 V o 5 V)Rp = 4,7 kΩ DQGND Una sola línea de datos, más masa. Cada sensor se reconoce por su número de serie único de 64 bits.

La línea de datos (DQ) es de colector abierto, igual que SDA y SCL en I²C (tema 16): el maestro y los dispositivos solo pueden bajarla o soltarla, y una resistencia de pull-up la sube. El valor típico es 4,7 kΩ a la alimentación (3,3 V o 5 V). Como cualquiera puede bajarla, la línea es un Y cableado, lo que más adelante permite que el maestro descubra los dispositivos por colisión de bits. En reposo, la línea está en alto.

Hay dos formas de alimentar a un dispositivo:

Alimentación externa

Se conectan tres cables: DQ, GND y VDD (el DS18B20 admite de 3,0 a 5,5 V). Es el modo más robusto y el que conviene siempre que se pueda. Permite además saber cuándo terminó una conversión, porque el dispositivo contesta a las lecturas.

Alimentación parásita

Se conectan solo DQ y GND, y el pin VDD del sensor va a masa. El dispositivo carga un pequeño condensador interno mientras la línea está en alto, y vive de él durante los bajos. Ahorra un cable, pero en las operaciones que consumen más (una conversión de temperatura, que llega a 1,5 mA) la pull-up no alcanza, y hace falta un pull-up fuerte: un transistor que conecte DQ directamente a VDD durante toda la operación.

Algunas pautas para la red:

  • Topología lineal: un cable principal con los sensores colgados a lo largo, o ramas muy cortas. Las estrellas con ramas largas producen reflexiones y fallas difíciles de explicar.
  • Cable de par trenzado (un par para DQ y GND, mejor con una masa extra), bien separado de motores, relés y otras fuentes de ruido. En instalaciones largas se usa un cable de red (UTP) con DQ en un par y GND en el otro.
  • La longitud admisible depende de la capacidad (como en I²C) y de los tiempos de subida: con cables de decenas de metros se baja la pull-up (de 4,7 kΩ a 2,2 kΩ o 1,5 kΩ) y se verifica con osciloscopio. Con un cable de calidad y una topología lineal se llegan a decenas de metros; más allá, conviene un maestro especializado o repetidores.
  • Más dispositivos, más capacidad y más corriente: con muchos sensores en modo parásito, la conversión simultánea exige un pull-up fuerte potente.

03 · Antes de cualquier cosa

Reset y presencia

Pulso de reset y pulso de presencia El maestro baja la línea durante al menos 480 microsegundos y la suelta. Entre 15 y 60 microsegundos después, los dispositivos presentes bajan la línea durante 60 a 240 microsegundos. El maestro lee la línea unos 70 microsegundos después de soltarla: un cero significa que hay alguien. El intervalo completo dura al menos 960 microsegundos. Maestro Dispositivos Línea DQ (lo que se ve) el maestro lee (≈ 70 µs) reset: ≥ 480 µs presencia: 60 a 240 µs 15 a 60 µs recuperación hasta ≥ 960 µs en total

Toda comunicación empieza con una secuencia de reset. Tiene dos partes y sirve para dos cosas: poner a todos los dispositivos en un estado conocido y saber si hay alguno conectado.

  1. Pulso de reset. El maestro baja la línea durante al menos 480 µs y la suelta. Cualquier dispositivo que lo vea reinicia su máquina de estados: la conversación anterior queda descartada.
  2. Pulso de presencia. Entre 15 y 60 µs después de que el maestro soltó la línea, cada dispositivo presente la baja durante 60 a 240 µs. Como todos hacen lo mismo a la vez, la línea muestra un solo pulso.
  3. Lectura del maestro. A los 70 µs de soltar la línea, el maestro la lee: si está en bajo, hay al menos un dispositivo. Después espera hasta completar un mínimo de 480 µs de recuperación (960 µs en total desde el comienzo del reset).

El instante de lectura (70 µs) está elegido para caer dentro del pulso de presencia en el peor caso: aun si un dispositivo tarda 60 µs en empezar, sigue en bajo hasta los 120, y si empieza a los 15 y dura solo 60, termina a los 75. Por eso el maestro lee a los 70 µs.

Dos limitaciones. La presencia dice que hay al menos un dispositivo, no cuántos ni cuáles: todos responden a la vez y el resultado es una sola línea baja. Y el tiempo de subida de la línea importa: si la capacidad del cable es grande y la pull-up débil, la línea sube tan lentamente que los dispositivos ven el flanco tarde, su pulso de presencia se retrasa y el maestro puede leer a los 70 µs una línea que todavía no bajó (una presencia perdida). Algunos dispositivos admiten además un modo más rápido (Overdrive, unos 125 kbit/s); el DS18B20 no.

04 · Un bit a la vez

Intervalos de tiempo

Intervalos de tiempo de 1-Wire Cuatro formas de onda de un intervalo de unos 70 microsegundos. Escribir un 1: el maestro baja la línea unos 6 microsegundos. Escribir un 0: la baja unos 60 microsegundos. Leer: el maestro baja la línea unos 6 microsegundos y la suelta; si el dispositivo envía un 0, la mantiene en bajo hasta unos 15 microsegundos y el maestro lee antes de ese momento. Escribir 1 Escribir 0 Leer 1 Leer 0 el dispositivo muestrea entre 15 y 60 µs el maestro lee antes de 15 µs 1 a 15 µs ≥ 60 µs el dispositivo mantiene el 0 hasta ~15 µs Cada intervalo dura al menos 60 µs y deja 1 µs de recuperación: en la práctica, 70 µs.

Después del reset, todo se transmite en intervalos de tiempo (time slots), cada uno de un bit y de unos 60 a 70 µs. El maestro inicia cada intervalo bajando la línea, y lo que ocurre después depende de si escribe o lee:

  • Escribir un 1. El maestro baja la línea un tiempo corto (de 1 a 15 µs) y la suelta. Para el dispositivo, un pulso corto es un 1.
  • Escribir un 0. El maestro baja la línea y la mantiene al menos 60 µs (hasta unos 120 µs). Un pulso largo es un 0.
  • Leer. El maestro baja la línea un instante (1 a 2 µs, típicamente 6 µs) y la suelta. Si el dispositivo quiere enviar un 0, la mantiene en bajo hasta unos 15 µs contados desde el flanco inicial; si quiere enviar un 1, no hace nada y la línea sube sola. El maestro tiene que leer antes de que pasen 15 µs desde el flanco, que es la ventana en la que el 0 todavía se ve.

El dispositivo muestrea la línea entre los 15 y los 60 µs después del flanco de bajada: si ya subió, es un 1; si sigue baja, un 0. Por eso un pulso de entre 15 y 60 µs es ambiguo y está prohibido. Cada intervalo debe durar al menos 60 µs, con un mínimo de 1 µs de recuperación entre uno y otro. Los bits viajan con el bit menos significativo primero (LSB first), al revés que en SPI e I²C.

Tiempos recomendados para un maestro por software (velocidad estándar, en µs; valores de la nota de aplicación AN126 de Maxim).
OperaciónLínea en bajoLínea suelta (con lectura)Intervalo total
Escribir 166470
Escribir 0601070
Leer un bit69 y se lee; luego 5570
Reset y presencia48070 y se lee; luego 410960

Con 70 µs por bit, un byte tarda 560 µs y la velocidad efectiva es de unos 14 kbit/s. Estos tiempos se cumplen desde el software, así que las interrupciones tienen que estar deshabilitadas durante cada intervalo: una interrupción de 100 µs en medio de un pulso de escritura alarga el 1 hasta convertirlo en 0. Las bibliotecas como OneWire usan acceso directo a los puertos y deshabilitan interrupciones por esa razón; con un microcontrolador rápido y un sistema operativo (como el ESP32) conviene una biblioteca bien probada, o el periférico RMT o una UART configurada especialmente para generar estos pulsos.

05 · Quién es quién

La identidad de 64 bits

Cada dispositivo 1-Wire trae una ROM de 64 bits grabada con láser en fábrica, única en el mundo. Tiene tres partes y se transmite en este orden, cada byte con el bit menos significativo primero:

Estructura de la ROM de 64 bits.
BytesContenidoEjemplo
1Código de familia: el tipo de dispositivo0x28 (DS18B20)
2 a 7Número de serie de 48 bitsAA 10 20 30 40 50
8CRC-8 de los 7 bytes anteriores0x1F

El código de familia dice qué clase de dispositivo es: 0x28 un sensor de temperatura DS18B20, 0x10 el DS18S20 (el modelo anterior, de 9 bits), 0x22 el DS1822, 0x01 un número de serie puro (DS2401), 0x3A un interruptor doble (DS2413) y 0x23 una memoria EEPROM (DS2433). Una red real mezcla familias, y el programa debe mirar el primer byte antes de interpretar nada.

El CRC-8 usa el polinomio x8 + x5 + x4 + 1. Se calcula byte a byte sobre los primeros siete bytes y debe coincidir con el octavo. Con un CRC bien hecho, calcular el CRC sobre los ocho bytes completos da 0. El mismo CRC protege la memoria de trabajo (scratchpad) del DS18B20 y se usa en la mayoría de los dispositivos de la familia. Su implementación, bit a bit con el polinomio reflejado 0x8C, está en la sección 09. Es la primera línea de defensa contra los errores de lectura en una línea larga.

Con la ROM, el maestro puede dirigirse a un dispositivo después de cada reset con los comandos de ROM:

Comandos de ROM, comunes a todos los dispositivos 1-Wire.
ComandoCódigoQué hace
Read ROM0x33El dispositivo envía su ROM. Solo sirve con un único dispositivo en la línea: con varios, contestan a la vez y llega el AND bit a bit de las ROM.
Match ROM0x55Seguido de 64 bits (una ROM): solo ese dispositivo queda seleccionado y atiende el comando siguiente.
Skip ROM0xCCSe dirige a todos los dispositivos sin identificar a ninguno. Útil con uno solo, o para una orden que todos deben ejecutar (iniciar la conversión de todos los sensores). No sirve para leer con varios.
Search ROM0xF0Inicia el algoritmo de búsqueda que descubre todas las ROM de la red.
Alarm Search0xECComo Search ROM, pero solo participan los dispositivos con una condición de alarma (en el DS18B20, una temperatura fuera de los límites TH y TL).

Una comunicación típica con un dispositivo concreto es entonces: reset → Match ROM (0x55) + 8 bytes de ROM → comando del dispositivo → datos. Con un solo dispositivo se acorta a reset → Skip ROM (0xCC) → comando.

06 · Cómo se descubre una red

Descubrir la red

El maestro no sabe qué ROM hay en la línea. Para averiguarlo usa el algoritmo de búsqueda, que aprovecha el Y cableado. Después de un reset y del comando Search ROM (0xF0), por cada uno de los 64 bits de la ROM se hacen tres intervalos:

  1. El maestro lee un bit: todos los dispositivos aún en la búsqueda envían el bit actual de su ROM. Como la línea es un Y, el maestro ve un 0 si alguno tiene un 0.
  2. El maestro lee un segundo bit: ahora todos envían el complemento de su bit. Ve un 0 si alguno tenía un 1.
  3. Con los dos resultados decide, y escribe un bit que indica cuál rama seguir: los dispositivos cuyo bit no coincide se retiran de la búsqueda hasta el próximo reset.
Qué significan los dos bits leídos en cada posición de la ROM.
Bit leídoComplemento leídoSignificaEl maestro…
01Todos los dispositivos activos tienen un 0 en esta posiciónescribe 0 y sigue
10Todos tienen un 1escribe 1 y sigue
00Discrepancia: algunos tienen 0 y otros 1elige una rama (la 0 primero), y recuerda la posición para volver
11Ningún dispositivo contestatermina: error o red vacía

Cada pasada identifica un dispositivo completo (64 bits) y anota la última posición con discrepancia. La pasada siguiente repite el camino hasta esa posición y, ahí, toma la otra rama. Es un recorrido en profundidad de un árbol binario cuyas hojas son las ROM. Con tres dispositivos 10-01-02-…, 28-AA-10-…-50 y 28-AB-11-… la búsqueda encuentra tres ROM en tres pasadas: hay una discrepancia en el bit 3 (el código de familia: 0x28 frente a 0x10) y otra en el bit 8 (el primer bit del número de serie de los dos sensores de familia 0x28). Por la regla de empezar por el 0, aparece primero el 0x10 y después los 0x28.

Lo que cuesta: cada pasada son un reset (960 µs), el comando 0xF0 (560 µs) y 64 × 3 = 192 intervalos de 70 µs (13,44 ms): casi 15 ms por dispositivo. Una red de 10 sensores se descubre en unos 150 ms, lo que se hace una vez al arrancar y se guarda. El tiempo manda: en la operación normal no se busca, se usan las ROM ya conocidas.

Una consecuencia de diseño: el orden en que aparecen las ROM no está ligado al lugar físico del sensor. Depende de los números de serie, y cambia si se agrega o se retira un sensor. Las bibliotecas que ofrecen «el sensor número 0» o «el número 1» identifican a cada sensor por su posición en la lista, y esa posición puede cambiar. La forma correcta es identificar cada sensor por su ROM: durante la instalación se lee la ROM de cada uno (calentándolo, o conectándolo de a uno) y se anota en una tabla qué ROM corresponde a qué lugar («agua de entrada», «ambiente», «salida»).

07 · El caso de estudio

El DS18B20 en la práctica

El DS18B20 es el sensor 1-Wire más usado: mide de −55 °C a +125 °C con una exactitud de ±0,5 °C entre −10 °C y +85 °C, y la resolución se elige de 9 a 12 bits. Viene en encapsulado TO-92 (como un transistor) y en sondas impermeables de acero inoxidable. Tiene una memoria de trabajo, el scratchpad, de 9 bytes:

Scratchpad del DS18B20 (se lee con el comando 0xBE).
ByteContenido
0Temperatura, byte bajo
1Temperatura, byte alto
2TH: límite superior de alarma
3TL: límite inferior de alarma
4Configuración: los bits 6 y 5 eligen la resolución (00 = 9 bits, 01 = 10, 10 = 11, 11 = 12)
5, 6, 7Reservados
8CRC-8 de los bytes 0 a 7

La temperatura es un entero de 16 bits en complemento a dos, con unidades de 1/16 °C (en 12 bits): el valor se divide por 16. Por ejemplo, 0x0191 son 401/16 = +25,0625 °C; 0x07D0, +125 °C; 0xFF5E, −162/16 = −10,125 °C; y 0xFC90, −55 °C. Con menos bits de resolución, los bits menos significativos quedan indefinidos y se enmascaran antes de dividir.

Resolución y tiempo máximo de conversión del DS18B20.
ResoluciónPasoTiempo de conversión (máx.)
9 bits0,5 °C93,75 ms
10 bits0,25 °C187,5 ms
11 bits0,125 °C375 ms
12 bits (por defecto)0,0625 °C750 ms

La secuencia de una medición es siempre la misma:

  1. Iniciar la conversión. Reset, 0xCC (Skip ROM, para todos a la vez) y 0x44 (Convert T). Una sola orden pone a medir a todos los sensores de la red al mismo tiempo; con la alimentación parásita, además, el maestro debe activar el pull-up fuerte durante toda la conversión.
  2. Esperar. Hasta 750 ms a 12 bits. Con alimentación externa se pueden hacer lecturas de un bit: el sensor contesta 0 mientras mide y 1 al terminar. En modo parásito no se puede consultar, y se espera un tiempo fijo.
  3. Leer cada sensor. Para cada uno: reset, 0x55 + su ROM (Match ROM), 0xBE (Read Scratchpad) y nueve bytes.
  4. Verificar el CRC del scratchpad (el byte 8 contra el CRC de los bytes 0 a 7). Si no coincide, la lectura se descarta y se repite.
  5. Convertir: armar el entero con signo, enmascarar según la resolución y dividir por 16.

Tres trampas conocidas. El valor 85 °C (0x0550) es el que tiene el sensor al encenderse: si se lee sin haber esperado la conversión, o si falló la alimentación a mitad de ella, se obtiene 85,0 aunque haga frío. Un 85 exacto es sospechoso. Una línea sin dispositivos lee todos unos (0xFFFF = −0,0625 °C, o la biblioteca devuelve un valor como −127 °C para marcar un sensor desconectado): el CRC y el pulso de presencia lo delatan. Y leer los sensores uno por uno con una conversión cada uno es lento: con ocho sensores a 12 bits serían seis segundos; con un único 0xCC 0x44 inicial, 750 ms para todos.

Para fijar la resolución se escribe el scratchpad con 0x4E (TH, TL y configuración, tres bytes) y, si se quiere que sobreviva a un corte de energía, se copia a la EEPROM interna con 0x48 (que también necesita el pull-up fuerte si el sensor está en modo parásito, unos 10 ms). El comando 0xB4 pregunta si el sensor tiene alimentación parásita o externa.

08 · Con el microcontrolador

Con el microcontrolador

El primer programa implementa el protocolo a mano, con los tiempos de la tabla de la sección 04, y lee la ROM de un único sensor conectado. Sirve para ver que todo lo anterior se reduce a bajar y soltar un pin con esperas. Se usa el mismo recurso del tema 16 para manejar un colector abierto: OUTPUT en bajo para bajar, INPUT para soltar.

const byte PIN_DQ = 4;                      // con pull-up de 4,7 kΩ a 3,3 V

inline void bajar()  { pinMode(PIN_DQ, OUTPUT); digitalWrite(PIN_DQ, LOW); }
inline void soltar() { pinMode(PIN_DQ, INPUT); }              // la pull-up externa sube la línea

bool owReset() {                            // true si hay al menos un dispositivo
    noInterrupts();
    bajar();  delayMicroseconds(480);
    soltar(); delayMicroseconds(70);
    bool presencia = !digitalRead(PIN_DQ);  // un dispositivo la tiene en bajo
    interrupts();
    delayMicroseconds(410);                 // completa los 960 µs
    return presencia;
}

void owEscribirBit(bool bit) {
    noInterrupts();
    if (bit) { bajar(); delayMicroseconds(6);  soltar(); delayMicroseconds(64); }   // pulso corto = 1
    else     { bajar(); delayMicroseconds(60); soltar(); delayMicroseconds(10); }   // pulso largo = 0
    interrupts();
}

bool owLeerBit() {
    noInterrupts();
    bajar();  delayMicroseconds(6);
    soltar(); delayMicroseconds(9);         // el dispositivo mantiene el 0 hasta ~15 µs desde el flanco
    bool bit = digitalRead(PIN_DQ);
    interrupts();
    delayMicroseconds(55);                  // completa el intervalo de 70 µs
    return bit;
}

void owEscribirByte(byte b) { for (byte i = 0; i < 8; i++) owEscribirBit((b >> i) & 1); }   // LSB primero
byte owLeerByte() {
    byte b = 0;
    for (byte i = 0; i < 8; i++) b |= owLeerBit() << i;
    return b;
}

byte crc8(const byte *d, byte n) {          // polinomio x^8 + x^5 + x^4 + 1 (0x8C reflejado)
    byte crc = 0;
    for (byte i = 0; i < n; i++) {
        byte b = d[i];
        for (byte k = 0; k < 8; k++) {
            byte mezcla = (crc ^ b) & 1;
            crc >>= 1;
            if (mezcla) crc ^= 0x8C;
            b >>= 1;
        }
    }
    return crc;
}

void setup() {
    Serial.begin(115200);
    soltar();
    if (!owReset()) { Serial.println("Sin presencia: revisar pull-up, cableado y masa"); return; }
    owEscribirByte(0x33);                   // Read ROM: solo con un único dispositivo en la línea
    byte rom[8];
    for (byte i = 0; i < 8; i++) rom[i] = owLeerByte();
    for (byte i = 0; i < 8; i++) { if (rom[i] < 16) Serial.print('0'); Serial.print(rom[i], HEX); Serial.print(i < 7 ? "-" : "\n"); }
    Serial.println(crc8(rom, 7) == rom[7] ? "CRC correcto" : "CRC erróneo: lectura dañada o hay más de un dispositivo");
    Serial.print("Familia 0x"); Serial.println(rom[0], HEX);
}

void loop() {}

Este código es didáctico: en un ESP32 el cambio de pinMode y las rutinas de digitalWrite son lo bastante lentas como para rozar los límites de tiempo, y noInterrupts() no frena las tareas del otro núcleo. En un proyecto real se usa la biblioteca OneWire, que hace lo mismo con acceso directo a los registros. El segundo programa la usa para descubrir la red, medir todos los sensores a la vez y leer cada uno por su ROM, con verificación del CRC:

#include <OneWire.h>

OneWire ds(4);                              // pin 4, pull-up de 4,7 kΩ
const byte MAX_SENSORES = 8;
byte roms[MAX_SENSORES][8];
byte cantidad = 0;

void imprimirRom(const byte *rom) {
    for (byte i = 0; i < 8; i++) { if (rom[i] < 16) Serial.print('0'); Serial.print(rom[i], HEX); if (i < 7) Serial.print('-'); }
}

void descubrir() {                          // se hace una vez al arrancar
    byte rom[8];
    cantidad = 0;
    ds.reset_search();
    while (cantidad < MAX_SENSORES && ds.search(rom)) {
        if (OneWire::crc8(rom, 7) != rom[7]) { Serial.println("ROM con CRC inválido: se descarta"); continue; }
        if (rom[0] != 0x28) { Serial.print("No es un DS18B20, familia 0x"); Serial.println(rom[0], HEX); continue; }
        memcpy(roms[cantidad++], rom, 8);
    }
}

void iniciarConversionDeTodos() {
    ds.reset();
    ds.skip();                              // 0xCC: todos los sensores a la vez
    ds.write(0x44, 0);                      // 0x44: Convert T (el 0 indica alimentación externa)
}

bool leerTemperatura(const byte *rom, float &celsius) {
    byte sp[9];
    if (!ds.reset()) return false;          // nadie contesta
    ds.select(rom);                         // 0x55 + 8 bytes de ROM
    ds.write(0xBE);                         // Read Scratchpad
    ds.read_bytes(sp, 9);
    if (OneWire::crc8(sp, 8) != sp[8]) return false;           // lectura dañada
    int16_t raw = (sp[1] << 8) | sp[0];
    switch ((sp[4] >> 5) & 3) {             // los bits menos significativos son indefinidos si la resolución es menor
        case 0: raw &= ~7; break;           //  9 bits
        case 1: raw &= ~3; break;           // 10 bits
        case 2: raw &= ~1; break;           // 11 bits
    }
    celsius = raw / 16.0;
    return true;
}

void setup() {
    Serial.begin(115200);
    descubrir();
    Serial.print(cantidad); Serial.println(" sensor(es) DS18B20:");
    for (byte i = 0; i < cantidad; i++) { Serial.print("  "); imprimirRom(roms[i]); Serial.println(); }
}

void loop() {
    iniciarConversionDeTodos();
    delay(750);                             // 12 bits: hasta 750 ms para todos
    for (byte i = 0; i < cantidad; i++) {
        float t;
        imprimirRom(roms[i]); Serial.print(": ");
        if (!leerTemperatura(roms[i], t)) Serial.println("sin respuesta o CRC erróneo");
        else if (t == 85.0) Serial.println("85 °C: valor de arranque, ¿terminó la conversión?");
        else { Serial.print(t, 2); Serial.println(" C"); }
    }
    delay(2000);
}

Cuatro decisiones del código. El CRC se verifica dos veces: en cada ROM descubierta y en cada scratchpad leído. La conversión se inicia con un solo Skip ROM para todos los sensores y se espera una vez. Los sensores se identifican por su ROM, no por un número de orden. Y el 85,0 se trata como sospechoso. Si los sensores estuvieran en modo parásito, ds.write(0x44, 1) mantiene la línea en alto después del comando para alimentar la conversión.

09 · Analogía con programación

La red 1-Wire en Python

Los puntos finos de 1-Wire (el CRC, el orden de los bits, el algoritmo de búsqueda, la conversión de la temperatura y los tiempos) se pueden modelar en pocas líneas. El programa siguiente implementa el CRC-8 bit a bit, arma las ROM de cuatro sensores, ejecuta el algoritmo de búsqueda sobre una red simulada (con el Y cableado de la línea incluido), decodifica temperaturas del scratchpad y calcula cuánto tarda cada operación.

Python en tu navegador. Los bloques son editables: cambiá los valores y presioná «Ejecutar Python». La primera vez tarda unos segundos en cargar.

def crc8(datos):
    """CRC-8 de Dallas/Maxim: x^8 + x^5 + x^4 + 1, bit a bit con el polinomio reflejado 0x8C."""
    crc = 0
    for b in datos:
        for _ in range(8):
            mezcla = (crc ^ b) & 1
            crc >>= 1
            if mezcla:
                crc ^= 0x8C
            b >>= 1
    return crc


def rom(familia, serie):
    cuerpo = [familia, *serie]
    return bytes(cuerpo + [crc8(cuerpo)])


def formato(r):
    return "-".join(f"{b:02X}" for b in r)


def bits_lsb(b):
    return "".join(str((b >> i) & 1) for i in range(8))


def bits_de_rom(r):
    return [(r[i // 8] >> (i % 8)) & 1 for i in range(64)]       # 64 bits, LSB primero dentro de cada byte


def buscar(roms):
    """Algoritmo de búsqueda: recorre el árbol de bits, empezando por la rama 0 en cada discrepancia."""
    encontradas, discrepancias = [], []

    def recorrer(activos, bit):
        if bit == 64:
            encontradas.append(activos[0][0])
            return
        ceros = [d for d in activos if d[1][bit] == 0]
        unos = [d for d in activos if d[1][bit] == 1]
        if ceros and unos:                                 # la línea (Y cableado) daría 0 en el bit y 0 en el complemento
            discrepancias.append(bit)
            recorrer(ceros, bit + 1)
            recorrer(unos, bit + 1)
        else:
            recorrer(ceros or unos, bit + 1)

    recorrer([(r, bits_de_rom(r)) for r in roms], 0)
    return encontradas, discrepancias


def temperatura(raw):
    if raw & 0x8000:
        raw -= 65536                                       # complemento a dos
    return raw / 16


A = rom(0x28, [0xAA, 0x10, 0x20, 0x30, 0x40, 0x50])
B = rom(0x28, [0xAB, 0x11, 0x22, 0x33, 0x44, 0x55])
C = rom(0x10, [0x01, 0x02, 0x03, 0x04, 0x05, 0x06])
D = rom(0x28, [0xAA, 0x10, 0x20, 0x30, 0x40, 0x51])

print("CRC de un ROM de ejemplo del fabricante (02 1C B8 01 00 00 00):", f"{crc8([0x02, 0x1C, 0xB8, 0x01, 0, 0, 0]):#04x}")
print("CRC del scratchpad de arranque (50 05 4B 46 7F FF 0C 10):", f"{crc8([0x50, 0x05, 0x4B, 0x46, 0x7F, 0xFF, 0x0C, 0x10]):#04x}")
print("Bits LSB primero:", {f"{c:#04x}": bits_lsb(c) for c in (0x33, 0xCC, 0x44, 0xBE)})

print()
for nombre, r in (("A", A), ("B", B), ("C", C), ("D", D)):
    print(f"ROM {nombre}: {formato(r)}  (CRC sobre los 8 bytes = {crc8(r):#04x})")

print()
for titulo, red in (("A, B y C", [A, B, C]), ("A y D", [A, D]), ("A, B, C y D", [A, B, C, D])):
    hallados, disc = buscar(red)
    print(f"Búsqueda con {titulo}: discrepancias en los bits {disc}")
    for r in hallados:
        print("   ", formato(r))

print()
and_rom = bytes(a & b for a, b in zip(A, B))
print(f"Read ROM con A y B a la vez (AND): {formato(and_rom)} -> CRC calculado {crc8(and_rom[:7]):#04x}, recibido {and_rom[7]:#04x}")

print()
for raw in (0x0191, 0x07D0, 0xFF5E, 0xFC90, 0x0550):
    print(f"scratchpad 0x{raw:04X} -> {temperatura(raw):9.4f} °C")

print()
intervalo, byte, reset = 70, 8 * 70, 960
print(f"Intervalo {intervalo} µs, byte {byte} µs, reset {reset} µs")
operaciones = {
    "Read ROM (reset + 0x33 + 8 bytes)": reset + 9 * byte,
    "Skip ROM + Convert T (reset + 2 bytes)": reset + 2 * byte,
    "Match ROM + Convert T (reset + 10 bytes)": reset + 10 * byte,
    "leer un scratchpad (reset + 0xCC + 0xBE + 9 bytes)": reset + 11 * byte,
    "una pasada de la búsqueda (reset + 0xF0 + 192 intervalos)": reset + byte + 192 * intervalo,
}
for nombre, us in operaciones.items():
    print(f"  {nombre:58} {us / 1000:7.2f} ms")

Resultado: el CRC-8 pasa dos pruebas conocidas: para el ROM de ejemplo del fabricante (02 1C B8 01 00 00 00) da 0xa2 y para el scratchpad de arranque del DS18B20 (50 05 4B 46 7F FF 0C 10) da 0x1c. Los bits LSB primero de los comandos son 11001100 para 0x33, 00110011 para 0xCC, 00100010 para 0x44 y 01111101 para 0xBE. Las ROM son A = 28-AA-10-20-30-40-50-1F, B = 28-AB-11-22-33-44-55-02, C = 10-01-02-03-04-05-06-7B y D = 28-AA-10-20-30-40-51-41, y el CRC calculado sobre los ocho bytes de cada una vale 0. La búsqueda con A, B y C encuentra primero C, luego A y luego B, con discrepancias en los bits 3 y 8; con A y D (que solo difieren en el último bit del número de serie), una discrepancia en el bit 48; con los cuatro, en los bits 3, 8 y 48, y el orden C, A, D, B. Un Read ROM con A y B a la vez devuelve el AND 28-AA-10-20-30-40-50-02: el CRC calculado es 0x1f pero llega 0x02, y el desacuerdo delata que hay más de un dispositivo. Los scratchpad 0x0191, 0x07D0, 0xFF5E, 0xFC90 y 0x0550 son +25,0625, +125, −10,125, −55 y +85 °C. Con 70 µs por intervalo, un byte son 560 µs y Read ROM tarda 6,00 ms; iniciar la conversión de todos con Skip ROM, 2,08 ms; con Match ROM, 6,56 ms; leer un scratchpad, 7,12 ms; y una pasada de la búsqueda, 14,96 ms.

Observá que la búsqueda no necesita ningún dato previo: solo la línea y el Y cableado. Y que el CRC detecta lo que de otro modo pasaría inadvertido, como dos sensores respondiendo a la vez.

10 · Exploración interactiva

Laboratorio: línea, intervalos, temperatura y búsqueda

El laboratorio tiene cuatro herramientas. La primera es el reset y la presencia: elegís la longitud del pulso, la pull-up y el cable, y ves si la presencia llega a tiempo. La segunda muestra qué interpreta el dispositivo según cuánto tiempo se baja la línea en un intervalo de escritura o de lectura. La tercera decodifica el scratchpad del DS18B20. La cuarta es la búsqueda: elegís qué sensores hay conectados y ves en qué orden aparecen sus ROM.

1. Reset y presencia

Capacidad · tiempo de subida—
Lectura del maestro a los 70 µs—
Duración mínima de la secuencia—
Veredicto—

Elegí el reset, los dispositivos y el cableado.

2. Intervalos de escritura y de lectura

Forma de onda—
Lo que se entiende—
Duración del intervalo—
Veredicto—

Elegí la operación y los tiempos.

3. Temperatura del DS18B20

Entero de 16 bits con signo—
Temperatura—
Paso · tiempo de conversión—
Veredicto—

Escribí los dos bytes de la temperatura.

4. Búsqueda de ROM

ROM halladas, en orden—
Posiciones con discrepancia (bit)—
Duración de la búsqueda—
Read ROM (0x33) con estos sensores—
Veredicto—

Elegí qué sensores hay en la línea.

En la herramienta 1, la capacidad es de 100 pF por metro más 50 pF de los dispositivos, y el tiempo de subida es 1,2 · R · C (hasta el 70 % de la alimentación); los umbrales del veredicto son reglas prácticas: hasta 10 µs es seguro, hasta 40 µs es dudoso y más ya pierde la presencia. En la 2, el dispositivo toma el estado de la línea entre 15 y 60 µs después del flanco, y para un 0 en lectura la mantiene unos 15 µs. En la 3, el valor se enmascara según la resolución. En la 4, un intervalo es de 70 µs.

Recorrido guiado

  1. Con los valores iniciales (reset de 480 µs, un dispositivo, 4,7 kΩ, 1 m), el cable suma 150 pF y la línea sube en 0,8 µs. A los 70 µs el maestro lee 0: presencia. La secuencia dura 960 µs como mínimo. «Presencia detectada».
  2. Pasá a «ninguno»: lee 1 (la pull-up mantiene la línea en alto) y el veredicto es «Sin presencia». Con «varios»: también 0, un único pulso: la presencia no cuenta dispositivos.
  3. Con el reset en 240 µs: «Reset demasiado corto»: la especificación pide 480 µs como mínimo y los dispositivos pueden no reconocerlo.
  4. Probá cables más largos con 4,7 kΩ: 10 m sube en 5,9 µs (bien), 50 m en 28,5 µs (dudoso: «marginal»), 100 m en 56,7 µs («presencia perdida»). Con 50 m y 1,5 kΩ la subida baja a 9,1 µs y vuelve a cumplir.
  5. En la herramienta 2, con los valores iniciales (escribir 1, línea en bajo 6 µs): el dispositivo entiende 1. Con 60 µs y el bit 0, entiende 0. Con 30 µs queda en la zona prohibida: «ambiguo». Si se quiere enviar un 1 y se baja 60 µs, el dispositivo entiende un 0: el pulso largo.
  6. Pasá a «Leer» con el bit 0 (el dispositivo envía un 0) y lectura a los 9 µs: el maestro lee 0, correcto. Con lectura a los 30 µs: el dispositivo ya soltó la línea y el maestro lee 1, un error. Con la línea en bajo 30 µs y lectura a los 9 µs: el propio maestro mantiene la línea, y siempre lee 0.
  7. En la herramienta 3, con 91 01 en 12 bits: 401/16 = +25,0625 °C, en 750 ms. Con D0 07: +125 °C. Con 5E FF: −10,125 °C. Con 90 FC: −55 °C. Con 50 05: 85 °C, y el laboratorio avisa que es el valor de arranque. Con FF FF: −0,0625 °C, que casi seguro es una línea sin dispositivo.
  8. Volvé a 91 01 y elegí 9 bits: se enmascaran los 3 bits bajos, la temperatura es 25,0 °C, con paso de 0,5 °C y 93,75 ms de conversión.
  9. En la herramienta 4, con los sensores A, B y C: las ROM aparecen en el orden C, A, B, con discrepancias en los bits 3 y 8, en 44,9 ms (tres pasadas). El Read ROM con tres sensores devuelve un AND que no pasa el CRC.
  10. Conectá D además: aparece una discrepancia más, en el bit 48 (A y D solo difieren en el último bit del número de serie) y el orden pasa a C, A, D, B. Dejá uno solo: Read ROM devuelve su ROM, con CRC correcto. Sin ninguno: «sin dispositivos».
Desafío: cuánto tarda leer una red de ocho sensores

Ocho DS18B20 a 12 bits, con alimentación externa. Con un único Skip ROM + Convert T (2,08 ms) y una espera de 750 ms, y luego ocho lecturas de scratchpad con Match ROM (reset + 0x55 + 8 bytes + 0xBE + 9 bytes = 960 + 19 × 560 = 11,6 ms cada una): 2,08 + 750 + 8 × 11,6 ≈ 845 ms en total. Si en cambio se hiciera una conversión por sensor (Match ROM + Convert T + espera + lectura), serían 8 × (6,56 + 750 + 11,6) ≈ 6,1 s. Convertir todos a la vez con Skip ROM ahorra más de cinco segundos por ciclo.

11 · Un procedimiento

Diagnóstico de una red 1-Wire

Los síntomas de 1-Wire se parecen entre sí (valores raros, sensores que «desaparecen»), pero casi todos se localizan con una secuencia corta:

  1. Medir DQ en reposo. Debe estar en alto (la alimentación). Si está en bajo, hay un cortocircuito o un dispositivo defectuoso reteniéndola.
  2. Hacer un reset y mirar la presencia. Sin presencia: pull-up ausente o de valor equivocado, DQ y GND invertidos, sensor sin alimentación en modo externo, o un cable cortado.
  3. Con un solo sensor conectado, leer su ROM y verificar el CRC y el código de familia.
  4. Agregar sensores de a uno y repetir la búsqueda. El punto en que algo se rompe señala un cable, un sensor o un límite de la línea.
  5. Mirar la forma de onda con un osciloscopio o un analizador lógico (a 1 MHz o más): flancos de subida, nivel bajo (cerca de 0 V) y tiempos de reset, presencia e intervalos.
  6. Verificar el software: interrupciones deshabilitadas durante los intervalos, espera de la conversión, CRC comprobado.
Síntomas más frecuentes y su causa probable.
SíntomaCausa probableQué hacer
No hay presenciaFalta la pull-up, cables cruzados o cortados, sensor sin alimentaciónMedir DQ en reposo; revisar el cableado
Todos los bytes leídos son 0xFF; temperatura de −0,0625 °C o −127 °CNo hay dispositivo, o la lectura se hizo sin responder el sensorComprobar la presencia antes de leer; verificar el CRC
La temperatura es siempre 85,0 °CSe lee antes de terminar la conversión, o la alimentación se cae durante ella (parásita sin pull-up fuerte)Esperar el tiempo de conversión; usar alimentación externa o pull-up fuerte
Errores de CRC intermitentesCable largo con pull-up débil, ruido, interrupciones en medio de un intervaloBajar la pull-up, mejorar el cable, deshabilitar interrupciones, reintentar
Con varios sensores, Read ROM devuelve basuraEs normal: contestan a la vez y llega el AND de las ROMUsar la búsqueda y Match ROM
Funcionan hasta agregar un cuarto sensor o más cableCapacidad o corriente superadasBajar la pull-up; acortar ramas; alimentar externamente
El sensor «número 2» ahora mide otra cosaSe identifica por posición en la lista, que cambióIdentificar los sensores por su ROM guardada

12 · Comprensión

Confusiones frecuentes

«1-Wire usa un solo cable»

Usa una sola línea de datos. Hace falta además la masa, y la alimentación puede ir por la misma línea (modo parásito) o por un tercer cable. Un dispositivo se conecta, como mínimo, con dos conductores.

«Para enviar un 1 se deja la línea en alto un buen rato»

Al revés: el 1 es el pulso corto en bajo (1 a 15 µs) y el 0 el pulso largo (al menos 60 µs). Siempre es el maestro quien baja la línea al comienzo de cada intervalo.

«El pulso de presencia me dice cuántos sensores hay»

Dice que hay al menos uno. Todos responden a la vez, y la línea muestra un único pulso. Para saber cuántos y cuáles, hace falta la búsqueda.

«Un delay alcanza para los tiempos»

Hace falta precisión de microsegundos, sin interrupciones en medio. Una interrupción larga en un intervalo de escritura de 1 lo convierte en un 0. Se usan bibliotecas con acceso directo a los puertos o hardware de apoyo.

«Con un Read ROM averiguo todos mis sensores»

Solo funciona con un único dispositivo. Con varios, la línea muestra el AND de las ROM, y el CRC falla. La forma de descubrirlos es la búsqueda (Search ROM).

«Con getTempCByIndex(0) siempre leo el mismo sensor»

El orden depende de los números de serie y cambia al agregar o quitar sensores. Para un sistema estable se guardan las ROM y se identifica cada sensor por la suya.

«Si leo 85 °C es que está caliente»

Es el valor de arranque del sensor: indica que no se completó una conversión. En un ambiente real, una lectura de exactamente 85,0 °C debe tratarse como una falla.

«La alimentación parásita es gratis»

Ahorra un cable pero exige un pull-up fuerte durante las conversiones, impide saber cuándo terminó una (hay que esperar un tiempo fijo) y es más sensible a las caídas de tensión con cables largos o muchos sensores.

13 · Práctica guiada

Predecí antes de comprobar

1. Tiempo de un Read ROM

Con 70 µs por intervalo y un reset de 960 µs, ¿cuánto tarda leer la ROM de un único sensor (reset, comando 0x33 y 8 bytes)?

Ver solución

Un byte son 8 × 70 = 560 µs. El comando y los 8 bytes de ROM son 9 bytes: 5040 µs. Con el reset: 960 + 5040 = 6000 µs = 6,0 ms.

2. Los bits del comando

¿En qué orden salen por la línea los bits del comando 0x44 (Convert T)? ¿Y los del 0xCC (Skip ROM)?

Ver solución

El bit menos significativo va primero. 0x44 = 0100 0100 sale como 0 0 1 0 0 0 1 0. 0xCC = 1100 1100 sale como 0 0 1 1 0 0 1 1.

3. De bytes a grados

El scratchpad de un DS18B20 en 12 bits tiene los bytes 0 y 1 iguales a 0x5E y 0xFF. ¿Qué temperatura es?

Ver solución

El entero es 0xFF5E = 65 374; como el bit 15 vale 1, es negativo: 65 374 − 65 536 = −162. Dividido por 16: −10,125 °C.

4. Conversión de varios sensores

Con ocho sensores a 10 bits, ¿cuánto se ahorra al iniciar todas las conversiones con un único Skip ROM frente a convertir sensor por sensor y esperar cada uno? (Ignorá el tiempo de las comunicaciones.)

Ver solución

A 10 bits la conversión tarda hasta 187,5 ms. Sensor por sensor: 8 × 187,5 = 1,5 s. Con un único Skip ROM + Convert T, 187,5 ms para todos a la vez: se ahorran 1,3125 s por ciclo.

5. Costo de la búsqueda

Una pasada de la búsqueda cuesta casi 15 ms. ¿Cuánto tarda descubrir una red de 5 sensores?

Ver solución

Una pasada: 960 + 560 + 192 × 70 = 14 960 µs. Cinco pasadas: 74,8 ms, una sola vez al arrancar.

6. Dos sensores contestan a la vez

En una red con dos sensores, un Read ROM devuelve 28-AA-10-20-30-40-50-02 y el CRC calculado sobre los siete primeros bytes da 0x1F. ¿Qué pasó?

Ver solución

Los dos sensores contestaron al mismo tiempo, y por el Y cableado la línea mostró el AND bit a bit de ambas ROM. El CRC recibido (0x02) no coincide con el calculado (0x1F): la lectura no es válida. Con más de un dispositivo no se usa Read ROM sino la búsqueda.

7. Un cable de 50 metros

Con 100 pF por metro y 4,7 kΩ, ¿cuánto tarda la línea en subir (1,2 · R · C)? ¿Y con 2,2 kΩ o 1,5 kΩ? ¿Qué hay que revisar al bajar la pull-up?

Ver solución

C = 50 m × 100 pF + 50 pF = 5,05 nF. Con 4,7 kΩ: 1,2 · 4700 · 5,05 nF ≈ 28 µs (dudoso). Con 2,2 kΩ: 13 µs; con 1,5 kΩ: 9 µs. Hay que revisar que la corriente al bajar la línea (3,3 V / 1,5 kΩ ≈ 2,2 mA) la pueda absorber cada dispositivo y el maestro.

14 · Síntesis

Ideas para recordar

  • 1-Wire usa una única línea de datos de colector abierto con pull-up (típicamente 4,7 kΩ), más masa. El Y cableado es la base de todo, incluida la búsqueda. Los dispositivos pueden alimentarse de la línea (modo parásito), con un pull-up fuerte durante las operaciones de más consumo.
  • No hay reloj: el bit se codifica en la duración del pulso en bajo. Escribir 1 = pulso corto (1 a 15 µs); escribir 0 = pulso largo (≥ 60 µs); leer = el maestro baja un instante y lee antes de 15 µs. Intervalos de unos 70 µs, bit menos significativo primero.
  • Toda conversación empieza con un reset: el maestro baja la línea ≥ 480 µs; los dispositivos contestan con un pulso de presencia (15 a 60 µs después, durante 60 a 240 µs); el maestro lee a los 70 µs. La presencia dice que hay alguien, no cuántos.
  • Cada dispositivo tiene una ROM única de 64 bits: familia (1 byte), serie (6 bytes) y CRC-8 (1 byte). Los comandos de ROM son Read ROM (solo con uno), Match ROM, Skip ROM, Search ROM y Alarm Search.
  • La búsqueda recorre el árbol de ROM con tres intervalos por bit (bit, complemento, elección de rama) y encuentra una ROM por pasada (unos 15 ms); el orden de aparición no corresponde al lugar físico, así que los sensores se identifican por su ROM.
  • El DS18B20 mide con 9 a 12 bits (hasta 750 ms por conversión); la temperatura es un entero de 16 bits en complemento a dos en unidades de 1/16 °C. Una sola orden Skip ROM + Convert T pone a medir a todos. El valor 85 °C es el de arranque y es sospechoso.
  • El CRC se verifica en cada ROM y en cada scratchpad. Los tiempos se cumplen con las interrupciones deshabilitadas o con hardware de apoyo.
  • Un diagnóstico ordenado: DQ en reposo, presencia, una ROM, agregar sensores de a uno, forma de onda y software.

¿Listo para el siguiente bloque?

Antes de avanzar, calculá cuánto tarda leer los 9 bytes del scratchpad de un sensor seleccionado con Match ROM (reset, 0x55, 8 bytes de ROM, 0xBE y 9 bytes) con intervalos de 70 µs; explicá por qué un 1 se transmite con un pulso corto y un 0 con uno largo, y por qué el maestro tiene que leer antes de 15 µs; y decidí cómo identificarías de forma permanente a cuatro sensores en una instalación. (Para la primera: 960 + 19 × 560 = 11 600 µs = 11,6 ms.) Si podés justificar las tres respuestas, tenés el bus de un cable.

En el próximo tema empezamos el bloque de buses industriales y de larga distancia con el RS-232: niveles de ±12 V, conectores DB9, líneas de control y adaptadores USB-serie.