The DS18B20 digital temperature sensor
We shall investigate the Maxim 1-wire data bus by using the Dallas Semiconductor DS18B20 digital temperature sensor, which comes in a 3-terminal TO-92 package. The DS18B20 measures temperatures from -55°C to +125°C, and is accurate to 0.5° from -10° to +85°. As you look at the flat side of the package, the GND pin is on the left, the VDD pin on the right, and the DQ (data) pin is in the middle. VDD is between 3.0 and 5.5 V, and the current drain is very small, only a few mA when active and 1 μA when standing by.
It can be powered through the DQ connection when the bus master applies a strong pullup to DQ and VDD is connected to GND. We shall not use this feature.
A Maxim iButton is an integrated circuit in a two-part stainless steel protective can. The two parts of the can are the ground and DQ connection, and the integrated circuit is powered (in most cases) through the 1-Wire connection.
The output is sixteenths of a degree as a 2's complement binary number. The upper byte contains the upper 3 data bits and possible sign extension 1's. The lower byte contains 8 data bits.
An alternative method of sensing temperature is to use an analog temperature sensor and an ADC.
The 1-wire bus is an open-drain bus with normally one bus master and any number of slaves, each of which can either release the bus to be pulled up to a 1-state by a 4.7k pullup resistor to VDD, or pull the bus down to a 0-state. There is no problem if multiple devices pull down the bus. More than one master could be used if some way to prevent collisions is provided, but this does not appear to be envisioned.
The bus is an asynchronous bus transmitting individual bits with every transaction controlled by the master. To exchange a bit, the master pulls the bus low for at least 1 μs, which serves as a start bit. Then, the device transmitting the bit releases the bus for a 1-bit, or holds the bus low for about 60 μs, while the device receiving the bit samples the bus about 15 μs from the start to determine whether it is a 1 or a 0. The standard timing is shown in the diagram at the right. The approximate 60 μs length of a time slot gives a speed of 1 000 000/60 = 16 666 or 16 kbps. This is sufficiently fast for transmitting small amounts of data. There is also a fast timing (called Overdrive) for a speedier bus with 142 kbps, but we shall not use it.
The master begins every transaction with a reset frame in which it holds the bus low for 480 μs. Each slave on the bus prepares itself to receive instructions, and signals its presence by pulling the bus low after the master has released the bus. The next step is to identify the slave that will be used, and to have the others stand by. The master may send a match ROM (55h) command byte followed by the 64 bits of the unique code that identifies the desired slave. If there is only one slave, the skip ROM (CCh) command addresses it without using the 64-bit code.
The master can determine the 64-bit codes of all the attached slaves by an iterative search ROM (F0h) bit-by-bit process that is described in AN187 and below. The code of a single attached slave can be read with the read ROM (33h) command. If the codes of each of the slaves is known, then the search ROM procedure is unnecessary and the codes can be programmed in. We shall use only one slave on the bus and the skip ROM command.
Following skip ROM, the slave is ready to receive command bytes. A temperature conversion is triggered with 44h. As long as the conversion is in progress, the slave will respond with 0 in read bit frames initiated by the master, and with 1 when the conversion is complete. Alternatively, one can wait past the conversion time of 750 ms. Then, the command BEh allows the master to read up to 9 bytes from the slave. We only require the first two, which are the low and the high bytes of the temperature. Then a reset frame brings us back to the command mode.
The search algorithm is interesting enough for description here. Refer to AN187 for further details. Each 1-Wire slave device has a unique 64-bit ROM number that identifies it. This number consists of an 8-bit cyclic redundancy check, a 48-bit identification code, and an 8-bit family identifier. The bits are numbered from 1 to 64 (so that 0 can be used as an initial value in a program), with bits 1-8 the family, 9-56 the ID, and 57-64 the CRC.
After the master sends the search ROM command, each slave sends its first ROM number bit when the master makes a read slot. On the second read slot each slave sends the complement of its first ROM number bit. If the first read gives 0 and the second gives 1, then all slaves have a 0 as the first bit. If the first bit gives 1 and the second gives 0, then all have 1 as the first bit. If both reads give zero, then there are both 0's and 1's among the ROM number bits of the slaves. If both reads give 1's, then there is no active slave on the bus, which is an error condition. Following these two reads, the master can send a 0 or a 1, which causes any slave with the contrary ROM number bit to enter a wait state and not participate further. This process of two reads and one write can be repeated, when it will involve the next ROM number bit. Eventually, all the slaves but one are put into wait states when bit 64 is reached, and an 8-byte register ROM_NO will contain all the bits determined in the process.
A binary tree can then be imagined in which every 0,0 read by the master, called a discrepancy, signifies a branch at which either the 0 or 1 direction is taken. We can start by taking the 0 direction in every case, until we reach bit 64 an have the first ID number in ROM_NO, which we can save somewhere. We have also noticed the last bit number at which we have a discrepancy. Now we can repeat the search from the begining by sending search ROM again, and following the same path down to the last bit number we have noticed, using the values in the last ROM_NO. Then we take the opposite branch, and when we reach bit 64 there will be a new ID in ROM_NO that we can save. Again, we have noted the bit number of the last discrepancy on this route (which will be earlier--the last discrepancy changes with every branch). Another iteration can then follow the new path and determine a third ROM_NO. This is repeated until we have indentified all the slaves on the bus.
There are integrated circuits that perform this search algorithm in hardware, but it is not impossible to program. There is a special search ROM command that searches only among slaves in an alarm condition (ECh), and it is also possible to search only one type of device, using the family code.
I used a PIC16F690 with a 4-digit, 7-segment display connected via the SPI interface, as in the humidity sensor project. In fact, I made a system that would display temperature and humidity alternately, since some of the routines are common to both. Three 1-wire routines are required: reset, send a byte, and receive a byte. The MPLAB Stopwatch was very useful for checking the timing. I used PORTC,0 for the DQ connection. The same trick as with the I2C bus of manipulating the TRISC,0 bit to release DQ or to pull it low was used. A #define DQ PORTC,0 will permit a reference to DQ, using bank 1 to control it, and bank 0 to read it.
The subroutines are shown in the figure at the left. IOBYTE, PRES, TCT and BCNT are all given locations in the 70's so we do not have to worry about bank selection for them. To send a byte, put it in W and call owtbyte. To read a byte, call owrbyte and the byte will be in W on return. To trigger a conversion, call reset, then send CC and send 44. Wait about a second, and then call reset, send CC, send BE and read two bytes, storing them in two locations TL and TH.
If bit 7 in TH is set, then the temperature is negative. Note this fact, and then convert the 2's complement negative number to a positive number by complementing it and adding 1. When you add 1, be sure to add any carry to TH. Now proceed as for a positive temperature, but display a "-". Shift the two temperature bytes four places to the right, so that TL now contains a bye with the whole number of degrees. Shift TH right four more places so that the fractional degrees are in the low nibble. Now convert the whole degrees in TL to decimal and display on the first three digits. This conversion proceeds exactly as with the humidity, but the digit values are 128, 64, 32 and so forth. Make a lookup table to convert the fractional degrees (in sixteenths) to decimal, and put this value in the fourth digit. If the temperature is negative, the first digit will be zero, and this can then be replaced by the "-".
The first byte of the ROM code is a cyclic redundancy check. If a CRC is calculated from the following 56 bits, then agreement with this value implies that the ROM code is error-free. Although this does not have to be used in simple applications, it is interesting so we shall discuss it.
The Maxim-Dallas 8-bit CRC is calculated using the linear feedback shift register shown at the right. The bits are presented one by one at the data input, and the register is shifted one place right. When the final bit has been input, the CRC is the byte remaining in the register, with b7 the msb and b0 the lsb. The theory behind this is rather difficult, but is basically working with polynomials with binary numbers as coefficients--that is, 1 or 0. The xor function is the only linear function of two bits. This shift register corresponds to the polynomial x8 + x5 + x4 + 1. It is easy to emulate the shift register in software, although the PIC can only set, clear or test bits, not move them or do operations with them.
AN27 gives A2 as the CRC for the ROM code A2 00 00 00 01 B8 1C 02. 02 is the family code. The subroutine at the left should be called after the ID code has been loaded in the ROM_NO registers. It returns with the CRC in W, and the ROM_NO registers cleared, except for ROM_NO1, which will also contain the original CRC byte (not the one just calculated). Note how bits shifted into C are converted to register data (DZ and B7). The feedback bit is the xor of DZ and B7. If it is zero, 0 is put in bit 7 and the shifted values left alone. If it is one, 1 is loaded into bit 7 and the proper bits are modified by an xor with 1.
If the 8 additional bits in ROM_NO1 are included in the CRC--that is, if all 64 bits are used, then if the CRC is correct the calculated CRC will be 00. The modification to the routine is simple, and the return value will be 00 if everything is all right.
The routine could return with all the ROM_NO registers unchanged, but this would require saving the value of C shifted out for the next shift, and there is no easy way to do this. C would have to be converted to data, and then convertd back to C for each shift.
The data sheet for the DS18B20 is available on the Maxim website. Also download AN126.htm, AN2420 and AN162 which show how to program a microcontroller as a 1-Wire bus master.
Maxim AN187 describes the search algorithm, while AN27 describes the Maxim 8-bit CRC.
The DS2890 is a 100kΩ digital potentiometer with a 1-Wire interface. I have not found a source, however.
Composed by J. B. Calvert
Created 6 August 2010