Como medir temperatura com um DS18B20

Este post é quase uma tradução do excelente post do blog Tweaking4all. Vale a pena uma visita, em inglês. O DS18B20 é um sensor digital de temperatura com características interessantes para uso com o Arduino, que são o baixo custo e a facilidade de uso. Eu comprei dois sensores a prova d´água no ebay por $2,95 cada, e, sinceramente, não sabia o que faria com eles. Pensei até que não dava para usar com o Arduino. Ledo engano… As aplicações deste sensor vai da criatividade de cada um, mas podemos dar os seguintes exemplos: medição de temperatura em aquários, sistemas de aquecimento de água, em áreas internas ou externas à residência, dentro de freezer/geladeira, etc. As principais características do DS18B20 são:

  • Alimentação DC entre 3.0V e 5.5V
  • Mede temperatura entre -55ºC e +125ºC
  • Não necessita de componentes externos
  • Resolução ajustável entre 9 e 12 bits
  • A prova de água, umidade e ferrugem
  • Utiliza o Protocolo 1-Wire para leitura
  • Cada sensor tem um Serial Number

Ainda, vale destacar que o DS18B20 pode operar em modo “normal” ou “parasita”. Em modo normal, utilizamos os três fios do sensor, já em modo parasita, podemos utilizar apenas 2 fios, curto-circuitando o DATA e  VCC no Arduino. No final temos exemplo de ligação para os dois modos. Outra característica legal é que podemos combinar até 127 sensores, utilizando apenas um pino de leitura do Arduino, isso graças ao sensor utilizar o Protocolo 1-Wire.

Protocolo 1-Wire

Até antes de começar a mexer com este sensor, eu nunca tinha ouvido falar deste Protocolo. É algo realmente interessante e vale a pena uma pesquisa sobre o assunto. Basicamente o Protocolo 1-Wire define algumas características que tornam possível utilizar vários sensores conectados a apenas um pino de leitura do Arduino. Algumas características do Protocolo são:

  • Definição de um Serial Number em cada sensor compatível, tornando possível identificar individualmente cada sensor conectado no mesmo pino de leitura (podemos  chamar de barramento).
  • Definição de um CRC para podermos tratar possíveis colisões no barramento (dois sensores enviando informação ao mesmo tempo)
  • Definição de meios para leitura e controle dos sensores.

Tipos de sensores DS18B20

ds18b20

Figura 1. Circuitos disponíveis

  DS18B20

Figura 2. DS18B20 em uma embalagem a prova d’àgua

O que é necessário para fazer o Arduino e o DS18B20 funcionarem?

Software

  • Arduino IDE
  • Biblioteca OneWire
  • Sketch

A IDE do Arduino pode ser obtida no site oficial do Arduino (www.arduino.cc). A biblioteca OneWire pode ser obtida na Página do Projeto OneWire. O sketch é o arquivo de exemplo, disponível após instalar a biblioteca no Arduino.

Hardware

  • Pelo meno um sensor DS18B20
  • Um Arduino
  • Uma breadbord
  • 3 cabos flexives para conexão do Arduino à breadbord
  • Cabo USB para o Arduino
  • Um resistor de 4.7K

Conectando o Arduino e o DS18B20

Conectar um sensor que utiliza o Protocolo 1-Wire é muito simples. O cabo GND do DS18B20 vai no GND do Arduino O cabo Vcc do DS18B29 vai no +5V do Arduino O cabo Data do DS18B20 vai pino digital de sua escolha do Arduino, no nosso caso usaremo o pino 2

ds18b20-arduino-connected

Figura 3. Esquema de ligação DS18B20 – Arduino

Sketch para medir temperatura

Instalando a biblioteca OneWire

Depois de baixar  a biblioteca você pode importá-la diretamente a partir da IDE do Arduino. Para isso clique em:

  • Sketch
  • Import Library
  • Add Library

e selecione o arquivo ZIP que você baixou. Reinicie a IDE do Arduino, fechando todas as janelas abertas e abra novamente, a biblioteca deverá estar disponível para uso.

Carregando o sketch de exemplo

Para abrir o sketch de exemplo, clique em:

  • File
  • Example
  • OneWire
  • DS18x20_Temperature

O skecth de exemplo  será carregado, logo no início localize a linha “OneWire ds(10)” e altere para “OneWire ds(2)”, faça o upload para o Arduino e verifique a saída serial, clicando em “Tools” –> “Serial Monitor”. Na janela que se abrirá, se tudo estiver certo, você deverá obter uma saida parecida com a abaixo:

ROM = 28 81 2E 11 5 0 0 1B
  Chip = DS18B20
  Data = 1 76 1 4B 46 7F FF A 10 79  CRC=79
  Temperature = 23.37 Celsius, 74.07 Fahrenheit
ROM = 28 AB 2D 11 5 0 0 2C
  Chip = DS18B20
  Data = 1 76 1 4B 46 7F FF A 10 79  CRC=79
  Temperature = 23.37 Celsius, 74.07 Fahrenheit
No more addresses.

Analisando a saída, temos as seguintes informações:

  • ROM  Esta informação é a identificação do sensor, única para cada sensor conectado.
  • Chip  O primeiro byte do valor da ROM é a identificação do tipo do sensor utilizado. No nosso caso, 28 é o identificador do sensor DS18B20
  • Data  Aqui temos a informação “bruta” sobre o valor informado pelo sensor. O primeiro byte (1) não faz parte do valor efetivamente retornado pelo sensor, e o ultimo byte(de valor 79) é o valor do CRC.
  • CRC   Ciclyc Redundancy Check é um mecanismo razoavelmente simples para validar informações digitais. Basicamente se nenhum bit enviado pelo sensor sofreu alteração, a verificação de CRC é realizada com sucesso.
  • Temperature  A temperatura medida, em Celsius e em Fahrenheit

Se notarem a saida, podem ver que estou usando dois sensores (28 81 2E 11 5 0 0 1B  e  28 AB 2D 11 5 0 0 2C ) Se estivermos usando apenas um tipo de sensor, podemos retirar do nosso sketch a verificação do tipo do Chip. Notem que a saída acima é muito “refinada”. Em aplicações reais, utilizamos apenas a ROM e a Temperature (em Celsius). No sketch temos que manter a verificação de CRC, pois assim descartamos dados corrompidos.

Analisando o sketch

Precisamos conhecer alguns métodos(funções) da biblioteca OneWire para entender o sketch de exemplo. Alguma das principais e utilizada no skech são:

  • #include <OneWire.h> Ao darmos um “include” na biblioteca, estamos informando à IDE que nosso sketch utilizará as funções definidas na biblioteca. É como se estivéssemos digitando todo o código da biblioteca dentro do nosso sketch
  • OneWire ds(2) Para que a biblioteca utilize nosso sensor, criamos um objeto e informamos em qual pino do Arduino ele esta conectado.
  • ds.reset.search() Essa função reinicia a busca por dispositivos. Internamente a biblioteca cria uma tabela onde mantêm uma lista ordenada de sensores encontrados, no próximo uso de ds.search(addr) o primeiro sensor da lista é retornado.
  • ds.search(addr) Essa função faz com que a biblioteca procure pelo próximo sensor, de uma maneira ordenada. Caso ele encontre, o serial number é armazenado na variável addr, que é uma variável do tipo array de 8 bytes, e true é retornado pela função.
  • ds.reset() Reinicia o barramento e a tabela interna de dispositivos. Os dispositivos conectados informam sua presença através de um “Presence Pulse”, que é uma sinalização definida pelo Protocolo 1-Wire. Caso a função detecte sensores conectados no barramento, true é retornado.
  • ds.select(addr) Seleciona um sensor, de acordo com o valor armazenado na variável addr. Após ds.reset(), temos que usar esta função para escolher o sensor que usaremos, e toda comunicação passará a ser com este sensor, até outro ds.reset() ou ds.search(addr).
  • ds.write(0x44) Faz com que um byte seja escrito no barramento, no caso 44. Os valores a serem escritos no barramento estão definidos no Protocolo 1-Wire, e fazem com que o sensor selecionado na função anterior realize algum procedimento, como informar seu valor(temperatura).
  • ds.read() Essa função faz com que a biblioteca leia o valor informado pelo sensor.

Abaixo o sketch de exemplo, já com o pino alterado para o 2.

#include <OneWire.h>

// OneWire DS18S20, DS18B20, DS1822 Temperature Example
//
// http://www.pjrc.com/teensy/td_libs_OneWire.html
//
// The DallasTemperature library can do all this work for you!
// http://milesburton.com/Dallas_Temperature_Control_Library

OneWire  ds(2);  // on pin 10 (a 4.7K resistor is necessary)

void setup(void) {
  Serial.begin(9600);
}

void loop(void) {
  byte i;
  byte present = 0;
  byte type_s;
  byte data[12];
  byte addr[8];
  float celsius, fahrenheit;

  if ( !ds.search(addr)) {
    Serial.println("No more addresses.");
    Serial.println();
    ds.reset_search();
    delay(250);
    return;
  }

  Serial.print("ROM =");
  for( i = 0; i < 8; i++) {
    Serial.write(' ');
    Serial.print(addr[i], HEX);
  }

  if (OneWire::crc8(addr, 7) != addr[7]) {
      Serial.println("CRC is not valid!");
      return;
  }
  Serial.println();

  // the first ROM byte indicates which chip
  switch (addr[0]) {
    case 0x10:
      Serial.println("  Chip = DS18S20");  // or old DS1820
      type_s = 1;
      break;
    case 0x28:
      Serial.println("  Chip = DS18B20");
      type_s = 0;
      break;
    case 0x22:
      Serial.println("  Chip = DS1822");
      type_s = 0;
      break;
    default:
      Serial.println("Device is not a DS18x20 family device.");
      return;
  } 

  ds.reset();
  ds.select(addr);
  ds.write(0x44);        // start conversion, use ds.write(0x44,1) with parasite power on at the end

  delay(1000);     // maybe 750ms is enough, maybe not
  // we might do a ds.depower() here, but the reset will take care of it.

  present = ds.reset();
  ds.select(addr);    
  ds.write(0xBE);         // Read Scratchpad

  Serial.print("  Data = ");
  Serial.print(present, HEX);
  Serial.print(" ");
  for ( i = 0; i < 9; i++) {           // we need 9 bytes
    data[i] = ds.read();
    Serial.print(data[i], HEX);
    Serial.print(" ");
  }
  Serial.print(" CRC=");
  Serial.print(OneWire::crc8(data, 8), HEX);
  Serial.println();

  // Convert the data to actual temperature
  // because the result is a 16 bit signed integer, it should
  // be stored to an "int16_t" type, which is always 16 bits
  // even when compiled on a 32 bit processor.
  int16_t raw = (data[1] << 8) | data[0];
  if (type_s) {
    raw = raw << 3; // 9 bit resolution default
    if (data[7] == 0x10) {
      // "count remain" gives full 12 bit resolution
      raw = (raw & 0xFFF0) + 12 - data[6];
    }
  } else {
    byte cfg = (data[4] & 0x60);
    // at lower res, the low bits are undefined, so let's zero them
    if (cfg == 0x00) raw = raw & ~7;  // 9 bit resolution, 93.75 ms
    else if (cfg == 0x20) raw = raw & ~3; // 10 bit res, 187.5 ms
    else if (cfg == 0x40) raw = raw & ~1; // 11 bit res, 375 ms
    //// default is 12 bit resolution, 750 ms conversion time
  }
  celsius = (float)raw / 16.0;
  fahrenheit = celsius * 1.8 + 32.0;
  Serial.print("  Temperature = ");
  Serial.print(celsius);
  Serial.print(" Celsius, ");
  Serial.print(fahrenheit);
  Serial.println(" Fahrenheit");
}

Como conectar múltiplos sensores

O sensor digital de temperatura DS18B20 permite que múltiplos sensores sejam ligados em paralelo. Neste caso, a biblioteca OneWire irá ler todos os sensores. Abaixo temos dois métodos de ligar vários sensores em parelelo, sendo um método utilizando o modo “Normal” e o outro o modo “Parasite”. Para uma rede com mais de 10 sensores, o uso de resistores menores deveria ser considerado, por exemplo 1.6K ou menor. Em redes com muitos sensores pode ocorrer colisões na transmissão dos dados, e um resistor adicional de 100 ou 120 deveria ser usado entre o pino digital do Arduino e o cabo Data do sensor, para cada sensor.

Selecionando um sensor específico

Quando usando múltiplos sensores, seria inútil se não houvesse um meio de associar a informação ao sensor de origem. Então, como podemos identificar individualmente  cada sensor e sua correspondente informação (temperatura)?

Serial Number

Cada sensor possui um Serial Number único, que pode ser usado para identificar a origem de determinada informação. O Serial Number é composto de 64 bits, e é o valor ROM na saida da janela serial. No meu exemplo, usando dois sensores, podemos ver que os valores dos Serias Numbers são

  • 28 81 2E 11 5 0 0 1B
  • 28 AB 2D 11 5 0 0 2C

Na prática, como usaremos o Serial Number e a temperatura de uma forma útil dependerá muito do nosso projeto. Neste exemplo, poderíamos criar uma variável para armazenar os Seriais Number e um nome adequado, por exemplo Sala e Quarto. Para um projeto mais complexo, poderíamos por exemplo armazenar a informação em um banco de dados, e criar outra tabela associando os Serias Number a nomes com algum significado mais adequado. Outro problema que temos é obter inicialmente o Serial Number de cada sensor. Como o sensor não vem com  nenhuma informação relativa ao Serial Number gravada em seu corpo, teríamos que conectá-lo inicialmente sozinho e obter o Serial Number, identificando de alguma forma o sensor.

Normal Power Mode

ds18b20-normal-power-400x184

Figura  4: DS18B20 – Múltiplos Sensores em “Normal Power Mode”

 

Parasite Power Mode

 ds18b20-parasite-power-400x181

Figura  5: DS18B20 – Múltiplos Sensores em “Parasite Power Mode”

Leitura recomenda

How it works: DS18B20 and Arduino Excelente artigo, bem técnico

Págino do Projeto OneWire

Protocolo 1-Wire Wikipedia

 

18 thoughts on “Como medir temperatura com um DS18B20

  1. Janaina

    Bom dia, estou tentando utilizar o DS18B20 já montado testei diversos programas inclusive este que você apresentou e obtenho apenas temperaturas negativas -2032 ºC que totalmente incompatível já que a temperatura deveria estar na faixa de 20ºC. Já testei diversas montagem e programas e todos me dão uma temperatura negativa totalmente fora da faixa. Você tem alguma ideia do que pode ser?
    Aguardo retorno.

    Reply
    1. Valdinei Rodrigues dos Reis Post author

      Primeiro perdão pelo abandono do blog.

      Ola Janaína. Bem, se a ligação estiver correta não vejo motivo algum para a temperatura negativa obtida.
      Presta atenção para as cores do sensor, os fios vermelho e preto sempre correspondem a +5V e GND, já o DATA pode vir em diversas cores, eu por exemplo tenho alguns sensores com o DATA branco, e outros com o DATA amarelo.

      Pode também remover o resistor e ver se altera algo.

      Reply
  2. Hélio

    Tive que comentar só pra dizer: Excelente artigo!

    Reply
    1. Valdinei Rodrigues dos Reis Post author

      Valeu colega.

      Reply
  3. Rafael Silva

    Como posso fazer para o sistema ler a temperatura do sensor durante 1 minuto e se durante esse 1 minuto ele variar 6 graus para mais faça tal comando que eu vou definir. Obrigado.

    Reply
    1. Valdinei Rodrigues dos Reis Post author

      Ola Rafael, perdão pelo abandono do blog e consequente demora em responder.

      Vou preparar um exemplo prático do que quer. Não é assim tão simples 🙂

      Reply
  4. LUCIO

    Fiz uma ligação em “modo normal” de vários sensores (mais especificamente 4 sensores) DS18B20. Coloquei-os medindo a mesma posição no quarto, porém mostraram valores diferentes entre si. A diferença não é muito grande (em torno de meio grau celsius). Gostaria de saber se isso tem algo a ver com o resistor utilizado (4,7 kohm) e se eu poderia melhorar a precisão da medida usando resistores diferentes para cada sensor.

    Reply
    1. Valdinei Rodrigues dos Reis Post author

      Ola Lúcio, desculpe a demora.

      Coloquei dois sensores encostados, e fiquei com o dedo a aproximadamente 1cm de um deles. Isso foi o suficiente para obter uma diferença de 0,2 graus entre os sensores.
      Qual a distância que os seus sensores estão entre si? Vários fatores podem influenciar, como fonte de calor, vento, etc.

      Reply
  5. Saulo Carvalho

    Aqui funcionou legal. Pena que não dar pra ver o Gráfico…

    Reply
    1. Valdinei Rodrigues dos Reis Post author

      Ola Claudio.

      Muitos fatores influenciam na distância máxima, li relatos de funcionamento correto a uma distância de 30m, mas pessoalmente não tenho muito o que dizer.
      Vou tentar uns testes práticos e posto aqui.

      Abs.

      Reply
  6. vinicius may

    boa noite; trabalho com um equipamento que tem sua temperatura monitorada por um sensor DS1820. O sensor queimou e subistitui pelo ds18b20, porem, os numeros mostrados no display estao muito estranhos; isto tem haver com a resolução?

    Reply
    1. Valdinei Rodrigues dos Reis Post author

      Ola Vinicius.

      Muito provavelmente sim, resolução.
      O substituto adequado para o DS1820 é o DS18S20, pelo que li seria apenas substituir.
      Já quando a substituição é pelo DS18B20, seria necessário ajustes no firmware/software devido a resolução.

      Abs.

      Reply
  7. Fabricio Oliveira

    Amigo boa noite, primeiramente queria agradecer pelo excelente artigo. Tenho uma dúvida, estes sensores são vendidos com diferentes metragens, eu poderia emendar os cabos dos sensores para dar mais extensão ? qual o cabo mais apropriado para fazer isso ? desde já agradeço muito !

    Reply
    1. Valdinei Rodrigues dos Reis Post author

      Ola Fabricio. Tranquilo?

      Pode emendar sim, eu gosto muito de utilizar cabos UTP, embora dê um pouco de trabalho conectar coisas no meio dele.
      Esta saindo do forno um post com vários DS18B20 utilizando um cabo UTP de 21 metros.

      Abs.

      Reply

Deixe uma resposta

O seu endereço de e-mail não será publicado. Campos obrigatórios são marcados com *

18 − cinco =