Skip to main content

PIC16F628A + DS1820 + 4-Digit Seven Segment C/F Thermometer

Introduction
This project describes how to read temperature from a DS1820 sensor with a PIC16F628A microcontroller and display the temperature value in a multiplexed 4-digit seven segment display. The temperature will be displayed in both Centigrade and Fahrenheit units switching back and forth. The temperature resolution is 1 degree in both the units. Out of 4-digits, the most significant three digits will display numeric temperature values from 00 to 125. The most significant digit will show '-' for negative temperatures, and the least significant digit will display C or F.

On my PIC16F628A board, connect D1 to RA2, D2 to RA1, D3 to RA0, and D4 to RA3. DS1820 data will be read at RA4 port. The seven segments a-g will be driven by RB0-RB6.

Software

/* Project name:
     Seven-segment display digital thermometer
 * Copyright:
     (c) Rajendra Bhatt, 2010.
      MCU:             PIC16F628A
     Oscillator:      XT, 4.0 MHz
*/

// Temperature digits
unsigned short i, DD0=0x3f, DD1=0x3f,DD2=0x3f, CF_Flag=0xff, CF=0x3f, N_Flag;
// CF_Flag = 0: F, 1: C
// Variable to store temperature register value
unsigned temp_value=0, temp_whole;
unsigned int temp_fraction=0;
float temp_F;

//-------------- Function to Return mask for common cathode 7-seg. display
unsigned short mask(unsigned short num) {
  switch (num) {
    case 0 : return 0x3F;
    case 1 : return 0x06;
    case 2 : return 0x5B;
    case 3 : return 0x4F;
    case 4 : return 0x66;
    case 5 : return 0x6D;
    case 6 : return 0x7D;
    case 7 : return 0x07;
    case 8 : return 0x7F;
    case 9 : return 0x6F;
    case 10 : return 0x40;  // Symbol '-'
    case 11 : return 0x39;   // Symbol C
    case 12 : return 0x71;   // Symbol F
    case 13 : return 0x00;  // Blank
  } //case end
}

void display_temp(short DD0, short DD1, short DD2, short CF)    {
    for (i = 0; i<=200; i++) {
      PORTB = DD0;
      RA0_bit = 1;          // Select Ones Digit
      RA1_bit = 0;
      RA2_bit = 0;
      RA3_bit = 0;
      delay_ms(5);
      PORTB = DD1;
      RA0_bit = 0;
      RA1_bit = 1;        // Select Tens Digit
      RA2_bit = 0;
      RA3_bit = 0;
      delay_ms(5);
      PORTB = DD2;
      RA0_bit = 0;
      RA1_bit = 0;
      RA2_bit = 1;        // Select +/- Digit
      RA3_bit = 0;
      delay_ms(5);
      PORTB = CF;
      RA0_bit = 0;
      RA1_bit = 0;
      RA2_bit = 0 ;
      RA3_bit = 1;        // Select CF Digit
      delay_ms(5);
        }
     return;
}


void main() {
  CMCON  |= 7;      // Disable Comparators
  TRISB = 0x00;    // Set PORTB direction to be output
  PORTB = 0x00;    // Turn OFF LEDs on PORTB
  TRISA0_bit = 0;  // RA.0 to RA3 Output
  TRISA1_bit = 0;
  TRISA2_bit = 0;
  TRISA3_bit = 0;


    //--- main loop
  do {

    N_Flag = 0;  // Reset Temp Flag
    //--- perform temperature reading
    Ow_Reset(&PORTA, 4);      // Onewire reset signal
    Ow_Write(&PORTA, 4, 0xCC);   // Issue command SKIP_ROM
    Ow_Write(&PORTA, 4, 0x44);   // Issue command CONVERT_T
    display_temp(DD0, DD1, DD2,CF)   ;
    Ow_Reset(&PORTA, 4);
    Ow_Write(&PORTA, 4, 0xCC);    // Issue command SKIP_ROM
    Ow_Write(&PORTA, 4, 0xBE);    // Issue command READ_SCRATCHPAD

    // Next Read Temperature
    // Read Byte 0 from Scratchpad
    temp_value =  Ow_Read(&PORTA, 4);
    // Then read Byte 1 from Scratchpad and shift 8 bit left and add the Byte 0
    temp_value = (Ow_Read(&PORTA, 4) << 8) + temp_value;

    if (temp_value & 0x8000) {
     temp_value = ~temp_value + 1;
     N_Flag = 1;   // Temp is -ive
     }
    if (temp_value & 0x0001) temp_value += 1;   // 0.5 round to 1
    temp_value = temp_value >> 1 ;
    if (CF_Flag == 0) {
     if (N_Flag ==1) {
      temp_F = (32.0-9.0*temp_value/5.0)*10 + 6;
      if (temp_F < 0){
         N_Flag=1;
         temp_value = abs(temp_value);
         }
         else N_Flag = 0;
      }
    else temp_F = (9.0*temp_value/5.0+32.0)*10 + 6; //If decimal is greater or equal
                                             // to 0.5, add 0.5
    temp_value = temp_F/10;
    CF = 12;
    }

    if (CF_Flag == 0xff) CF = 11;

    DD0 = temp_value%10;  // Extract Ones Digit
    DD0 = mask(DD0);
    DD1 = (temp_value/10)%10; // Extract Tens Digit
    DD1 = mask(DD1);
    DD2 =  temp_value/100; // Extract Hundred digit
    CF = mask(CF);
    if (N_Flag == 1) DD2=10;
    else if (DD2 == 0) DD2 = 13 ;
    DD2 = mask(DD2) ;

      PORTB=0x00;
      CF_Flag =~CF_Flag;

    } while (1);
}



Output Pictures





Over 99F temperature reading (touched the sensor with a hot soldering iron )

Comments

  1. Perfect mr Raj. I waiting this type of project for a long time.
    Your blog is excellent.
    Very tanks,
    from Brazil.

    ReplyDelete
  2. mr Raj tq for sharing this project.
    did you have a circuit for this project?
    i want know that because i have doing this to my project
    very thank
    from malaysia.

    ReplyDelete
  3. I try to simulate this schematic in Proteus, but in display I have only strange characters :( ... I tried both variant of display, AC and CC ... What could be wrong ? Thanks and regards !

    ReplyDelete
  4. do u have the circuit diagram ti build this project,
    if yes mail me

    theresraj57@gmail.com

    ReplyDelete
  5. Still no answer ... Please, check your mail for schematic. Thanks !

    ReplyDelete
  6. do u have the circuit diagram ti build this project,
    if yes mail me umutozgur@gmail.com

    ReplyDelete
  7. Still not having the schematic for this thermometer :( ... Happy new Year 2016 !

    ReplyDelete
  8. Hello reallynice project. Will you please send the circuit diagram of this project? Thank you...
    s-karaaslan@hotmail.com

    ReplyDelete
  9. Last post on this site is on 2011 ...

    ReplyDelete

Post a Comment

Popular posts from this blog

Contact less tachometer using PIC16F628A

Introduction Tachometer is a device that gives you the information about the rotational speed of any shaft or disc. It usually measures the speed in revolutions per minute (RPM). Today we are going to make a simple tachometer that could measure the rotation speed of a disk without making any physical contact (that's why it is contact less) with the rotating object. The range of this tachometer is 0 - 9999 RPM and displays the RPM on a multiplexed 4-digit seven-segment display. Of course, we are going to do this project on our usual PIC16F628A development board. Infrared sensor Contact-less measurement of RPM will be achieved through an IR sensor. An IR diode will send a beam of infrared towards the rotating disc, and any reflected pulse will be received by a photo diode. The resistance of a photo diode drops drastically when exposed to infrared. An infrared is reflected by a white surface and absorbed by the dark ones. The test disc for this project is shown below. You can see ...

PIC16F628A Development Board

The development board we are going to make for our experimental microcontroller PIC16F628A will look like this. Here are the features it is going to have: Access to all I/O pins through female header pins 4 Push Buttons for Input 4 LEDs for Output An LCD Interface Port A 4-digit Seven-Segment Display Interface LCD Backlight Switch and Contrast Adjustment ICSP Programming (Very Important)

Experiment No. 2 : Push Button and Seven Segment Display Interface

In this experiment, we will program the PIC16F628A as an UP/DOWN Decade Counter. The count value will be displayed on a Seven-Segment Display and will be incremented/decremented by two push buttons on the board. Experimental Setup: The board has built in interface for a multiplexed 4-digit seven segment display (HS-5461AS2 from www.futurlec.com ).We will select only one digit by connecting a Digit Select pin to Vcc, as shown in figure below. A black jumper wire is used for this purpose. The seven segments will be driven through PORTB (already wired on the board). Connect Push Buttons (PB3 and PB4) to RA1 and RA0 female headers using jumper wires.