Sensor de temperatura DSB18B20 e Raspberry Pi 3

O protocolo 1-Wire é um tipo de comunicação que se utiliza de apenas um pino de dados e o terra, bastante similar ao I2C, porém com mais alcance e taxas mais baixas de dados. Por essa facilidade, é bastante usado em sistemas embarcados, como sensores de temperaturas, sensores de corrente, entre outros.

Neste tutorial, vamos usar o sensor DS18B20 da MAXIM. Este sensor possui um código 64-bits único, o que se permite ligar vários deles usando o mesmo pino do nosso controlador (imagine as aplicações disso, dá pra dominar o mundo! Ok. Nem tanto).

Materiais necessários

  • Raspberry Pi 3
  • DS18B20
  • Resistor 4K7 Ohm
  • Protoboard

Habilitando 1-Wire na Raspberry

Por maravilhas do destino, o kernel da Raspberry Pi já tem suporte ao protocolo 1-Wire. Para habilitar, acesse a sua Raspberry usando SSH e edite o arquivo /boot/config.txt:

$ sudo nano /boot/config.txt

E insira a seguinte linha ao final do arquivo:

dtoverlay=w1-gpio

Salve o arquivo e reboot o terminal para as alterações fazerem efeito.

$ sudo reboot

Conectando o sensor

  1. Conecte o pino de terra (GND – pino 9) ao cabo preto do sensor.
  2. Conecte o pino 3.3 V (pino 1) ao cabo vermelho do sensor.
  3. Conecte o pino GPIO4 (pino 7) ao cabo amarelo do sensor (dados).
  4. Ligue uma perna do resistor ao pino 7 e a outra perna no pino 1. Esse resistor vai funcionar como um pull-up para a linha de dados e pode ser usado apenas um para vários sensores na mesma linha.

Nota: caso tenha alguma dúvida com relação ao GPIO, leia esse artigo.

Listando o ID

Como dissemos anteriormente, cada sensor possui um identificador único, o que permite ligar vários em paralelo. O kernel vem com muitos drivers para interface de sensores, para cada tipo diferente. Não faz sentido carregar todos no momento do boot, já que isso vai aumentar o tempo significativamente e também uma grande quantidade de recursos a ser usado de forma redundante (e, é claro, não queremos fazer isso). Portanto, para carregar esses drivers podemos usar o comando modprobe:

$ sudo modprobe w1-gpio
$ sudo modprobe w1-therm

Esses dois comandos carregam o driver do 1-Wire e do termometro (por ser um sensor de temperatura, dã!) para o pino GPIO4 (que você sabiamente conectou o sensor DS18B20) da Raspberry Pi.

Antes de começar a programação, vamos determinar o valor do sensor que estamos usando (o kernel cria um diretório pra cada sensor conectado em /sys/bus/w1/devices):

$ ls -l /sys/bus/w1/devices

No nosso caso, o sistema registrou o sensor como 28-0416938bedff. Esse é o identificador do sensor e o que vamos usar para acessá-lo.

Periodicamente, o sensor escreve nesse diretório, em um arquivo chamado w1_slave, o valor da temperatura. É esse arquivo que vamos ler para saber o valor da temperatura:

$ cat /sys/bus/w1/devices/28-0416938bedff/w1_slave

Com esses dados em mãos, podemos começar a escrever o nosso programa.

Programando

Vamos escrever o nosso código em Python (se você não sabe, nunca viu, só ouve falar, veja aqui).

Em primeiro lugar, devemos importar os módulos e garantir que os drivers para usar o 1-Wire estejam carregados.

import os
import time
 
os.system('modprobe w1-gpio')
os.system('modprobe w1-therm')

E então definimos o caminho do arquivo que o kernel cria (que descobrimos anteriormente):

temp_file = '/sys/bus/w1/devices/28-0416938bedff/w1_slave'

Esse arquivo já contém o dado que queremos (a temperatura), mas ainda assim vamos parseá-lo para conseguirmos a informação de forma mais amigável e podermos usar mais fácil dentro do nosso programa. Para isso, vamos ler as linhas desse arquivo:

def read_temp_file():
    f = open(temp_file, 'r')
    lines = f.readlines()
    f.close()
    return lines

O arquivo lido sempre terá o mesmo formato. A primeira linha conterá uma verificação do dado (como um CRC), indicando se a leitura foi realizada corretamente (indicado pelo YES ao final). A segunda linha indica a leitura em si, com a temperatura sendo indicada em t=24937. Essa temperatura está em mºC, então convertemos para ºC.

def read_temp():
     lines = read_temp_file()
     while lines[0].strip()[-3:] != 'YES':
         time.sleep(0.1)
         lines = read_temp_file()
     temp_output = lines[1].find('t=')
     if temp_output == -1:
         return -1
     temp_string = lines[1].strip()[temp_output+2:]
     temp_c = float(temp_string) / 1000.0
     return temp_c

Depois disso, colocamos o processo em um loop para mostrar a temperatura a cada 1 segundo:

while True:
    print(read_temp())
    time.sleep(1)

Código completo:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
import os
import time
 
os.system('modprobe w1-gpio')
os.system('modprobe w1-therm')
temp_file = '/sys/bus/w1/devices/28-0416938bedff/w1_slave'
 
def read_temp_file():
    f = open(temp_file, 'r')
    lines = f.readlines()
    f.close()
    return lines
 
def read_temp():
    lines = read_temp_file()
    while lines[0].strip()[-3:] != 'YES':
        time.sleep(0.1)
        lines = read_temp_file()
    temp_output = lines[1].find('t=')
    if temp_output == -1:
        return -1
    temp_string = lines[1].strip()[temp_output+2:]
    temp_c = float(temp_string) / 1000.0
    return temp_c
 
while True:
    print(read_temp())
    time.sleep(1)

Verificação

Salve o arquivo (no nosso caso, salvamos como o sugestivo e bem criativo nome de temp_sensor.py). Para rodar o programa:

$ sudo python temp_sensor.py

E você terá uma saída parecida com essa:

E parabéns! Você acaba de fazer um pequeno termometro. Até a próxima!

4 opiniões sobre “Sensor de temperatura DSB18B20 e Raspberry Pi 3”

  1. Quando eu executo o comando final, “sudo python temp_sensor.py”, eu recebo apenas o valor “none”, repetidamente, no lugar dos valores de temperatura. O que poderia ser?

    1. Olá Guilherme, obrigado pelo comentário! Pode ser algo relacionado com o arquivo que é criado pelo modbus. Às vezes, o formato não está condizente com o código. Use o comando `cat` para verificar o formato do arquivo. Pode colocar aqui no comentário caso queira também.

  2. Olá,
    troquei meu raspberry por um modelo B+,
    agora estou tendo problemas para identificar os três sensores.
    Aparecer somente 01 endereço. Já troquei os sensores e nada.
    Alguém já passou por isso? Alguma ideia de como resolver?

    1. Olá, Anderson. Já passei esse problema na primeira conexão com mais de um sensor. Normalmente, se você rodar o modprobe novamente é pra resolver o problema. Caso não, verifique a conexão dos fios, pode ser um mal-contato ou algo assim. Se você liga os sensores individualmente, todos eles aparecem listados?

Deixe uma resposta

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