Digital Thermometer
    This project uses a standard (PDIP) PIC16F684 as well as a standard thermistor. It will tell the temperature between 0 and 140 farenheit. The temperature is displayed on a 3 digit, 7 segment display. This project is actually quite easy to build; the hardest part is calibrating the thermistor...

    Let's start with the bill of goods:


1 x PIC16f684 microcontroller
1 x 14 pin IC socket (so the PIC can be removed to reprogram)
1 x Thermistor (see below)
3 x 2N3906 PNP transistors
1 x .01mF capacitor (any kind)
10 x 100ohm 1/4watt resistors
1 x 3-digit 7 segment display
1 x 3 AAA battery holder with switch.
1 x PCB breadboard
etching chemicals to make board etc. 

    Now onto the schematic (click to enlarge):
Thermometer Schematic
    Starting from left to right on the schematic...

    Because we are limited to 12 I/O pins on the PIC16F684, we must switch between the 3 digits of the display, turning on each digit one at a time very quickly in unison. Each digit takes 7 I/O lines from the PIC (corresponding to each bar of the digit.) If we wanted to power all of these digits directly, we would need a PIC with at least 21 I/O lines. Since we are using a PIC with only 12, we will turn on only 1 digit at a time and use the remaining I/O lines to decide which digit will be on. If we alternate between these at least 50 times a second, they will all appear to be on at the same time. Therefore, if each digit takes 7 I/O lines, we can use an additonal 3 lines to choose which digit we want on at any given time. These digits are selected through the 2N3906 transistors. We use the transistors because the PIC I/O lines are not capable of providing enough current to power the entire digit, so instead, the I/O line simply turns on the transistor which allows the full current of power to enter the digit. Once we have the digit turned on and the current supplied, we then power the appropriate I/O lines to provide current to the 7 segments we want to light up.

    Next is the 7 segment display. You can see that only 7 lines come in from the PIC, and are branched to each of the 3 digits, corresponding to the same input for all 3 digits. It should be obvious that, depending on which transistor is on (thus powering that particular digit) the 7 I/O lines will power the same inputs on each digit. So, basically, we will turn on the first digit, send out a character using the 7 I/O lines that we want displayed, keep it on for 1/50th of a second, then turn that off and turn on the next digit, display that character for 1/50th of a second, and so on...

    Here is a picture of a 3 digit 7 segment display:
.
    Next we come to the resistors. There is one for each I/O line in order to limit the current, as not having resistors would allow a great deal of current running through the 7 segment and could very easily damage it.
    Next is the PIC itself. It is a PIC16F684. It's optimum power requirements are 4.5v to 5.5v, which we are providing. There is a .01 capacitor connected between power and ground in case of voltage spikes (if you chose to hook power up to a wall adapter.)

    Finally I have a thermistor set up in a voltage divider with a 10k resistor. I happened to have this thermistor from another project, but just about any can be used. Because you will be calibrating the temperature yourself, you just need to make sure the thermistor covers the temperature range you would like to display. Here is a picture of the thermistor I am using:
    Here is a picture of the EaglePCB board layout for the thermometer as well as the PCB artwork if you would like to make your own board. These can be dowloaded at the end of this article. I've set it up in an aesthetical way, with resitors on both sides of the IC. The red lines are jumpers that will have to be made after making the PCB.
    Now on to the code. I used MPLAB v8 and PICC Lite (both free) to make this project. I used a PicKit2 from Microchip to burn it. The source code can be downloaded at the end of this article, but here are a couple things I thought I would mention about the code. First is that I cycle through the three digits, one at a time, and display them for 1/50th of a second:
                if(DisplayPos == 0)                                                                        //Light 1st segment
                {
                        TempDigit = Temperature % 10;                                        //Just get "1"s place
                        RA5 = LEDDigit[TempDigit] >> 6;                                //Turn on digit
                        PORTC = LEDDigit[TempDigit];
                        DIGIT3 = ON;
                        for(D1=0;D1<414;D1++);                                                        //Delay for 7ms
                        
                }else if(DisplayPos == 1)                                                        //Light 2nd segment
                {
                        TempDigit = Temperature % 100;                                //Just get "10"s place (strip off "100"s place)
                        TempDigit = TempDigit / 10;                                        //   and convert to "1"s place
                        RA5 = LEDDigit[TempDigit] >> 6;                                //Turn on digit
                        PORTC = LEDDigit[TempDigit];
                        DIGIT2 = ON;
                        for(D1=0;D1<400;D1++);                                                        //Delay for 7ms
                }else                                                                                                                //Light 3rd segment
                {        
                        TempDigit = Temperature / 100;                                //Just get "100"s place
                        RA5 = LEDDigit[TempDigit] >> 6;                                //Turn on digit
                        PORTC = LEDDigit[TempDigit];
                        DIGIT1 = ON;
                        for(D1=0;D1<400;D1++);                                                        //Delay for 7ms
                }

                DisplayPos = (DisplayPos + 1) % 3;                                //Next segment
    Secondly, I field tested the unit in several different situations to get the correct ratio of ADC voltage (coming in from the Analog to Digital Controller pin from the thermistor.) I got a 29 cents thermometer from a drug store and put it next to the thermometer. I first put it in a normal temperature room. Then the refridgerator, the freezer, outside in the sun...well, you get the idea. Once I had about 6 readings, I could make a deision of what the actual temperature was based on the ADC. In my situation, it was the ADC value minus '82.' Hence the code:
switch(ADCState)
{
case 0:                                                //Start ADC operation
        GODONE = 1;
        ADCState = 1;
        break;
case 1:
        ADCState = 0;
        Temperature = ADRESH - 82;
        break;
}
    If you wanted to know more about how the ADC works, please take a look at the PIC datasheet. It has a very detailed explaination.
   I wanted to be able to turn the power on and off without removing the batteries, so I installed a simple battery holder with an on/off switch built in. I have found these to be life savers, keeping you from having to make your own switch. Here is a picture of the back with the on/off switch on top, as well as a picture with the display on ("60" degrees in this case):
    If you would like to download the schematic, Eagle PCB file, artwork and source code, please click Here.

    To email me any questions or comments, please click Here.