Manual

do

Maker

.

com

Sensor de temperatura DS18B20 com ESP8266

Sensor de temperatura DS18B20 com ESP8266

Um diferencial desse sensor de temperatura DS18B20 para os LM3x é o fato de ele ser digital. Isto é, não será necessário utilizar pinos analógicos para sua leitura e de quebra, ele é endereçável. Isso significa que com apenas 1 pino digital você pode ler mais do que 1 sensor, bastando controlar a leitura pelo endereço.

Ele possui 2 bibliotecas interessantes, sendo que um exemplo está na própria OneWire da IDE do Arduino e a outra, oferecida pela Dallas, pode ser baixada do github nesse link. Lá você opta por zip ou clone do git.

Se quiser experimentar algo realmente diferente, você pode utilizar esse sensor de temperatura DS18B20 com ESP8266 utilizando MicroPython através desse artigo que escrevi.

Em especial, esse sensor de temperatura DS18B20 que adquiri tem a vantagem de ser a prova d'agua e ter fios bastante compridos, o que permite utilizá-lo em condições diversas. Meu propósito inicial com esse sensor foi de controlar a temperatura da água do banho de minha filha, uma vez que um bebê normalmente pode chorar só pelo fato de estar sendo molhado. Então, como saber se a água está muito fria ou muito quente? - Com esse sensor e uma MCU fica fácil. E se a água estiver quente demais, deixe o sensor lá e aguarde que a MCU informe quando chegar na temperatura ideal; e foi por essa razão que escolhi o ESP8266, uma vez que esse sensor trabalha bem de 3V à 5V, enquanto o ESP8266 tem possui WiFi.

Já falei em outros artigos, mas vale citar novamente. O ESP8266 é um processador RISC que roda um RTOS (Real Time Operating System) e tem um clock padrão de 80MHz. É muito mais do que precisamos para esse artigo tão simplório, mas a maior vantagem é o WiFi, além do preço, uma vez que o ESP8266-01 é o suficiente para esse projeto. Porém, vou utilizar o NodeMCU (que também é um ESP8266). Isso se dá ao fato que tenho um segundo artigo a escrever e pretendo usá-lo também como cobaia.

Como se trata de um artigo muito simples, vamos direto aos finalmentes.

Características do sensor de temperatura DS18B20

Esse sensor tem várias características tentadoras. Confesso que perdi totalmente o interesse nos LM35 e LM37 depois que li o datasheetDS18B20.pdf.

  • One Wire - esse sensor é digital!
  • Não requer componentes adicionais
  • Pode ser alimentado de 3V à 5V, servindo para qualquer controlador
  • Pise nos sus LM35; o DS18B20 mede de -55 até 125 celsius
  • 0.5% de variação entre -18 até 85 celsius, sendo bastante preciso!
  • Resolução programável de 9 (512) à 12 bits (4096)!
  • Conversão de 12bits para word em menos de 750ms
  • Alarme definido pelo usuário

Onde comprar?

Esse sensor é fácil de achar em sites e em algumas lojas, mas sugiro que dê preferência ao nosso parceiro Fulltronic, que patrocina alguns dos artigos que envolvem alguns de seus produtos. Tenho adquirido produtos com eles já há algum tempo e sempre resulta em satisfação.

Wiring do sensor de temperatura DS18B20

Ele tem 2 modos de operação possíveis, sendo um deles chamado de "parasita", onde você pode alimentá-lo pelo próprio pino de leitura e assim utilizar só um par de fios. O sensor que está encapsulado nesse cilindro de aço inox possui 3 pinos, sendo GND, DATA, VCC. Prefiro utilizar os 3 e o wiring será desse jeito:

01a-ds18b20-wiring-esp8266.webp

O sensor tem apenas 3 fios, não sei porque no desenho do Fritzing ele possui 4 fios. De qualquer modo, coloquei um "X" sobre o fio branco.

Comunicação com o DS18B20

Conforme o datasheet o DS18B20 tem 4 principais componentes de dados:

  • ROM de 64-bit
  • sensor de temperatura
  • alarme não-volátil de temperatura com gatilhos TH e TL (para máxima e mínima)
  • um registro de configuração

Por ser 1-wire, ao ligá-lo é necessário esperar que ele estabilize. Sua leitura também tem um pequeno delay, correspondente ao processamento dos dados. Ele responde a 5 comandos:

  1. Read ROM

  2. Match ROM

  3. Search ROM

  4. Skip ROM

  5. Alarm Search

Estes comandos atuam na ROM de 64bits do dispositvo. Os gatilhos de alarme TH e TL tem 1 byte de EEPROM cada. Se não estiverem sendo utilizados para o propósito de alarme, eles podem ser utilizados como memória do usuário; 2 bytes inteirinhos pra usar à vontade!

DS18B20 modo parasitário

02a-bs18b20-diagram.webp

No diagrama de blocos está representada a alimentação no modo parasita. Nesse modo, um capacitor interno vai capturando energia enquanto o pino digital ou o VCC estiverem em HIGH. O datasheet relata duas vantagens de se utilizar esse sensor no modo parasita, e os reproduzo, mas não sei se os argumentos me convencem, verei com o passar do tempo e com mais testes.

As vantagens citadas no datasheet são:

  • Não haver necessidade de fonte de alimentação nele para leitura remota de temperatura;
  • A ROM pode ser lida na ausência de alimentação convencional

Claro que existem casos que pode fazer a diferença não precisar de espaço pra mais um fio no circuito. Não sei se algum dia será o caso para mim.

Quando efetuando a conversão de temperaturas, a alimentação deve ser suficiente na linha digital, mas a corrente de operação é de 1.5mA, um limão é o suficiente para alimentá-lo por uma semana, presumo.

Utilizar a alimentação externa já garante que não haja necessidade de colocar o pino digital em pullup.

Pra finalizar, o modo parasita é recomendado até 100 graus celsius, portanto mais que o suficiente para nós usuários comuns.

Uso de VDD e interconexão no barramento

Por ser um barramento com protocolo endereçável, você pode ter mais de um sensor (ou outro dispositivo OneWire) no barramento, ambos utilizando o mesmo pino digital. No esquema abaixo você pode ver como fazer essa interface de forma bastante simples:

03a-bs18b20-powered.webp

Medição da temperatura e resolução

O sensor de temperatura DS18B20 tem uma resolução configurável de 9 até 12 bita, sendo 12 bits o padrão. Com isso, a resolução pode ser configurada para exibir de 0.5C até 0.0625. Na resolução de 12bits o tempo de leitura é de 750ms, enquanto em 9bits o tempo de leitura é menor que 100ms. Não vivi uma experiência que necessitasse um intervalo tão curto quanto 100ms, mas talvez alguma aplicação utilizando PID se beneficie disto.

As informações no datasheet falam dos endereçamentos e memória, da alocação no scratchpad, tabela de relacionamento etc. Como vamos utilizar uma das bibliotecas, essas informações serão transparentes para nós, não é necessário se aprofundar nisso agora.

Modo de operação do alarme do sensor de temperatura DS18B20

Quando o sensor faz a medição, o resultado é comparado com os valores de TH e TL. Se exceder os limites de baixa ou alta, uma flag é assinalada dentro do dispositivo. Essa flag é atualizada a cada leitura do dispositivo, portanto, não haverá memória de uma ocorrência em um determinado tempo passado quando retomado o estado de normalidade.

Com o comportamento do alarme, é possível ter diversos DS18B20 conectados em paralelo fazeno leituras simultâneas e, se algum deles exceder os limites, os dispositivos alarmados podem ser identificados e lidos imediatamente sem precisar ficar fazendo polling de leituras. Isso auxilia na redução de processamento para MCUs modestas como PICs pequenos e afins.

Agora que já conversamos sobre o brinquedo, vamos à brincadeira.

Wiring do NodeMCU

Não vou fazer outro desenho no Fritzing. Esse sensor à prova d'agua às vezes varia a cor do fio de leitura. No meu caso, o fio é amarelo, em outros casos, ele é branco, mas o VCC é sempre o vermelho e o GND é sempre o preto. Coloque o VCC em 3.3V do NodeMCU e o preto no GND. O fio amarelo/branco vai no D5. Coloquei um resistor de 20k conectado entre VCC e D5:

#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(14);  // on pin 10 (a 4.7K resistor is necessary)

void setup(void) {
  Serial.begin(9600);
  Serial.println("OK");
}

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, 1);        // start conversion, 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");
}

Repare que a correspondência do D5 é físico é GPIO 14, portanto não será necessário equivocar-se em dizer que o código está errado. Pra finalizar, esse código é exemplo da própria biblioteca, basta procurar pelo DS18B20 nos exemplos, abrir, trocar o número do pino OneWire, salvar e "uppar". O resultado será como esse:

04a-nodeMCU-ds18b20.webp

Inscreva-se no nosso canal Manual do Maker Brasil no YouTube.

Próximo post a caminho!

Nome do Autor

Djames Suhanko

Autor do blog "Do bit Ao Byte / Manual do Maker".

Viciado em embarcados desde 2006.
LinuxUser 158.760, desde 1997.