Skip to main content

Experiment No. 11: Temperature Data Logger Using PIC16F628A Microcontroller

This project is the combination of the two experiments that we already did in past: Experiment No. 4 and 10. In experiment 4, we demonstrated how to use the mikroC 1-wire library to read temperature data from a digital sensor DS1820, and display the value on a LCD screen. Now we are going to use the hardware UART to transfer the temperature data from the PIC to a PC (Exp. No. 10). The Hyper-Terminal program running on a PC will receive the temperature values and display on screen. The temperature data from the microcontroller will be sent in every 15 sec.

Experimental Setup:

The setup for this experiment is same as the Experiment no. 10 with a DS1820 inserted in its 3-pin female header receiver on the board. The data output of DS1820 is connected to RB.0 (see articles  Exp. No. 4 and 1-Wire Protocol for detail). You need to rebuild the same TTL to RS232 level shifter circuit on a breadboard and set up a hyper-terminal to receive data at 9600 baud rate.



Software:

 /*
 * Project name:
     Temperature Data Logger
    PIC16F628A reads digital temperature data from a DS1820 chip, and
    send it to a PC through RS232 port to display on hyperterminal window.
 * Copyright:
     (c) Rajendra Bhatt, 2009.
*/

// String array to store temperature value to display
char *temp = "000.00";

// Temperature Resolution : No. of bits in temp value = 9
const unsigned short TEMP_RES = 9;

// Variable to store temperature register value
unsigned temp_value;

void Display_Temperature(unsigned int temp2write) {
  const unsigned short RES_SHIFT = TEMP_RES - 8;

  // Variable to store Integer value of temperature
  char temp_whole;

  // Variable to store Fraction value of temperature
  unsigned int temp_fraction;

  // check if temperature is negative
  if (temp2write & 0x8000) {
     temp[0] = '-';
     // Negative temp values are stored in 2's complement form
     temp2write = ~temp2write + 1;
     }

  // Get temp_whole by dividing by 2 (DS1820 9-bit resolution with
  // 0.5 Centigrade step )
  temp_whole = temp2write >> RES_SHIFT ;

  // convert temp_whole to characters
  if (temp_whole/100)
  // 48 is the decimal character code value for displaying 0 on LCD
     temp[0] = temp_whole/100  + 48;
  else
     temp[0] = '0';

  temp[1] = (temp_whole/10)%10 + 48;             // Extract tens digit
  temp[2] =  temp_whole%10     + 48;             // Extract ones digit

  // extract temp_fraction and convert it to unsigned int
  temp_fraction  = temp2write << (4-RES_SHIFT);
  temp_fraction &= 0x000F;
  temp_fraction *= 625;

  // convert temp_fraction to characters
  temp[4] =  temp_fraction/1000    + 48;         // Extract tens digit
  temp[5] = (temp_fraction/100)%10 + 48;         // Extract ones digit

  // Send temperature to RS232
  UART1_Write(10); // Line Feed
  UART1_Write(13); // Carriage Return
  UART1_Write_Text("Temperature= ");
  UART1_Write_Text(temp);

 }

//unsigned char _data = 0x1E;
void main() {
CMCON = 7;       // Disable Comparators
UART1_Init(9600);
Delay_ms(100);
 //--- main loop
  do {
    //--- perform temperature reading
    Ow_Reset(&PORTB, 0);      // Onewire reset signal
    Ow_Write(&PORTB, 0, 0xCC);   // Issue command SKIP_ROM
    Ow_Write(&PORTB, 0, 0x44);   // Issue command CONVERT_T
    Delay_ms(600);
    // If this delay is less than 500ms, you will see the first reading on LCD
    //85C which is (if you remember from my article on DS1820)
    //a power-on-reset value.

    Ow_Reset(&PORTB, 0);
    Ow_Write(&PORTB, 0, 0xCC);    // Issue command SKIP_ROM
    Ow_Write(&PORTB, 0, 0xBE);    // Issue command READ_SCRATCHPAD

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

    //--- Format and display result on Lcd
    Display_Temperature(temp_value);
    Delay_ms(30000);

    } while (1);
}

Output:

Comments

  1. This comment has been removed by the author.

    ReplyDelete
  2. #include

    #define DIGIT1 RA0
    #define DIGIT2 RA1
    #define DIGIT3 RA2
    #define ON 0
    #define OFF 1

    /*
    RA5 - Segment a
    RC5 - Segment b
    RC4 - Segment c
    RC3 - Segment d
    RC2 - Segment e
    RC1 - Segment f
    RC0 - Segment g

    RA4 - Thermistor
    */

    __CONFIG(INTIO & WDTDIS & PWRTEN & MCLRDIS & UNPROTECT \
    & UNPROTECT & BORDIS & IESODIS & FCMDIS);


    const char LEDDigit[10] = {
    0b0000001, // Digit Zero
    0b1001111, // Digit One
    0b0010010, // Digit Two
    0b0000110, // Digit Three
    0b1001100, // Digit Four
    0b0100100, // Digit Five
    0b0100000, // Digit Six
    0b0001111, // Digit Seven
    0b0000000, // Digit Eight
    0b0000100}; // Digit Nine


    int Temperature, TempDigit, DisplayPos, D1, j;
    int ADCState;

    int i, j, d, t, temp;
    main()
    {
    /////////// INIT ////////////

    PORTA = 0;
    PORTC = 0;
    TRISA = 0b010000; // All Bits of PORTA are Outputs except RA4
    TRISC = 0; // All Bits of PORTC are Outputs

    CMCON0 = 7; // Turn off Comparators
    ANSEL = 1 << 4; // RA4 is ADC input
    ADCON0 = 0b00001101; // Left justify, Use Vdd, Channel 4 (AN3), Do not start, Turn on
    ADCON1 = 0b00010000; // run oscillatr as 8 x prescalar

    DisplayPos = 0;
    j = 0;
    Temperature = 0;
    ADCState = 0;


    //// MAIN LOOP ////

    while(1)
    {
    /////////// DISPLAY READOUT ///////////

    DIGIT1 = OFF;
    DIGIT2 = OFF;
    DIGIT3 = OFF;

    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


    j++;
    if(j == 50) //Time to update temp?
    {
    j = 0;

    switch(ADCState)
    {
    case 0: //Start ADC operation
    GODONE = 1;
    ADCState = 1;
    break;
    case 1:
    ADCState = 0;
    Temperature = ADRESH - 82;
    break;
    }
    }
    }
    }

    this the code but i donno how to store data every 30 mins inside internal eeprom. please help me

    ReplyDelete
  3. I have done EEPROM Read/Write in my experiment no. 6. Check this out: http://pic16f628a.blogspot.com/2009/10/experiment-no-6-readwrite-internal.html

    ReplyDelete
  4. This comment has been removed by the author.

    ReplyDelete
  5. Have you worked with PIC microcontrollers before? Let me know what have you got first? Do you have a PIC programmer?

    - MicroGuru
    http://learnpicmicrocontrollers.blogspot.com

    ReplyDelete
  6. This comment has been removed by the author.

    ReplyDelete
  7. I don't have a schematic for just this project. I am doing all these experiments with my tutorial board that built by myself. You can find the circuit for that in one of my articles, "Make your own PIC develpment board". Then in experimental setup section, I describe what additional connections should be made using jumper wires to do a specific experiment. The software is right above in the blog article. It is in C, I am using mikroC compiler.

    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.