Usando 5 sensores DS18B20 ou mais

Olá pessoal. Vamos rever o sensor de temperatura DS18B20?

Os motivos desta revisão (ou repost) são para:

  • responder a dúvida do leitor Fabricio Oliveira(desculpa a demora);
  • para num próximo post mostrar um setup I2C multimaster;
  • para falar de algumas características do protocolo one wire;
  • para num próximo post mostrar como gravar e visualizar dados utilizando o emonCMS;
  • e, por fim, apresentar um projeto de redução de consumo elétrico.

Então, recomendo que vejam(ou revejam) o post anterior sobre DS18B20.

Agora que viram, vamos ver fotos do setup utilizado.

5 Sensores DS18B20

Sensores DS18B20 utilizados, com identificação

Arduino e DS18B20

Arduino e DS18B20 – Necessário resistor de 4.7K

DS18B20 e UTP

Cabo UTP de 21 metros utilizado para conexão aos DS18B20

Conexões DS18B20

Conectando os 5 sensores DS18B20

Setup completo DS18B20

Como está a gambiarra 😀 😀

Estamos utilizando 5 sensores DS18B20, ligados ao Arduino por um cabo UTP de 21 metros. Para a conexão estamos utilizando os fios branco como GND, laranja como +5v e azul como sinal conectado no pino 10 do Arduino. Finalizando, notem um resistir de 4,7k entre o sinal e o +5v.

De interessante temos a quantidade de sensores utilizados e o comprimento do cabo. O protocolo permite a utilização de muitos dispositivos, sendo a quantidade e a distância variavel segundo alguns fatores.

Código utilizado

O código utilizado é baseado no exemplo do post indicado no início. Vamos ver o código e ver as alterações

#include <OneWire.h>
OneWire  ds(10);  // on pin 10 (a 4.7K resistor is necessary)

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

void loop(void) {
  le_temperatura();
}

void le_temperatura() {
  byte i;
  byte data[12];
  byte addr[8];
  float celsius;
  ds.reset_search();
  while (ds.search(addr)){
    switch (addr[7]) {
    case 0x2c:
      Serial.println("  sensor: amb01");
      break;
    case 0x8e:
      Serial.println("  sensor: cxA1");
      break;
    case 0xd2:
      Serial.println("  sensor: cxA2");
      break;
    case 0x3f:
      Serial.println("  sensor: cxB1");
      break;
    case 0xde:
      Serial.println("  sensor: cxB2");
      break;
    default:
      Serial.print("ROM =");
      for ( i = 0; i < 8; i++) {
        Serial.write(' ');
        Serial.print(addr[i], HEX);
      }
  }

  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

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

  for ( i = 0; i < 9; i++) {           // we need 9 bytes
    data[i] = ds.read();
  }

  // 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];
  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;

  Serial.print("  Temperature = ");
  Serial.print(celsius);
  Serial.println(" Celsius, ");
  Serial.println("");
}
}

A principal alteração foi a criação de uma função que lê os sensores (le_temperatura), onde basicamente pegamos o código original e jogamos dentro desta função. Outra alteração importante é que no exemplo original cada sensor é lido em uma execução própria do loop, ou seja, para lermos 5 sensores teríamos a execução do loop 5 vezes. Neste post fazemos com que nossa função leia todos os sensores em um único loop. Se é melhor ler um sensor por loop ou todos em um loop vai depender do que deseja fazer.

Qual temperatura é de qual sensor DS18B20?

Vou explicar essa parte. Reparem na declaração switch, que, baseada no oitavo byte que compõem o endereço do sensor, ela imprime o nome do sensor da qual estamos lendo a temperatura. Este oitavo byte (de indice 7, lembrem-se que começa em 0) armazena o CRC do endereço. Um byte pode assumir 256 valores distintos, então não é assim tão comum termos sensores com o mesmo CRC.

Como curiosidade, podemos comparar a probabilidade de um mesmo CRC para mais de um sensor com o conceito de colisão em hashes(como MD5). Apenas para exemplificar, a probabilidade de ter um sensor com o CRC repetido no meu caso(5 sensores) é de 4%. Caso eu estivesse utilizando 20 sensores, a probabilidade subiria para 53%.

Link para um calculadora de probabilidade de colisões aqui.

É, pensando bem essa não foi das minhas melhores ideias.

Continuando…

Bem, continuando, reparem que no case default nós imprimimos o endereço completo do sensor. Em resumo, quando eu conectar um sensor pela primeira vez, ele vai sempre imprimir o endereço completo, então eu pego o último byte(valor do CRC) e atualizo o código com esse valor. Ah, claro que temos que colocar alguma identificação correspondente no sensor físico.

Entendido? Espero que tenham entendido essa parte, pois há chance de terem problemas (CRC duplicado).

Considerações quanto a distância e quantidade de sensores.

Vou resumir um pouco o excelente documento técnico da Maxin relativo a distâncias e topologia utilizada. O documento original pode ser consultado clicando aqui.

O protocolo One-Wire(ou 1-Wire) foi projeto para comunicação a curtas distâncias com dispositivos próximos, mas com o passar do tempo foi evoluindo e permitindo uma grande aumento na distância entre os componentes, além do aumento no número de dispositivos.

Determinar qual a máxima distância e o número máximo de dispositivos não é tarefa exatamente simples, pois envolve muito fatores técnicos como o cabeamento utilizado, interferências externas, a potência do dispositivo atuando como master, a topologia utilizada, etc. Vamos ver alguns fatores relativos a topologia.

Topologia utilizada.

A topologia em uma rede One-Wire é importante na definição de dois conceitos muito importantes na determinação da máxima distância e máximo de dispositivos: raio e peso.

  • Raio (ou radius): é a distância em metros entre o master e o slave mais distante. Se tivermos 3 dispositivos slave, um a 4 metros de distância, outro a 10 metros e o último a 21 metros, o raio da nossa rede será de 21 metros.
  • Peso (ou weight): é a soma da distância de todos os slaves para o master. No exemplo acima, o peso da nossa rede seria de 35 metros (4+10+11).

Técnicamente o raio influi na temporização(reflexão do sinal) enquanto o peso influi nas mudanças de estado do sinal (alto para baixo, ou +5v para 0v).

No exemplo deste post temos um raio de 22 metros(21 do cabo UTP mais 1 metro do sensor propriamente) e um peso de 110 metros (22m * 5 DS18B20).

Topologia Linear

DS18B20 Linear Topology

One-Wire Linear Topology

Temos basicamente todos os dispositivos conectados ao mesmo cabeamento(GND, +5v e Sinal), com a importante observação de que cada dispositivo esteja a menos de 3 metros do cabeamento.

Topologia “Stubbed”

DS18B20 Stubbed Network

One-Wire Stubbed Topology

Esta topologia é muito similar a linear, com a exceção de que os dispositivos slave estão a mais de 3 metros do cabeamento utilizado.

Topologia em estrela

DS18B20 Star Topology

One-Wire Star Topology

Nesta topologia temos uma divisão perto do master do cabeamento utilizado, seguindo diferentes direções. Cada “direção” pode ter vários dispositivos conectados.

Topologia Comutada

DS18B20 Switched Topology

One-Wire Switched Topology

A topologia comutada não é exatamente um novo layout de conexões, e sim um modo de ultrapassar os limites impostos pelo raio e peso de uma rede. O objetivo de uma rede comutada é dividir logicamente a rede em porções menores, ativando o segmento que desejamos efetuar a leitura em determinado momento.

Limitação na prática.

Seguindo a documentação e conforme o layout escolhido, podemos ver que o máximo de sensores e a máxima distância estão relacionados. Pelas considerações com relação ao raio, podemos ter um dispositivo conectado a algo próximo de 750 metros. Já com relação ao peso, podemos ter algo em torno de 500 metros. Isso nos dá, na prática, a possibilidade de termos UM slave a uma distancia de 500 metros do master.

Indo para o exemplo deste post, veja que estamos dentro dos limites impostos pelo raio e peso. O raio é 22 metros, enquanto o peso é 110 metros. Poderíamos adicionar mais um sensor a 390 metros de distância, totalizando os 500 metros do peso, ou poderíamos adicionar outros 40 sensores com a mesma distância de 11 metros, totalizando 495 metros de peso(45*11).

OK. E onde raios pretende utilizar isso?

Sem entrar em detalhes por enquanto, mas estes sensores serão utilizados para medição de eficiência de um aquecedor solar caseiro. Pelo código podem notar que os sensores serão utilizados da seguinte forma:

  • amb01 –> Medição da temperatura ambiente
  • cxA01  –> Medição da temperatura da caixa A. 01 medirá a temperatura de fundo
  • cxA02 –> Medição da temperatura da caixa A. 02 medira a temperatura de superfície
  • cxB01  –> Medição da temperatura da caixa B. 01 medirá a temperatura de fundo
  • cxB02 –> Medição da temperatura da caixa B. 02 medira a temperatura de superfície

Os sensores já estão posicionados e medindo corretamente. Na primeira fase preciso ainda armazenar os dados(temperaturas) no emonCMS. Numa segunda fase instalarei o aquecedor e então monitorar sua eficiência.

Logo venho dar mais detalhes e informar os resultados obtidos.

Deixe uma resposta

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

três + 15 =