Continuamos nosso estudo com o Módulo Tiny RTC I2C, e apresento para vocês a última parte dessa série. Nesta parte 3 vamos analisar o sensor de temperatura DS18B20 que o módulo permite adicionar, usando comunicação 1-Wire. Vamos entender como é feito o protocolo de comunicação e quais suas principais características.
Para quem não acompanhou, podem acessar aqui a parte 1 e parte 2 da nossa série. O Módulo Tiny RTC I2C pode ser encontrado no FILIPEFLOP, assim como os cabos utilizados para a montagem das experiências.
Esta série foi desenvolvida com o hardware oferecido pelo loja FILIPEFLOP, a qual foi fundamental para o desenvolvimento deste projeto, pois sem o auxílio do hardware, o projeto se tornaria inviável.
Comunicação 1-Wire
Muito conhecida e aplicada principalmente nos iButtons, a comunicação 1-Wire (ou One-Wire) foi desenvolvida pela Dallas Semiconductor, posteriormente adquirida pela Maxim Integrated. Trata-se de uma comunicação serial bidirecional assíncrona half-duplex, desenvolvida para que toda a comunicação aconteça com apenas uma única linha de comunicação. Daí o nome 1-Wire.
O formato do Bit
Assim como a comunicação I2C, a comunicação 1-Wire é feita através de um dreno aberto. Isso significa que o bit 0 acontece quando o transistor está fechado, e o bit 1 se dá através de um resistor de pull-up externo ao circuito.
O estado idle da comunicação, ou seja, o estado inativo de comunicação, é mantendo o valor 1 no barramento de comunicação. Cada bit é transmitido em um tempo de exatamente 60µs, iniciado por uma borda de descida. A largura em 0 é que define se a comunicação é um bit 0 ou um bit 1.
De maneira similar, acontece a leitura de um bit. Um sinal de 0 é gerado com largura específica, e o barramento é liberado para que o componente escreva 0 ou 1 dependendo do valor a ser transmitido.
Toda a comunicação 1-Wire é sincronizada com um sinal de reset. Trata-se de um pulso 0 com largura superior a 480µs. Podemos observar esse sinal na imagem abaixo.
Biblioteca 1-Wire
O Arduino já possui uma biblioteca para comunicação 1-Wire. No entanto, ela não está presente nativamente nas bibliotecas do ambiente e precisa ser instalada. Apesar disso, ela pode ser baixada no site oficial do Arduino e instalada facilmente.
O processo é simples, após baixar o OneWire.zip, basta adicioná-lo em seu ambiente. No nosso caso, estamos utilizando a versão 1.6.3 do Arduino.
Após instalar a biblioteca, uma nova lista de exemplos é adicionada. Uma delas é específica para nosso sensor de temperatura, e é dele que vamos partir para desenvolver nosso software.
Bits de comunicação 1-Wire
Ao realizar testes com essa biblioteca, pode-se verificar como é formado o bit 0 e 1 que verificamos na carta de tempo anteriormente. Podemos ver abaixo respectivamente os bits 0 e 1.
Dessa forma, podemos analisar a troca de um byte completo. Verificando a troca do byte 8Ah, percebemos que os primeiros bits transmitidos são os menos significativos. Dessa forma, a seguencia de bits para formar o byte 8Ah será 0101.0001, pois começará do menos significativo.
Sinal de Reset
Também verificamos o sinal de Reset gerado pela biblioteca. Como verificamos na carta de tempo, é um sinal bastante largo. Após seu envio, um pulso de resposta de um dos componentes ligados a este barramento pode ser verificado.
Sensor de Temperatura DS18B20 via 1-Wire
Nosso sensor de temperatura se apresenta em um encapsulamento TO-92. É fácil confundi-lo com um BC548, mas sua pinagem de nada tem a ver com um transistor. Trata-se de um circuito integrado inteiro em apenas três pinos.
Nosso Módulo Tiny RTC I2C possui um espaço específico para esse sensor nesse encapsulamento, fornecendo acesso ao barramento de comunicação 1-Wire no pino DS em ambos os conectores (P1.6 e P2.5). É possível verificar essa conexão no esquemático do módulo.
Verificamos também que o módulo já possui o resistor de pull-up R1, de valor 3K3Ω, montado. Dessa forma, basta apenas a conexão do terminal de acesso com o Arduino.
O sensor pode trabalhar com diferentes tamanhos de palavra. Isso significa que a precisão da medida pode variar de acordo com a necessidade do sistema. No entanto, a velocidade de conversão também está ligada com o número de bits, de forma que a velocidade de conversão também varia. Podemos verificar as possibilidades conforme a tabela abaixo:
| N° de Bits | Tempo de Conversão | Precisão da Medida |
| 9 | 93,75ms | 0,5°C |
| 10 | 187,5ms | 0,25°C |
| 11 | 375ms | 0,125°C |
| 12 | 750ms | 0,0625°C |
Para verificar o funcionamento do sistema, vamos executar o exemplo presente na biblioteca que instalamos logo antes. Esse exemplo (DS18x20_Temperature) faz a leitura dos módulos 1-Wire presentes no sistema e executa a medida de temperatura.
#include <OneWire.h>
// OneWire DS18S20, DS18B20, DS1822 Temperature Example
//
// https://www.pjrc.com/teensy/td_libs_OneWire.html
//
// The DallasTemperature library can do all this work for you!
// https://milesburton.com/Dallas_Temperature_Control_Library
OneWire ds(10); // 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, 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");
}
A montagem realizada foi bastante simples, fazendo uso do pino 10 do Arduino, conforme indicado no software. Além da alimentação (Vcc + GND), apenas 1 pino de dados é necessário nessa comunicação 1-Wire.
Ao executar o exemplo DS18x20_Temperature da biblioteca, temos o seguinte resultado no terminal:
Para compreender o resultado, vamos analisar o campo Data que foi trocado na comunicação. Essa transferência de dados teve os seguintes resultados.
| Temp LSB | Temp MSB | Th | Tl | Conf. Register | Res. | Res. | Res. | CRC |
| A2 | 01 | 4B | 46 | 7F | FF | 0E | 10 | D8 |
Temperatura
A temperatura é dada por alguns bits de sinal e um valor em ponto fixo. Sua estrutura possui sempre 16 bits, embora sejam utilizados até 12. O excedente mais significativo será o sinal, sendo 0 para positivo e 1 para negativo.
| 15 | 14 | 13 | 12 | 11 | 10 | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
| S | S | S | S | S | 26 | 25 | 24 | 23 | 22 | 21 | 20 | 2-1 | 2-2 | 2-3 | 2-4 |
A partir dessa informação, podemos calcular que nosso valor 01.A2h, representado pelo valor 0000.0001.1010.0010b. Sabemos que os 5 primeiros bits serão idênticos e representam o sinal, neste caso positivo. Dessa forma, nossa informação de temperatura está nos bits 001.1010.0010b.
| 0*26 | = 0*64 | = 0 |
| 0*25 | = 0*32 | = 0 |
| 1*24 | = 1*16 | = 16 |
| 1*23 | = 1*8 | = 8 |
| 0*22 | = 0*4 | = 0 |
| 1*21 | = 1*2 | = 2 |
| 0*20 | = 0*1 | = 0 |
| 0*2-1 | = 0*0,5 | = 0 |
| 0*2-2 | = 0*0,25 | = 0 |
| 1*2-3 | = 0*0,125 | = 0,125 |
| 0*2-4 | = 0*0,0625 | = 0 |
A soma de todos os valores, no caso 16+8+2+0,125, dão o resultado da temperatura. O valor de 26,125°C condiz com o valor de 26,12°C verificado no resultado do teste.
Série “Módulo Tiny RTC I2C”
– Módulo Tiny RTC I2C – Parte 1
– Módulo Tiny RTC I2C – Parte 2
Referências
[1] Maxim-IC – DS18B20 [2] Atmel – AT24C32 [3] Wikipedia – 1-Wire [4] Maxim ICFigura 1 – Fonte: Maxim IC – 1-Wire Comunication
Figura 2 – Fonte: Maxim-IC – DS18B20
Figura 3 – Fonte: Maxim-IC – DS18B20
Figura 4 – Fonte: Maxim-IC – DS18B20
Crédito da Imagem Destacada: Módulo Tiny RTC I2C – FILIPEFLOP










Muito bacana o projeto,
Eu consigo ligar vários arduinos entre si, nos quais eles consigam fazer leituras de variáveis diferentes e enviem esses dados para um arduino mestre?
Muito obrigado.
Abraço!
Muito legal a serie de posts.
Qual é esse software que exibe as formas de onda?
Olá Henrique,
Está falando das figuras 7 a 10? Se forem elas, eu usei um analisador lógico da Saleae. É muito bom e muito prático, um dia faço um artigo só sobre ele.
Uma braço.