PIC Projects

Digital thermometer with digital 1-Wire interface sensor

First attempt

This thermometer is much more stable than the one with analog interface. It can display temperatures in the range -55°C - 125°C (-58°F - 257°F). This is accomplished by a digital sensor DS1822 with a 1-Wire interface manufactured by Dallas Semiconductor (now a part of Maxim). This sensor contains a pretty decent electronics including ADC, several registers for storing temp and alarm values, CRC codes, configuration bits, etc. It provides a 12-bit temperature resolution of 0.0625°C, which enables to reliably display temperatures with one decimal digit.

Schematic Temp in °C Temp in °F

The circuit is very much simplified, I still do not have a proper decoder handy to simplify the LED interface. Moving a lot of functionality to the sensor weakens the PIC requirements. One does not need to have a DAC, just mush have enough output pins. By using PIC16F628 (with 12 I/O pins) one could further simplify the circuit by eliminating 74HC138 decoder.

The sensor stores temperatures in a 12-bit 2's complement representation internally. To retrieve them one should implement the 1-Wire interface designed by Dallas Semiconductor (nowdays a part of Maxim). This interface supports asynchronous data exchange between devices by using just 1 wire (and the ground). The interface puts strict requirements on signals, which is very good documented in the device specifications available for download from the manufacturer's web site.

The sensor is really stable, and this eliminated a need in the sliding average technique which I used with an analog sensor. In this sense the software is simplified. At the first reading the sensor returns +85.0C and this is what is displayed on the LED for a couple of seconds. To get rid of this one should request temp conversion and wait for about 750msec for it to be ready. Most of the embedded code is intended for formatting the temp values and displaying them properly. The code contains several procedures that implement 16-bit fixed point arithmetic on a 8-bit CPU. Positive temperatures are displayed with one digit after the decimal point unless it is a 3-digit value. In the last case no decimal digits are displayed because there is no place for them on a 4-digit LCD. Negative temp values are preceeded by the minus sign in the leftmost digit. Negative double-digit values are displayed without a decimal digit, while one-digit values are shown with one decimal digit. This rule is valid for both Celsius and Fahrenheit scales. The sensor provides measurements in Celsius. To convert them into Fahrenheit we use a divide-and-conquer division algorithm that implements a 16-bit division by using three 8-bit divisions. The last ones are implemented by using a 256-byte table stored in the EEPROM memory (hence, 256 bytes of EEPROM are required to be present in PIC).

Download the complete source code here.

Each digit on the LED display is on for 4 milliseconds provided by the main loop of the code. The temperature is monitored every 4 seconds. Each time a new temp value is read one experiences a slight flickering of the display. This is because the 1-Eire interface is SLOW. It takes about 0.9msec to initialize the data exchange and to get two bytes from the sensor requires totally about 3msec and the temp conversion within the server takes 750msec max. This time is compatible with the LED display digit activity. As soon as the sensor data is ready, an interrupt in the PIC leads to reading it. Another interrupt function is to initiate the temp conversion every 4sec. I tried also to put the LED digits scrolling on an interrupt controlled by TMR0 overflow every 4msec, but this did not help much to get rid of flickering. Maybe a more clever implementation would make it possible. A slight display flickering every 4 seconds is not necessarily a disadvantage - it might be seen as sign that the device is up and running.

Second attempt

As I slept over with the idea of the first design, it occurred to me how to improve the code and get rid of flickering. There are several processes involved into the device functionality: displaying a single digit on the LED, requesting a new temp conversion form the DS1822 sensor, reading the temp from sensor as it becomes available and converting it into BCD, and monitoring the C/F button press and switch to the other temp scale, respectively. These events could be better organized, but first we consider them in detail.

Throwing a new digit to the LCD is a very fast procedure that takes at most 40μsec in the current implementation. This should be repeated every 4msec. Thus, on a 4msec cycle just 1% of that cycle is used for the digit processing.

Sending a request to the sensor by using a 1-Wire interface starts with an initialization procedure that takes about 1msec. After that a ROM command must be send (0.5msec) following by the function command (start new temp conversion), which also takes about 0.5msec. Reading the temp from sensor follows the same pattern at the beginning (1 + 2· 0.5msec) ending with receiving two bytes for the temp (another 2· 0.5msec).

Checking the button status takes about 10μsec. I programmed all these events as single interrupt that is initiated every 4msec and whose main task is to switch to displaying another digit on the LCD. Thus, the time is divided now into windows of 4msec length. I count these events and as soon the counter reaches the value 1024 (represented as a 16-bit integer) then 4sec have been passed and it is time to request a new temp conversion from sensor. I send the request within the same time window right after completing the LED business. Sending a request takes about 2 msec, so this task is completed within the same window frame before the next interrupt. I raise a flag indicating that a new request is sent and one should wait for the end of the temp conversion in sensor. I just check the DQ line status within each window frame and as soon as gets to the high state, I read the temp value. This takes about 3msec, so this task can be also completed within one window frame.

The updated code can be downloaded here and the HEX file here. I fixed some bugs in the above code resulting in an incorrect conversion of C into F for negative temperatures.

I also decided to finally simplify the schematic and get rid of the decoder and four PNP transistors. This caused a necessity to use another PIC with more I/O pins (13 are needed). The simplest one I had that satisfies the pin count requirement (PIC16F628) is equipped with only 128 byte EEPROM while 256 are needed. So another modification in the code is storing the read-only C/F conversion table in the flash memory instead of EEPROM. The code starts with an initialization and then falls into an infinite loop. The rest is done by the interrupt that calls necessary subroutines within each window frame.

Schematic Temp in °C Temp in °F

The flickering is completely gone now. The device works very good and I think on assembling it on a PCB.


Last modified:Mon, Jan 23, 2023.

04757