Digital Thermometer

The thermometer is capable to measure the air temperature in degrees Fahrenheit with resolution of 0.1°F and accuracy provided by the sensor IC of type MCP9003. The temperature readings on display is updated every seconds. The display module is based on MAX6950 controller and is described here.

Schematic Layout

Hardware

The thermometer consists of two main blocks connected to the microcontroller: the sensor and the display module. The sensor uses I2C interface and the display module uses the SPI interface. The pull-up resistor of 4.7K is needed for implementation of the I2C interface with the sensor. Since it works only in slave mode, no pull-up resistor is needed at its SCK pin.

The unit is powered from a 9V external power supply. The 7805 chip converts it into 5V needed for the controller board. The 78033 chip further drops the voltage down to 3.3V needed for the microcontroller. The 47K resistor along with 0.01uF capacitor is needed for keeping the microcontroller in reset during power-up. The remaining capacitors are decoupling ones.

Software

The software starts with setting the interrupt vectors for the reset event and for the Timer_A events. The DATA segment includes a variable temp for storing the temperature which the rest of RAM is used for stack. The MAIN segment starts with standard housekeeping code: setting up stack, turning off the watchdog timer, configuring the ports pins for input or output, enabling the timer interrupts. The timer is clocked from the crystal oscillator and produces timestamp events every 0.5 sec. During the initialization phase we also call init_MAX6950() procedure that displays 0 on display.

After the initialization the program falls into an infinite loop. At each iteration of this loop we first request the temperature conversion from sensor by calling getTemp1(). The sensor is configured to work in 12-bit resolution and one-shot mode. This means that it turns into a sleep mode upon completing the temperature conversion. The conversion takes about 250msec and we read it after 500msec at the nest timestamp event by calling getTemp2(). This way the new data must be ready in the sensor.

The last part of getTemp2() routine converts the temperature from degrees Celsius (the sensor represents the temperature in this scale) into degrees Fahrenheit. The formula is F = (9/5)·C + 32. For our purposes it is more convenient to compute 10·F = 18·C + 320. This way we know for sure that the decimal point must be placed right before the last decimal digit.

Upon converting the temperature into degrees Fahrenheit, we apply the bin2BCD() routine to convert it into the BCD representation. This is needed to fetch the digits of the temperature and forward them into the corresponding registers of MAX6950 for displaying. The conversion is accomplished by using the DAAD instruction, which noticeably simplifies the code.

The rest of the code consists of implementation of the I2C interface routines for communication with the temperature sensor and implementation of SPI routines to communicate with the display module. The CPU is involved into processing for about 250 μs. For the remaining time it is placed into a sleep mode twice per each iteration of the main program loop. The first time it is done right after sending to the sensor a request for a new temperature conversion. For the second time CPU goes into sleep right after sending the data into the display controller. Awaking the CPU from sleep is done by the Timer_A interrupt. The entire interrupt service routine is reduced to modifying the mode bit in stack, so the CPU remains active after completion of the ISR.

To keep this demo code simple I assumed that the temperature is above the freezing point (32°F or 0°C). Processing of negative temperatures still needs to be implemented.

Downloads